1
0
Fork 0
libreoffice/cui/source/dialogs/MacroManagerDialog.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

2520 lines
102 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <MacroManagerDialog.hxx>
#include <bitmaps.hlst>
#include <cfgutil.hxx>
#include <dialmgr.hxx>
#include <scriptdlg.hxx>
#include <strings.hrc>
#include <basctl/basctldllpublic.hxx>
#include <basctl/sbxitem.hxx>
#include <basctl/scriptdocument.hxx>
#include <basic/basmgr.hxx>
#include <comphelper/SetFlagContextHelper.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx>
#include <osl/file.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/inputdlg.hxx>
#include <sfx2/minfitem.hxx>
#include <sfx2/request.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/viewfrm.hxx>
#include <svl/itemset.hxx>
#include <svl/stritem.hxx>
#include <svtools/imagemgr.hxx>
#include <svx/passwd.hxx>
#include <tools/urlobj.hxx>
#include <unotools/viewoptions.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/weldutils.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>
#include <com/sun/star/document/XScriptInvocationContext.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/script/browse/XBrowseNode.hpp>
#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
#include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
#include <com/sun/star/script/XLibraryContainer2.hpp>
#include <com/sun/star/script/XLibraryContainerPassword.hpp>
#include <com/sun/star/script/XPersistentLibraryContainer.hpp>
#include <com/sun/star/script/XInvocation.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
ScriptsListBox::ScriptsListBox(std::unique_ptr<weld::TreeView> xTreeView)
: m_xTreeView(std::move(xTreeView))
, m_xScratchIter(m_xTreeView->make_iterator())
{
m_xTreeView->make_sorted();
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35,
m_xTreeView->get_height_rows(9));
m_xTreeView->connect_query_tooltip(LINK(this, ScriptsListBox, QueryTooltip));
}
ScriptsListBox::~ScriptsListBox() { ClearAll(); }
void ScriptsListBox::ClearAll()
{
sal_uInt16 nCount = aArr.size();
for (sal_uInt16 i = 0; i < nCount; ++i)
{
ScriptInfo* pScriptInfo = aArr[i].get();
if (pScriptInfo && pScriptInfo->pBrowseNode)
pScriptInfo->pBrowseNode->release();
}
aArr.clear();
m_xTreeView->clear();
}
void ScriptsListBox::Remove(const weld::TreeIter& rEntry)
{
ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(m_xTreeView->get_id(rEntry));
if (pScriptInfo)
{
if (pScriptInfo->pBrowseNode)
pScriptInfo->pBrowseNode->release();
for (auto it = aArr.begin(); it != aArr.end(); ++it)
{
if ((*it).get() == pScriptInfo)
{
aArr.erase(it);
break;
}
}
}
m_xTreeView->remove(rEntry);
}
OUString ScriptsListBox::GetDescriptionText(const OUString& rId)
{
ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rId);
if (pScriptInfo)
{
return pScriptInfo->sDescription;
}
return OUString();
}
OUString ScriptsListBox::GetSelectedScriptName()
{
std::unique_ptr<weld::TreeIter> xScriptsEntryIter = m_xTreeView->make_iterator();
if (!m_xTreeView->get_selected(xScriptsEntryIter.get()))
return OUString();
return m_xTreeView->get_text(*xScriptsEntryIter);
}
IMPL_LINK(ScriptsListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString)
{
return GetDescriptionText(m_xTreeView->get_id(rEntryIter));
}
ScriptContainersListBox::ScriptContainersListBox(std::unique_ptr<weld::TreeView> xTreeView,
MacroManagerDialog* pMacroManagerDialog)
: m_pScriptsListBox(nullptr)
, m_xTreeView(std::move(xTreeView))
, m_pMacroManagerDialog(pMacroManagerDialog)
{
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35,
m_xTreeView->get_height_rows(9));
m_xTreeView->connect_expanding(LINK(this, ScriptContainersListBox, ExpandingHdl));
m_xTreeView->connect_query_tooltip(LINK(this, ScriptContainersListBox, QueryTooltip));
}
ScriptContainersListBox::~ScriptContainersListBox() { ClearAll(); }
void ScriptContainersListBox::ClearAll()
{
sal_uInt16 nCount = m_xTreeView->n_children();
for (sal_uInt16 i = 0; i < nCount; ++i)
{
ScriptContainerInfo* pScriptContainerInfo
= weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(i));
if (pScriptContainerInfo)
{
if (pScriptContainerInfo->pBrowseNode)
pScriptContainerInfo->pBrowseNode->release();
delete pScriptContainerInfo;
}
}
m_xTreeView->clear();
}
void ScriptContainersListBox::Init(const css::uno::Reference<css::uno::XComponentContext>& xContext,
const css::uno::Reference<css::frame::XFrame>& xFrame)
{
m_xContext = xContext;
m_xFrame = xFrame;
m_xTreeView->freeze();
Fill(nullptr);
m_xTreeView->thaw();
m_xTreeView->set_cursor(0);
}
void ScriptContainersListBox::Remove(const weld::TreeIter* pEntryIter, bool bRemoveEntryIter)
{
// remove all children of pEntryIter
std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter);
if (m_xTreeView->iter_has_child(*pEntryIter) && m_xTreeView->iter_children(*xIter))
{
// set xIter to the last child of pEntryIter
do
{
std::unique_ptr<weld::TreeIter> xChildIter = m_xTreeView->make_iterator(xIter.get());
while (m_xTreeView->iter_next_sibling(*xChildIter))
m_xTreeView->copy_iterator(*xChildIter, *xIter);
} while (m_xTreeView->iter_has_child(*xIter) && m_xTreeView->iter_children(*xIter));
// children must be removed from the tree in reverse order
std::unique_ptr<weld::TreeIter> xRemoveIter = m_xTreeView->make_iterator();
while (m_xTreeView->iter_compare(*xIter, *pEntryIter) != 0)
{
m_xTreeView->copy_iterator(*xIter, *xRemoveIter);
(void)m_xTreeView->iter_previous(*xIter);
ScriptContainerInfo* pScriptContainerInfo
= weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xRemoveIter));
if (pScriptContainerInfo)
{
if (pScriptContainerInfo->pBrowseNode)
pScriptContainerInfo->pBrowseNode->release();
delete pScriptContainerInfo;
}
m_xTreeView->remove(*xRemoveIter);
}
}
// maybe remove the entry
if (bRemoveEntryIter)
{
ScriptContainerInfo* pScriptContainerInfo
= weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter));
if (pScriptContainerInfo)
{
if (pScriptContainerInfo->pBrowseNode)
pScriptContainerInfo->pBrowseNode->release();
delete pScriptContainerInfo;
}
m_xTreeView->remove(*pEntryIter);
}
}
// inspired by CuiConfigGroupListBox::FillScriptList
// cui/source/customize/cfgutil.cxx
void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter)
{
weld::WaitObject aWait(m_pMacroManagerDialog->getDialog());
css::uno::Reference<css::script::browse::XBrowseNode> xNode;
if (pEntryIter == nullptr)
{
ClearAll();
try
{
css::uno::Reference<css::script::browse::XBrowseNodeFactory> xFac
= css::script::browse::theBrowseNodeFactory::get(
comphelper::getProcessComponentContext());
xNode.set(
xFac->createView(css::script::browse::BrowseNodeFactoryViewTypes::MACROORGANIZER));
}
catch (const css::uno::Exception&)
{
TOOLS_WARN_EXCEPTION(
"cui.dialogs", "Caught some exception whilst retrieving browse nodes from factory");
// TODO exception handling
return;
}
}
else
{
ScriptContainerInfo* pScriptContainerInfoEntry
= weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter));
xNode.set(pScriptContainerInfoEntry->pBrowseNode);
Remove(pEntryIter, /*bRemoveEntryIter*/ false);
}
if (xNode->hasChildNodes())
{
// tdf#120362: Don't ask to enable disabled Java when filling script list
css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext());
bool bIsRootNode = false;
OUString user(u"user"_ustr);
OUString share(u"share"_ustr);
OUString uno_packages(u"uno_packages"_ustr);
if (xNode->getName() == "Root")
{
bIsRootNode = true;
}
//To mimic current starbasic behaviour we
//need to make sure that only the current document
//is displayed in the config tree. Tests below
//set the bDisplay flag to FALSE if the current
//node is a first level child of the Root and is NOT
//either the current document, user or share
//
// NOTE: This approach doesn't work for open documents with the same name, for example
// Untitled 1.odt and Untitled 1.ods will both be included as root containers.
OUString currentDocTitle;
if (css::uno::Reference<css::frame::XController> xController = m_xFrame->getController();
xController.is())
{
css::uno::Reference<css::frame::XModel> xModel = xController->getModel();
if (xModel.is())
currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel);
}
const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> children
= xNode->getChildNodes();
for (css::uno::Reference<css::script::browse::XBrowseNode> const& theChild : children)
{
if (!theChild.is())
continue;
if (theChild->getType() == css::script::browse::BrowseNodeTypes::SCRIPT)
// we only want containers in this list box
continue;
if (theChild->getName() == uno_packages)
continue;
OUString uiName = theChild->getName();
if (bIsRootNode)
{
if (uiName == user)
{
uiName = CuiResId(RID_CUISTR_MYMACROS);
}
else if (uiName == share)
{
uiName = CuiResId(RID_CUISTR_PRODMACROS);
}
else if (uiName != currentDocTitle)
{
// as noted above
// NOTE: This approach doesn't work for open documents with the same name, for
// example, Untitled 1.odt and Untitled 1.ods will both be included as root
// containers.
continue;
}
}
// We call acquire on the XBrowseNode so that it does not
// get autodestructed and become invalid when accessed later.
theChild->acquire();
bool bChildOnDemand = false;
if (theChild->hasChildNodes())
{
const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>>
grandchildren = theChild->getChildNodes();
for (const auto& rxNode : grandchildren)
{
if (!rxNode.is())
continue;
if (rxNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER)
{
bChildOnDemand = true;
break;
}
}
}
OUString aImage = CuiConfigGroupListBox::GetImage(theChild, m_xContext, bIsRootNode);
Insert(theChild, pEntryIter, uiName, aImage, bChildOnDemand);
}
}
// add Basic dialogs
if (pEntryIter && m_xTreeView->get_iter_depth(*pEntryIter) == 2) // library
{
// parent node of entry node is a language node
std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter);
m_xTreeView->iter_parent(*xIter); // language
if (m_xTreeView->get_text(*xIter) == "Basic")
{
basctl::ScriptDocument aDocument = GetScriptDocument(pEntryIter);
if (!aDocument.isAlive())
{
return;
}
OUString aLibName = m_xTreeView->get_text(*pEntryIter);
css::uno::Reference<css::script::XLibraryContainer> xDlgLibContainer(
aDocument.getLibraryContainer(basctl::E_DIALOGS));
if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
&& !xDlgLibContainer->isLibraryLoaded(aLibName))
{
xDlgLibContainer->loadLibrary(aLibName);
}
if (!(xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
&& xDlgLibContainer->isLibraryLoaded(aLibName)))
{
return;
}
for (const OUString& rDlgName : aDocument.getObjectNames(basctl::E_DIALOGS, aLibName))
{
Insert(nullptr, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, false);
}
}
}
}
void ScriptContainersListBox::Insert(
const css::uno::Reference<css::script::browse::XBrowseNode>& xInsertNode,
const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage,
bool bChildOnDemand, int nPos, weld::TreeIter* pRet)
{
std::unique_ptr<weld::TreeIter> xNewEntryIter = m_xTreeView->make_iterator();
OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get())));
m_xTreeView->insert(pIter, nPos, &rsUiName, &sId, nullptr, nullptr, bChildOnDemand,
xNewEntryIter.get());
m_xTreeView->set_image(*xNewEntryIter, rsImage);
// set password and linked image only for Basic libraries
if (m_xTreeView->get_iter_depth(*xNewEntryIter) == 2) // library
{
std::unique_ptr<weld::TreeIter> xLanguageIter
= m_xTreeView->make_iterator(xNewEntryIter.get());
m_xTreeView->iter_parent(*xLanguageIter);
if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
{
basctl::ScriptDocument aDocument = GetScriptDocument(xNewEntryIter.get());
if (!aDocument.isAlive())
return;
OUString aLibName = m_xTreeView->get_text(*xNewEntryIter);
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName))
{
css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
xModLibContainer, css::uno::UNO_QUERY);
if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName))
{
// password protected
m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LOCKED);
}
else if (xModLibContainer->isLibraryLink(aLibName))
{
// linked
m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LINKED);
}
}
}
}
if (pRet)
pRet = xNewEntryIter.get();
}
// fills the scripts list box
// inspired by code in void CommandCategoryListBox::addChildren
// cui/source/customize/CommandCategoryListBox.cxx
// and void CuiConfigGroupListBox::GroupSelected()
// cui/source/customize/cfgutil.cxx
void ScriptContainersListBox::ScriptContainerSelected()
{
std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
if (!m_xTreeView->get_selected(xIter.get()))
return;
m_pScriptsListBox->freeze();
m_pScriptsListBox->ClearAll();
if (!m_xTreeView->iter_has_child(*xIter) && !m_xTreeView->get_children_on_demand(*xIter))
{
// maybe the browse node has children and those children are most likely script nodes
ScriptContainerInfo* pScriptContainerInfo
= weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xIter));
css::uno::Reference<css::script::browse::XBrowseNode> xBrowseNode(
pScriptContainerInfo->pBrowseNode);
try
{
if (xBrowseNode->hasChildNodes())
{
const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>>
children = xBrowseNode->getChildNodes();
for (const css::uno::Reference<css::script::browse::XBrowseNode>& childNode :
children)
{
if (!childNode.is())
continue;
if (childNode->getType() == css::script::browse::BrowseNodeTypes::SCRIPT)
{
css::uno::Reference<css::beans::XPropertySet> xPropSet(childNode,
css::uno::UNO_QUERY);
if (!xPropSet.is())
{
continue;
}
OUString sURI;
try
{
css::uno::Any value = xPropSet->getPropertyValue(u"URI"_ustr);
value >>= sURI;
}
catch (css::uno::Exception&)
{
// do nothing, the URI will be empty
}
OUString sDescription;
try
{
css::uno::Any value = xPropSet->getPropertyValue(u"Description"_ustr);
value >>= sDescription;
}
catch (css::uno::Exception&)
{
// do nothing, the description will be empty
}
childNode->acquire();
m_pScriptsListBox->aArr.push_back(
std::make_unique<ScriptInfo>(childNode.get(), sURI, sDescription));
OUString sId(weld::toId(m_pScriptsListBox->aArr.back().get()));
m_pScriptsListBox->append(sId, childNode->getName(), RID_CUIBMP_MACRO);
}
}
}
}
catch (css::uno::RuntimeException&)
{
// do nothing, the entry will not be displayed in the UI
}
}
m_pScriptsListBox->thaw();
if (m_pScriptsListBox->n_children())
m_pScriptsListBox->select(0);
}
OUString ScriptContainersListBox::GetContainerName(const weld::TreeIter& rIter,
const ScriptContainerType eScriptContainerType)
{
weld::TreeView& rScriptContainersTreeView = *m_xTreeView;
std::unique_ptr<weld::TreeIter> xSelectedEntryIter
= rScriptContainersTreeView.make_iterator(&rIter);
std::unique_ptr<weld::TreeIter> xIter
= rScriptContainersTreeView.make_iterator(xSelectedEntryIter.get());
int nEntryDepth;
while ((nEntryDepth = rScriptContainersTreeView.get_iter_depth(*xIter)))
{
if ((nEntryDepth == 3 && eScriptContainerType == ScriptContainerType::MODULEORDIALOG)
|| (nEntryDepth == 2 && eScriptContainerType == ScriptContainerType::LIBRARY)
|| (nEntryDepth == 1 && eScriptContainerType == ScriptContainerType::LANGUAGE))
return rScriptContainersTreeView.get_text(*xIter);
rScriptContainersTreeView.iter_parent(*xIter);
}
if (eScriptContainerType == ScriptContainerType::LOCATION)
return rScriptContainersTreeView.get_text(*xIter);
return OUString();
}
OUString
ScriptContainersListBox::GetSelectedEntryContainerName(ScriptContainerType eScriptContainerType)
{
std::unique_ptr<weld::TreeIter> xSelectedEntryIter = m_xTreeView->make_iterator();
if (!m_xTreeView->get_selected(xSelectedEntryIter.get()))
return OUString(); // should never happen
return GetContainerName(*xSelectedEntryIter, eScriptContainerType);
}
IMPL_LINK(ScriptContainersListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString)
{
// for Basic library check for linked library
if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library
{
// language
std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter);
m_xTreeView->iter_parent(*xLanguageIter);
if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
{
basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter);
if (!aDocument.isAlive())
return OUString();
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
// check for linked library
OUString aLibName = m_xTreeView->get_text(rEntryIter);
if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
&& xModLibContainer->isLibraryLink(aLibName))
{
OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName);
osl::File::getSystemPathFromFileURL(aLinkURL, aLinkURL);
return aLinkURL;
}
}
}
return OUString();
}
IMPL_LINK(ScriptContainersListBox, ExpandingHdl, const weld::TreeIter&, rEntryIter, bool)
{
// for Basic library check for password protected
if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library
{
// language
std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter);
m_xTreeView->iter_parent(*xLanguageIter);
if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
{
basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter);
if (!aDocument.isAlive())
return false; // not expanded
OUString aLibName = m_xTreeView->get_text(rEntryIter);
// check if the library is password protected
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName))
{
css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
xModLibContainer, css::uno::UNO_QUERY);
if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)
&& !xPasswd->isLibraryPasswordVerified(aLibName))
{
// ensure selection before password dialog is shown
m_xTreeView->select(rEntryIter);
OUString sPassword;
if (!basctl::QueryPassword(m_pMacroManagerDialog->getDialog(), xModLibContainer,
aLibName, sPassword, true, true))
{
return false; // indicates the expansion of the row is refused
}
}
}
}
}
if (m_xTreeView->get_children_on_demand(rEntryIter))
{
Fill(&rEntryIter);
}
return true;
}
MacroManagerDialog::MacroManagerDialog(weld::Window* pParent,
const css::uno::Reference<css::frame::XFrame>& xDocFrame)
: GenericDialogController(pParent, u"cui/ui/macromanagerdialog.ui"_ustr,
u"MacroManagerDialog"_ustr)
, m_xDocumentFrame(xDocFrame)
, m_xScriptContainersListBox(
new ScriptContainersListBox(m_xBuilder->weld_tree_view(u"scriptcontainers"_ustr), this))
, m_xScriptsListBox(new ScriptsListBox(m_xBuilder->weld_tree_view(u"scripts"_ustr)))
, m_xScriptContainersListBoxLabel(m_xBuilder->weld_label(u"scriptcontainerlistboxlabel"_ustr))
, m_xScriptsListBoxLabel(m_xBuilder->weld_label(u"scriptslistboxlabel"_ustr))
, m_xRunButton(m_xBuilder->weld_button(u"run"_ustr))
, m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr))
, m_xDescriptionText(m_xBuilder->weld_text_view(u"description"_ustr))
, m_xDescriptionFrame(m_xBuilder->weld_frame(u"descriptionframe"_ustr))
, m_xNewLibraryButton(m_xBuilder->weld_button(u"newlibrary"_ustr))
, m_xNewModuleButton(m_xBuilder->weld_button(u"newmodule"_ustr))
, m_xNewDialogButton(m_xBuilder->weld_button(u"newdialog"_ustr))
, m_xLibraryModuleDialogEditButton(m_xBuilder->weld_button(u"librarymoduledialogedit"_ustr))
, m_xLibraryModuleDialogRenameButton(m_xBuilder->weld_button(u"librarymoduledialogrename"_ustr))
, m_xLibraryModuleDialogDeleteButton(m_xBuilder->weld_button(u"librarymoduledialogdelete"_ustr))
, m_xLibraryPasswordButton(m_xBuilder->weld_button(u"librarypassword"_ustr))
, m_xLibraryImportButton(m_xBuilder->weld_button(u"libraryimport"_ustr))
, m_xLibraryExportButton(m_xBuilder->weld_button(u"libraryexport"_ustr))
, m_xMacroEditButton(m_xBuilder->weld_button(u"macroedit"_ustr))
, m_xMacroDeleteButton(m_xBuilder->weld_button(u"macrodelete"_ustr))
, m_xMacroCreateButton(m_xBuilder->weld_button(u"macrocreate"_ustr))
, m_xMacroRenameButton(m_xBuilder->weld_button(u"macrorename"_ustr))
, m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr))
{
m_aScriptsListBoxLabelBaseStr = m_xScriptsListBoxLabel->get_label();
m_xScriptContainersListBox->SetScriptsListBox(m_xScriptsListBox.get());
m_xScriptContainersListBox->Init(comphelper::getProcessComponentContext(), m_xDocumentFrame);
m_xScriptContainersListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl));
m_xScriptsListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl));
m_xScriptsListBox->connect_row_activated(
LINK(this, MacroManagerDialog, FunctionDoubleClickHdl));
m_xScriptsListBox->connect_popup_menu(LINK(this, MacroManagerDialog, ContextMenuHdl));
m_xAssignButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xRunButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xCloseButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xNewLibraryButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xNewModuleButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xNewDialogButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryModuleDialogEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryModuleDialogRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryModuleDialogDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryPasswordButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryImportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xLibraryExportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xMacroCreateButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xMacroEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xMacroRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
m_xMacroDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
StartListening(*SfxGetpApp());
}
MacroManagerDialog::~MacroManagerDialog() { EndListening(*SfxGetpApp()); }
void MacroManagerDialog::Notify(SfxBroadcaster&, const SfxHint& rHint)
{
if (rHint.GetId() == SfxHintId::ScriptDocumentChanged)
{
weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget();
auto get_path = [&rScriptContainersTreeView](const weld::TreeIter* pIter) {
std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator(pIter);
OUString sPath = rScriptContainersTreeView.get_text(*xIter);
while (rScriptContainersTreeView.iter_parent(*xIter))
sPath = rScriptContainersTreeView.get_text(*xIter) + "|" + sPath;
return sPath;
};
std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator();
// for use to restore the script container tree scroll position
int nOldScrollPos = rScriptContainersTreeView.vadjustment_get_value();
// save the current path of the selection in the script containers list for reselection
// and the selected entry in the scripts list box
OUString sScriptContainersListBoxSelectedEntryPath;
OUString sScriptsListBoxSelectedEntry;
if (rScriptContainersTreeView.get_selected(xIter.get()))
{
sScriptContainersListBoxSelectedEntryPath = get_path(xIter.get());
sScriptsListBoxSelectedEntry = m_xScriptsListBox->GetSelectedScriptName();
}
// create a set containing paths for use to restore the script containers tree expand state
std::unordered_set<OUString> aExpandedSet;
if (!rScriptContainersTreeView.get_iter_first(*xIter)) // no entries?
return;
do
{
if (rScriptContainersTreeView.get_row_expanded(*xIter))
aExpandedSet.insert(get_path(xIter.get()));
} while (rScriptContainersTreeView.iter_next(*xIter));
// fill
rScriptContainersTreeView.freeze();
m_xScriptContainersListBox->Fill(nullptr);
rScriptContainersTreeView.thaw();
// restore script container tree expand state or at least try
if (!rScriptContainersTreeView.get_iter_first(*xIter))
{
UpdateUI();
return;
}
do
{
if (aExpandedSet.erase(get_path(xIter.get())))
rScriptContainersTreeView.expand_row(*xIter);
} while (aExpandedSet.size() && rScriptContainersTreeView.iter_next(*xIter));
// restore the script containers tree scroll position
rScriptContainersTreeView.vadjustment_set_value(nOldScrollPos);
// if possible select the saved scripts container list entry
if (sScriptContainersListBoxSelectedEntryPath.isEmpty())
{
UpdateUI();
return;
}
bool bFound = false;
while (true)
{
if (!rScriptContainersTreeView.get_iter_first(*xIter))
{
UpdateUI();
return;
}
do
{
if (get_path(xIter.get()) == sScriptContainersListBoxSelectedEntryPath)
{
rScriptContainersTreeView.select(*xIter);
bFound = true;
break;
}
} while (rScriptContainersTreeView.iter_next(*xIter));
if (bFound)
break;
// when not found remove the last node from path and try again
auto i = sScriptContainersListBoxSelectedEntryPath.lastIndexOf('|');
if (i == -1)
{
// didn't find
UpdateUI();
return;
}
sScriptContainersListBoxSelectedEntryPath
= sScriptContainersListBoxSelectedEntryPath.copy(0, i);
}
// fill the scripts list box and set label
m_xScriptContainersListBox->ScriptContainerSelected();
m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " "
+ rScriptContainersTreeView.get_text(*xIter));
// reselect the macro in the scripts list box
if (!sScriptsListBoxSelectedEntry.isEmpty())
{
weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget();
xIter = rScriptsTreeView.make_iterator();
if (!rScriptsTreeView.get_iter_first(*xIter))
{
UpdateUI();
return;
}
bool bIsIterValid = true;
while (bIsIterValid
&& rScriptsTreeView.get_text(*xIter) != sScriptsListBoxSelectedEntry)
bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter);
if (bIsIterValid)
{
rScriptsTreeView.scroll_to_row(*xIter);
rScriptsTreeView.select(*xIter);
}
}
UpdateUI();
}
}
IMPL_LINK(MacroManagerDialog, SelectHdl, weld::TreeView&, rTreeView, void)
{
if (&rTreeView == &m_xScriptContainersListBox->get_widget())
{
m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr);
m_xScriptsListBox->ClearAll();
std::unique_ptr<weld::TreeIter> xSelectedEntryIter = rTreeView.make_iterator();
if (!rTreeView.get_selected(xSelectedEntryIter.get()))
{
UpdateUI();
return;
}
auto nSelectedEntryDepth = rTreeView.get_iter_depth(*xSelectedEntryIter);
bool bBasic = m_xScriptContainersListBox->GetContainerName(*xSelectedEntryIter,
ScriptContainerType::LANGUAGE)
== u"Basic"_ustr;
if (nSelectedEntryDepth > 1)
{
if (nSelectedEntryDepth > (!bBasic ? 1 : 2))
{
ScriptContainerInfo* pScriptContainerInfo
= weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(*xSelectedEntryIter));
// pBrowseNode is nullptr for Basic Dialog entries
if (pScriptContainerInfo->pBrowseNode)
{
// fill the scripts list box and set the label
m_xScriptContainersListBox->ScriptContainerSelected();
m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " "
+ rTreeView.get_text(*xSelectedEntryIter));
}
}
}
}
UpdateUI();
}
// IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&, bool)
// cui/source/customize/cfgutil.cxx
IMPL_LINK_NOARG(MacroManagerDialog, FunctionDoubleClickHdl, weld::TreeView&, bool)
{
if (m_xRunButton->get_sensitive())
ClickHdl(*m_xRunButton);
return true;
}
// IMPL_LINK(SvxScriptSelectorDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
// cui/source/customize/cfgutil.cxx
// and
// IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
// basctl/source/basicide/macrodlg.cxx
IMPL_LINK(MacroManagerDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
{
weld::TreeView& xTreeView = m_xScriptsListBox->get_widget();
if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !xTreeView.n_children())
return false;
std::unique_ptr<weld::Builder> xBuilder(
Application::CreateBuilder(&xTreeView, u"modules/BasicIDE/ui/sortmenu.ui"_ustr));
std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu(u"sortmenu"_ustr));
std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu(u"sortsubmenu"_ustr));
xDropMenu->set_active(u"alphabetically"_ustr, xTreeView.get_sort_order());
xDropMenu->set_active(u"properorder"_ustr, !xTreeView.get_sort_order());
OUString sCommand(
xPopup->popup_at_rect(&xTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1))));
if (sCommand == "alphabetically")
{
xTreeView.make_sorted();
}
else if (sCommand == "properorder")
{
xTreeView.make_unsorted();
m_xScriptContainersListBox->ScriptContainerSelected();
}
else if (!sCommand.isEmpty())
{
SAL_WARN("cui.dialogs", "Unknown context menu action: " << sCommand);
}
return true;
}
// same as OUString SvxScriptOrgDialog::getBoolProperty((Reference<beans::XPropertySet> const& xProps, OUString const& propName)
// cui/source/dialogs/scriptdlg.cxx
bool MacroManagerDialog::getBoolProperty(
css::uno::Reference<css::beans::XPropertySet> const& xProps, OUString const& propName)
{
bool result = false;
try
{
xProps->getPropertyValue(propName) >>= result;
}
catch (css::uno::Exception&)
{
return result;
}
return result;
}
css::uno::Reference<css::script::browse::XBrowseNode>
MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter)
{
if (&rTreeView == m_xScriptContainersListBox->m_xTreeView.get())
{
ScriptContainerInfo* pScriptContainerInfo;
pScriptContainerInfo = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(rTreeIter));
if (pScriptContainerInfo)
return pScriptContainerInfo->pBrowseNode;
}
else
{
ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rTreeView.get_id(rTreeIter));
if (pScriptInfo)
return pScriptInfo->pBrowseNode;
}
return nullptr;
}
void MacroManagerDialog::UpdateUI()
{
OUString sDescriptionText
= ScriptsListBox::GetDescriptionText(m_xScriptsListBox->get_selected_id());
weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
if (rTreeView.get_selected(xSelectedIter.get())
&& rTreeView.get_iter_depth(*xSelectedIter) == 2) // library
{
if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE)
== "Basic")
{
basctl::ScriptDocument aDocument
= m_xScriptContainersListBox->GetScriptDocument(xSelectedIter.get());
if (aDocument.isAlive())
{
// if this is a Basic linked library use the link url name for the description string
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
OUString aLibName = rTreeView.get_text(*xSelectedIter);
if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
&& xModLibContainer->isLibraryLink(aLibName))
{
OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName);
OUString aSysPath;
if (osl::File::getSystemPathFromFileURL(aLinkURL, aSysPath)
== osl::FileBase::E_None)
sDescriptionText = aSysPath;
else
sDescriptionText = aLinkURL;
}
}
}
}
m_xDescriptionText->set_text(sDescriptionText);
CheckButtons();
}
void MacroManagerDialog::CheckButtons()
{
bool bSensitiveNewLibraryButton = false;
bool bSensitiveNewModuleButton = false;
bool bSensitiveNewDialogButton = false;
bool bSensitiveLibraryModuleDialogEditButton = false;
bool bSensitiveLibraryModuleDialogRenameButton = false;
bool bSensitiveLibraryModuleDialogDeleteButton = false;
bool bSensitiveLibraryPasswordButton = false;
bool bSensitiveLibraryImportButton = false;
bool bSensitiveLibraryExportButton = false;
bool bSensitiveMacroRunButton = false;
bool bSensitiveMacroCreateButton = false;
bool bSensitiveMacroEditButton = false;
bool bSensitiveMacroRenameButton = false;
bool bSensitiveMacroDeleteButton = false;
bool bSensitiveAssignButton = false;
weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget();
std::unique_ptr<weld::TreeIter> xScriptContainersSelectedIter
= rScriptContainersTreeView.make_iterator();
if (rScriptContainersTreeView.get_selected(xScriptContainersSelectedIter.get()))
{
if (auto nSelectedIterDepth
= rScriptContainersTreeView.get_iter_depth(*xScriptContainersSelectedIter))
{
std::unique_ptr<weld::TreeIter> xLocationContainerIter
= rScriptContainersTreeView.make_iterator(xScriptContainersSelectedIter.get());
while (rScriptContainersTreeView.get_iter_depth(*xLocationContainerIter))
rScriptContainersTreeView.iter_parent(*xLocationContainerIter);
bool bSharedLocationContainer
= getBrowseNode(rScriptContainersTreeView, *xLocationContainerIter)->getName()
== u"share"_ustr;
bool bBasic = m_xScriptContainersListBox->GetSelectedEntryContainerName(
ScriptContainerType::LANGUAGE)
== u"Basic"_ustr;
if (nSelectedIterDepth == 1) // language node
{
if (!bSharedLocationContainer)
{
if (bBasic)
{
bSensitiveNewLibraryButton = true;
bSensitiveLibraryImportButton = true;
}
else
{
css::uno::Reference<css::script::browse::XBrowseNode> node = getBrowseNode(
rScriptContainersTreeView, *xScriptContainersSelectedIter);
if (node.is())
{
css::uno::Reference<css::beans::XPropertySet> xProps(
node, css::uno::UNO_QUERY);
if (xProps.is())
{
if (getBoolProperty(xProps, "Creatable"))
{
bSensitiveNewLibraryButton = true;
}
}
}
}
}
}
else if (bBasic && nSelectedIterDepth == 2) // library node
{
basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument();
if (!aDocument.isAlive())
return;
OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName(
ScriptContainerType::LIBRARY);
css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)
&& !xPasswd->isLibraryPasswordVerified(aLibName))
{
bSensitiveLibraryPasswordButton = true;
}
else if (bSharedLocationContainer)
{
bSensitiveLibraryModuleDialogEditButton = true;
}
else
{
// check, if library is readonly
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
bool bReadOnly = xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
&& xModLibContainer->isLibraryReadOnly(aLibName);
bSensitiveNewModuleButton = !bReadOnly;
bSensitiveNewDialogButton = !bReadOnly;
bSensitiveLibraryModuleDialogEditButton = true;
if (aLibName != u"Standard"_ustr) // need to use a ResId?
{
bSensitiveLibraryModuleDialogRenameButton = !bReadOnly;
bSensitiveLibraryModuleDialogDeleteButton = true; //!bReadOnly;
bSensitiveLibraryPasswordButton = !bReadOnly;
// why not export for "Standard"?
bSensitiveLibraryExportButton = true;
}
}
}
else if (bBasic && nSelectedIterDepth == 3) // module/dialog node
{
if (bSharedLocationContainer)
{
bSensitiveLibraryModuleDialogEditButton = true;
}
else
{
basctl::ScriptDocument aDocument
= m_xScriptContainersListBox->GetScriptDocument();
assert(aDocument.isAlive());
OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName(
ScriptContainerType::LIBRARY);
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
css::uno::Reference<css::script::XLibraryContainer2> xDlgLibContainer(
aDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY);
bool bReadOnly
= (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
&& (xModLibContainer->isLibraryReadOnly(aLibName)
|| xModLibContainer->isLibraryLink(aLibName)))
|| (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
&& (xDlgLibContainer->isLibraryReadOnly(aLibName)
|| xDlgLibContainer->isLibraryLink(aLibName)));
bSensitiveLibraryModuleDialogEditButton = true;
bSensitiveLibraryModuleDialogRenameButton = !bReadOnly;
bSensitiveLibraryModuleDialogDeleteButton = !bReadOnly;
}
}
if (!bSharedLocationContainer && nSelectedIterDepth > 1)
{
css::uno::Reference<css::script::browse::XBrowseNode> node
= getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter);
if (node.is())
{
css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY);
if (xProps.is())
{
if (getBoolProperty(xProps, "Creatable")
&& rScriptContainersTreeView.get_iter_depth(
*xScriptContainersSelectedIter)
== 2) // library entry
{
bSensitiveMacroCreateButton = true;
}
if (getBoolProperty(xProps, "Editable"))
{
bSensitiveLibraryModuleDialogEditButton = true;
}
if (getBoolProperty(xProps, "Deletable"))
{
bSensitiveLibraryModuleDialogDeleteButton = true;
}
if (getBoolProperty(xProps, "Renamable"))
{
bSensitiveLibraryModuleDialogRenameButton = true;
}
}
}
}
// scripts list box state dependant buttons
weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget();
std::unique_ptr<weld::TreeIter> xScriptsSelectedIter = rScriptsTreeView.make_iterator();
if (rScriptsTreeView.n_children()
&& rScriptsTreeView.get_selected(xScriptsSelectedIter.get()))
{
bSensitiveAssignButton = true;
css::uno::Reference<css::script::browse::XBrowseNode> node;
node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter);
if (node.is())
{
bSensitiveMacroRunButton = true;
css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY);
if (xProps.is())
{
if (getBoolProperty(xProps, "Editable"))
{
bSensitiveMacroEditButton = true;
}
if (!bSharedLocationContainer)
{
if (getBoolProperty(xProps, "Deletable"))
{
bSensitiveMacroDeleteButton = true;
}
if (getBoolProperty(xProps, "Renamable"))
{
bSensitiveMacroRenameButton = true;
}
}
}
}
}
}
}
m_xNewLibraryButton->set_sensitive(bSensitiveNewLibraryButton);
m_xNewModuleButton->set_sensitive(bSensitiveNewModuleButton);
m_xNewDialogButton->set_sensitive(bSensitiveNewDialogButton);
m_xLibraryModuleDialogEditButton->set_sensitive(bSensitiveLibraryModuleDialogEditButton);
m_xLibraryModuleDialogRenameButton->set_sensitive(bSensitiveLibraryModuleDialogRenameButton);
m_xLibraryModuleDialogDeleteButton->set_sensitive(bSensitiveLibraryModuleDialogDeleteButton);
m_xLibraryPasswordButton->set_sensitive(bSensitiveLibraryPasswordButton);
m_xLibraryImportButton->set_sensitive(bSensitiveLibraryImportButton);
m_xLibraryExportButton->set_sensitive(bSensitiveLibraryExportButton);
m_xRunButton->set_sensitive(bSensitiveMacroRunButton);
m_xMacroCreateButton->set_sensitive(bSensitiveMacroCreateButton);
m_xMacroEditButton->set_sensitive(bSensitiveMacroEditButton);
m_xMacroRenameButton->set_sensitive(bSensitiveMacroRenameButton);
m_xMacroDeleteButton->set_sensitive(bSensitiveMacroDeleteButton);
m_xAssignButton->set_sensitive(bSensitiveAssignButton);
}
// void createLibImpl(weld::Window* pWin, const ScriptDocument& rDocument,
// weld::TreeView* pLibBox, SbTreeListBox* pBasicBox)
// basctl/source/basicide/moduldl2.cxx
void MacroManagerDialog::BasicScriptsCreateLibrary(const basctl::ScriptDocument& rDocument)
{
// create a unique library name
OUString aLibName = CuiResId(STR_LIBRARY) + OUString::number(1);
for (sal_uInt32 i = 1; rDocument.hasLibrary(basctl::E_SCRIPTS, aLibName)
|| rDocument.hasLibrary(basctl::E_DIALOGS, aLibName);
aLibName = CuiResId(STR_LIBRARY) + OUString::number(++i))
;
InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL));
aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE));
aInputDlg.SetEntryText(aLibName);
aInputDlg.HideHelpBtn();
aInputDlg.setCheckEntry([&](OUString sNewName) {
if (sNewName.isEmpty() || rDocument.hasLibrary(basctl::E_SCRIPTS, sNewName)
|| rDocument.hasLibrary(basctl::E_DIALOGS, sNewName) || sNewName.getLength() > 30
|| !basctl::IsValidSbxName(sNewName))
return false;
return true;
});
if (!aInputDlg.run())
return;
aLibName = aInputDlg.GetEntryText();
try
{
// create library container for modules
rDocument.getOrCreateLibrary(basctl::E_SCRIPTS, aLibName);
// create a module
OUString aModName = rDocument.createObjectName(basctl::E_SCRIPTS, aLibName);
OUString sModuleCode;
if (!rDocument.createModule(aLibName, aModName, true, sModuleCode))
throw css::uno::Exception("could not create module " + aModName, nullptr);
// tdf#151741 - store all libraries to the file system, otherwise they
// cannot be renamed/moved since the SfxLibraryContainer::renameLibrary
// moves the folders/files on the file system
css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
css::uno::Reference<css::script::XPersistentLibraryContainer> xModPersLibContainer(
xModLibContainer, css::uno::UNO_QUERY);
if (xModPersLibContainer.is())
xModPersLibContainer->storeLibraries();
// update Basic IDE object catalog
SbxItem aModuleSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName,
basctl::SBX_TYPE_MODULE);
if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON,
{ &aModuleSbxItem });
}
catch (const css::uno::Exception&)
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
void MacroManagerDialog::BasicScriptsCreateModule(const basctl::ScriptDocument& rDocument)
{
// library name is the selected tree entry
weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
if (!rTreeView.get_selected(xSelectedIter.get()))
return; // should never happen
OUString aLibName = rTreeView.get_text(*xSelectedIter);
// create an unused module name
OUString aModName = CuiResId(STR_MODULE) + OUString::number(1);
for (sal_uInt32 i = 1; rDocument.hasModule(aLibName, aModName);
aModName = CuiResId(STR_MODULE) + OUString::number(++i))
;
InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWMODULELABEL));
aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWMODULETITLE));
aInputDlg.SetEntryText(aModName);
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<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
if (!rTreeView.get_selected(xSelectedIter.get()))
return; // should never happen
OUString aLibName = rTreeView.get_text(*xSelectedIter);
// create an unused 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<css::io::XInputStreamProvider> 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<weld::MessageDialog> 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<weld::TreeIter> 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<ScriptContainerInfo*>(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<css::script::XLibraryContainerPassword> 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<weld::TreeIter> 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<ScriptContainerInfo*>(m_xTreeView->get_id(*xIter));
if (pScriptContainerInfo && pScriptContainerInfo->pBrowseNode)
{
css::uno::Reference<css::script::browse::XBrowseNode> 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<weld::TreeIter> 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<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
if (!rTreeView.get_selected(xSelectedIter.get()))
return; // should never happen
css::uno::Reference<css::script::browse::XBrowseNode> node
= getBrowseNode(rTreeView, *xSelectedIter);
css::uno::Reference<css::script::XInvocation> xInv(node, css::uno::UNO_QUERY);
if (xInv.is())
{
m_xDialog->response(RET_CANCEL);
css::uno::Sequence<css::uno::Any> args(0);
css::uno::Sequence<css::uno::Any> outArgs(0);
css::uno::Sequence<sal_Int16> 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<weld::TreeIter> 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<weld::TreeIter> 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<weld::TreeIter> 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<weld::TreeIter> 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<css::script::XLibraryContainer2> xModLibContainer(
rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
css::uno::Reference<css::script::XLibraryContainer2> 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<weld::MessageDialog> 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<css::script::XLibraryContainerPassword> 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<weld::TreeIter> 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<css::script::XLibraryContainer2> xModLibContainer(
rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
if (xModLibContainer.is() && xModLibContainer->hasByName(sOldName))
xModLibContainer->renameLibrary(sOldName, sNewName);
css::uno::Reference<css::script::XLibraryContainer2> 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<ScriptContainerInfo*>(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<weld::TreeIter> 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<css::script::XLibraryContainer2> xModLibContainer(
rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);
css::uno::Reference<css::script::XLibraryContainer2> 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<ScriptContainerInfo*>(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<weld::TreeIter> 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<css::script::XLibraryContainer> 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<css::script::XLibraryContainerPassword> 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<css::script::browse::XBrowseNode> xBrowseNode
= getBrowseNode(rTreeView, rEntry);
css::uno::Reference<css::script::XInvocation> 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<css::uno::Any> args{ css::uno::Any(aNewName) };
css::uno::Sequence<css::uno::Any> outArgs;
css::uno::Sequence<sal_Int16> 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<ScriptInfo*>(m_xScriptsListBox->get_id(rEntry));
if (pScriptInfo)
{
css::uno::Reference<css::beans::XPropertySet> 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<weld::MessageDialog> 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<css::script::browse::XBrowseNode>& 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<css::uno::Reference<css::script::browse::XBrowseNode>> children
= node->getChildNodes();
for (const css::uno::Reference<css::script::browse::XBrowseNode>& 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<css::script::browse::XBrowseNode> node = getBrowseNode(rTreeView, rEntry);
// ISSUE L10N string & can we center list?
OUString aQuery = CuiResId(RID_CUISTR_DELQUERY) + getListOfChildren(node, 0);
std::unique_ptr<weld::MessageDialog> 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<css::script::XInvocation> xInv(node, css::uno::UNO_QUERY);
if (xInv.is())
{
css::uno::Sequence<css::uno::Any> args(0);
css::uno::Sequence<css::uno::Any> outArgs(0);
css::uno::Sequence<sal_Int16> 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<weld::MessageDialog> 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<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
if (!rTreeView.get_selected(xSelectedIter.get()))
return; // should never happen
css::uno::Reference<css::script::browse::XBrowseNode> aChildNode;
css::uno::Reference<css::script::browse::XBrowseNode> xBrowseNode
= getBrowseNode(rTreeView, *xSelectedIter);
css::uno::Reference<css::script::XInvocation> 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<css::uno::Reference<css::script::browse::XBrowseNode>> 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<css::script::browse::XBrowseNode>& 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<css::script::browse::XBrowseNode>& n : childNodes)
{
if (Concat2View(aUserSuppliedName + extn) == n->getName())
{
bValid = false;
OUString aError = CuiResId(RID_CUISTR_CREATEFAILED)
+ CuiResId(RID_CUISTR_CREATEFAILEDDUP);
std::unique_ptr<weld::MessageDialog> 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<css::uno::Any> args{ css::uno::Any(aNewName) };
css::uno::Sequence<css::uno::Any> outArgs;
css::uno::Sequence<sal_Int16> 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<weld::MessageDialog> 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<weld::TreeIter> xIter = m_xScriptsListBox->make_iterator();
if (m_xScriptsListBox->get_selected(xIter.get()))
{
ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(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<weld::TreeIter> 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<weld::TreeIter> 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: */