/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ScriptsListBox::ScriptsListBox(std::unique_ptr xTreeView) : m_xTreeView(std::move(xTreeView)) , m_xScratchIter(m_xTreeView->make_iterator()) { m_xTreeView->make_sorted(); m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9)); m_xTreeView->connect_query_tooltip(LINK(this, ScriptsListBox, QueryTooltip)); } ScriptsListBox::~ScriptsListBox() { ClearAll(); } void ScriptsListBox::ClearAll() { sal_uInt16 nCount = aArr.size(); for (sal_uInt16 i = 0; i < nCount; ++i) { ScriptInfo* pScriptInfo = aArr[i].get(); if (pScriptInfo && pScriptInfo->pBrowseNode) pScriptInfo->pBrowseNode->release(); } aArr.clear(); m_xTreeView->clear(); } void ScriptsListBox::Remove(const weld::TreeIter& rEntry) { ScriptInfo* pScriptInfo = weld::fromId(m_xTreeView->get_id(rEntry)); if (pScriptInfo) { if (pScriptInfo->pBrowseNode) pScriptInfo->pBrowseNode->release(); for (auto it = aArr.begin(); it != aArr.end(); ++it) { if ((*it).get() == pScriptInfo) { aArr.erase(it); break; } } } m_xTreeView->remove(rEntry); } OUString ScriptsListBox::GetDescriptionText(const OUString& rId) { ScriptInfo* pScriptInfo = weld::fromId(rId); if (pScriptInfo) { return pScriptInfo->sDescription; } return OUString(); } OUString ScriptsListBox::GetSelectedScriptName() { std::unique_ptr xScriptsEntryIter = m_xTreeView->make_iterator(); if (!m_xTreeView->get_selected(xScriptsEntryIter.get())) return OUString(); return m_xTreeView->get_text(*xScriptsEntryIter); } IMPL_LINK(ScriptsListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString) { return GetDescriptionText(m_xTreeView->get_id(rEntryIter)); } ScriptContainersListBox::ScriptContainersListBox(std::unique_ptr xTreeView, MacroManagerDialog* pMacroManagerDialog) : m_pScriptsListBox(nullptr) , m_xTreeView(std::move(xTreeView)) , m_pMacroManagerDialog(pMacroManagerDialog) { m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9)); m_xTreeView->connect_expanding(LINK(this, ScriptContainersListBox, ExpandingHdl)); m_xTreeView->connect_query_tooltip(LINK(this, ScriptContainersListBox, QueryTooltip)); } ScriptContainersListBox::~ScriptContainersListBox() { ClearAll(); } void ScriptContainersListBox::ClearAll() { sal_uInt16 nCount = m_xTreeView->n_children(); for (sal_uInt16 i = 0; i < nCount; ++i) { ScriptContainerInfo* pScriptContainerInfo = weld::fromId(m_xTreeView->get_id(i)); if (pScriptContainerInfo) { if (pScriptContainerInfo->pBrowseNode) pScriptContainerInfo->pBrowseNode->release(); delete pScriptContainerInfo; } } m_xTreeView->clear(); } void ScriptContainersListBox::Init(const css::uno::Reference& xContext, const css::uno::Reference& xFrame) { m_xContext = xContext; m_xFrame = xFrame; m_xTreeView->freeze(); Fill(nullptr); m_xTreeView->thaw(); m_xTreeView->set_cursor(0); } void ScriptContainersListBox::Remove(const weld::TreeIter* pEntryIter, bool bRemoveEntryIter) { // remove all children of pEntryIter std::unique_ptr xIter = m_xTreeView->make_iterator(pEntryIter); if (m_xTreeView->iter_has_child(*pEntryIter) && m_xTreeView->iter_children(*xIter)) { // set xIter to the last child of pEntryIter do { std::unique_ptr xChildIter = m_xTreeView->make_iterator(xIter.get()); while (m_xTreeView->iter_next_sibling(*xChildIter)) m_xTreeView->copy_iterator(*xChildIter, *xIter); } while (m_xTreeView->iter_has_child(*xIter) && m_xTreeView->iter_children(*xIter)); // children must be removed from the tree in reverse order std::unique_ptr xRemoveIter = m_xTreeView->make_iterator(); while (m_xTreeView->iter_compare(*xIter, *pEntryIter) != 0) { m_xTreeView->copy_iterator(*xIter, *xRemoveIter); (void)m_xTreeView->iter_previous(*xIter); ScriptContainerInfo* pScriptContainerInfo = weld::fromId(m_xTreeView->get_id(*xRemoveIter)); if (pScriptContainerInfo) { if (pScriptContainerInfo->pBrowseNode) pScriptContainerInfo->pBrowseNode->release(); delete pScriptContainerInfo; } m_xTreeView->remove(*xRemoveIter); } } // maybe remove the entry if (bRemoveEntryIter) { ScriptContainerInfo* pScriptContainerInfo = weld::fromId(m_xTreeView->get_id(*pEntryIter)); if (pScriptContainerInfo) { if (pScriptContainerInfo->pBrowseNode) pScriptContainerInfo->pBrowseNode->release(); delete pScriptContainerInfo; } m_xTreeView->remove(*pEntryIter); } } // inspired by CuiConfigGroupListBox::FillScriptList // cui/source/customize/cfgutil.cxx void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) { weld::WaitObject aWait(m_pMacroManagerDialog->getDialog()); css::uno::Reference xNode; if (pEntryIter == nullptr) { ClearAll(); try { css::uno::Reference xFac = css::script::browse::theBrowseNodeFactory::get( comphelper::getProcessComponentContext()); xNode.set( xFac->createView(css::script::browse::BrowseNodeFactoryViewTypes::MACROORGANIZER)); } catch (const css::uno::Exception&) { TOOLS_WARN_EXCEPTION( "cui.dialogs", "Caught some exception whilst retrieving browse nodes from factory"); // TODO exception handling return; } } else { ScriptContainerInfo* pScriptContainerInfoEntry = weld::fromId(m_xTreeView->get_id(*pEntryIter)); xNode.set(pScriptContainerInfoEntry->pBrowseNode); Remove(pEntryIter, /*bRemoveEntryIter*/ false); } if (xNode->hasChildNodes()) { // tdf#120362: Don't ask to enable disabled Java when filling script list css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext()); bool bIsRootNode = false; OUString user(u"user"_ustr); OUString share(u"share"_ustr); OUString uno_packages(u"uno_packages"_ustr); if (xNode->getName() == "Root") { bIsRootNode = true; } //To mimic current starbasic behaviour we //need to make sure that only the current document //is displayed in the config tree. Tests below //set the bDisplay flag to FALSE if the current //node is a first level child of the Root and is NOT //either the current document, user or share // // NOTE: This approach doesn't work for open documents with the same name, for example // Untitled 1.odt and Untitled 1.ods will both be included as root containers. OUString currentDocTitle; if (css::uno::Reference xController = m_xFrame->getController(); xController.is()) { css::uno::Reference xModel = xController->getModel(); if (xModel.is()) currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel); } const css::uno::Sequence> children = xNode->getChildNodes(); for (css::uno::Reference const& theChild : children) { if (!theChild.is()) continue; if (theChild->getType() == css::script::browse::BrowseNodeTypes::SCRIPT) // we only want containers in this list box continue; if (theChild->getName() == uno_packages) continue; OUString uiName = theChild->getName(); if (bIsRootNode) { if (uiName == user) { uiName = CuiResId(RID_CUISTR_MYMACROS); } else if (uiName == share) { uiName = CuiResId(RID_CUISTR_PRODMACROS); } else if (uiName != currentDocTitle) { // as noted above // NOTE: This approach doesn't work for open documents with the same name, for // example, Untitled 1.odt and Untitled 1.ods will both be included as root // containers. continue; } } // We call acquire on the XBrowseNode so that it does not // get autodestructed and become invalid when accessed later. theChild->acquire(); bool bChildOnDemand = false; if (theChild->hasChildNodes()) { const css::uno::Sequence> grandchildren = theChild->getChildNodes(); for (const auto& rxNode : grandchildren) { if (!rxNode.is()) continue; if (rxNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER) { bChildOnDemand = true; break; } } } OUString aImage = CuiConfigGroupListBox::GetImage(theChild, m_xContext, bIsRootNode); Insert(theChild, pEntryIter, uiName, aImage, bChildOnDemand); } } // add Basic dialogs if (pEntryIter && m_xTreeView->get_iter_depth(*pEntryIter) == 2) // library { // parent node of entry node is a language node std::unique_ptr xIter = m_xTreeView->make_iterator(pEntryIter); m_xTreeView->iter_parent(*xIter); // language if (m_xTreeView->get_text(*xIter) == "Basic") { basctl::ScriptDocument aDocument = GetScriptDocument(pEntryIter); if (!aDocument.isAlive()) { return; } OUString aLibName = m_xTreeView->get_text(*pEntryIter); css::uno::Reference xDlgLibContainer( aDocument.getLibraryContainer(basctl::E_DIALOGS)); if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) && !xDlgLibContainer->isLibraryLoaded(aLibName)) { xDlgLibContainer->loadLibrary(aLibName); } if (!(xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) && xDlgLibContainer->isLibraryLoaded(aLibName))) { return; } for (const OUString& rDlgName : aDocument.getObjectNames(basctl::E_DIALOGS, aLibName)) { Insert(nullptr, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, false); } } } } void ScriptContainersListBox::Insert( const css::uno::Reference& xInsertNode, const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage, bool bChildOnDemand, int nPos, weld::TreeIter* pRet) { std::unique_ptr xNewEntryIter = m_xTreeView->make_iterator(); OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get()))); m_xTreeView->insert(pIter, nPos, &rsUiName, &sId, nullptr, nullptr, bChildOnDemand, xNewEntryIter.get()); m_xTreeView->set_image(*xNewEntryIter, rsImage); // set password and linked image only for Basic libraries if (m_xTreeView->get_iter_depth(*xNewEntryIter) == 2) // library { std::unique_ptr xLanguageIter = m_xTreeView->make_iterator(xNewEntryIter.get()); m_xTreeView->iter_parent(*xLanguageIter); if (m_xTreeView->get_text(*xLanguageIter) == "Basic") { basctl::ScriptDocument aDocument = GetScriptDocument(xNewEntryIter.get()); if (!aDocument.isAlive()) return; OUString aLibName = m_xTreeView->get_text(*xNewEntryIter); css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) { css::uno::Reference xPasswd( xModLibContainer, css::uno::UNO_QUERY); if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)) { // password protected m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LOCKED); } else if (xModLibContainer->isLibraryLink(aLibName)) { // linked m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LINKED); } } } } if (pRet) pRet = xNewEntryIter.get(); } // fills the scripts list box // inspired by code in void CommandCategoryListBox::addChildren // cui/source/customize/CommandCategoryListBox.cxx // and void CuiConfigGroupListBox::GroupSelected() // cui/source/customize/cfgutil.cxx void ScriptContainersListBox::ScriptContainerSelected() { std::unique_ptr xIter(m_xTreeView->make_iterator()); if (!m_xTreeView->get_selected(xIter.get())) return; m_pScriptsListBox->freeze(); m_pScriptsListBox->ClearAll(); if (!m_xTreeView->iter_has_child(*xIter) && !m_xTreeView->get_children_on_demand(*xIter)) { // maybe the browse node has children and those children are most likely script nodes ScriptContainerInfo* pScriptContainerInfo = weld::fromId(m_xTreeView->get_id(*xIter)); css::uno::Reference xBrowseNode( pScriptContainerInfo->pBrowseNode); try { if (xBrowseNode->hasChildNodes()) { const css::uno::Sequence> children = xBrowseNode->getChildNodes(); for (const css::uno::Reference& childNode : children) { if (!childNode.is()) continue; if (childNode->getType() == css::script::browse::BrowseNodeTypes::SCRIPT) { css::uno::Reference xPropSet(childNode, css::uno::UNO_QUERY); if (!xPropSet.is()) { continue; } OUString sURI; try { css::uno::Any value = xPropSet->getPropertyValue(u"URI"_ustr); value >>= sURI; } catch (css::uno::Exception&) { // do nothing, the URI will be empty } OUString sDescription; try { css::uno::Any value = xPropSet->getPropertyValue(u"Description"_ustr); value >>= sDescription; } catch (css::uno::Exception&) { // do nothing, the description will be empty } childNode->acquire(); m_pScriptsListBox->aArr.push_back( std::make_unique(childNode.get(), sURI, sDescription)); OUString sId(weld::toId(m_pScriptsListBox->aArr.back().get())); m_pScriptsListBox->append(sId, childNode->getName(), RID_CUIBMP_MACRO); } } } } catch (css::uno::RuntimeException&) { // do nothing, the entry will not be displayed in the UI } } m_pScriptsListBox->thaw(); if (m_pScriptsListBox->n_children()) m_pScriptsListBox->select(0); } OUString ScriptContainersListBox::GetContainerName(const weld::TreeIter& rIter, const ScriptContainerType eScriptContainerType) { weld::TreeView& rScriptContainersTreeView = *m_xTreeView; std::unique_ptr xSelectedEntryIter = rScriptContainersTreeView.make_iterator(&rIter); std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(xSelectedEntryIter.get()); int nEntryDepth; while ((nEntryDepth = rScriptContainersTreeView.get_iter_depth(*xIter))) { if ((nEntryDepth == 3 && eScriptContainerType == ScriptContainerType::MODULEORDIALOG) || (nEntryDepth == 2 && eScriptContainerType == ScriptContainerType::LIBRARY) || (nEntryDepth == 1 && eScriptContainerType == ScriptContainerType::LANGUAGE)) return rScriptContainersTreeView.get_text(*xIter); rScriptContainersTreeView.iter_parent(*xIter); } if (eScriptContainerType == ScriptContainerType::LOCATION) return rScriptContainersTreeView.get_text(*xIter); return OUString(); } OUString ScriptContainersListBox::GetSelectedEntryContainerName(ScriptContainerType eScriptContainerType) { std::unique_ptr xSelectedEntryIter = m_xTreeView->make_iterator(); if (!m_xTreeView->get_selected(xSelectedEntryIter.get())) return OUString(); // should never happen return GetContainerName(*xSelectedEntryIter, eScriptContainerType); } IMPL_LINK(ScriptContainersListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString) { // for Basic library check for linked library if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library { // language std::unique_ptr xLanguageIter = m_xTreeView->make_iterator(&rEntryIter); m_xTreeView->iter_parent(*xLanguageIter); if (m_xTreeView->get_text(*xLanguageIter) == "Basic") { basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter); if (!aDocument.isAlive()) return OUString(); css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); // check for linked library OUString aLibName = m_xTreeView->get_text(rEntryIter); if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && xModLibContainer->isLibraryLink(aLibName)) { OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName); 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 xLanguageIter = m_xTreeView->make_iterator(&rEntryIter); m_xTreeView->iter_parent(*xLanguageIter); if (m_xTreeView->get_text(*xLanguageIter) == "Basic") { basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter); if (!aDocument.isAlive()) return false; // not expanded OUString aLibName = m_xTreeView->get_text(rEntryIter); // check if the library is password protected css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) { css::uno::Reference xPasswd( xModLibContainer, css::uno::UNO_QUERY); if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) && !xPasswd->isLibraryPasswordVerified(aLibName)) { // ensure selection before password dialog is shown m_xTreeView->select(rEntryIter); OUString sPassword; if (!basctl::QueryPassword(m_pMacroManagerDialog->getDialog(), xModLibContainer, aLibName, sPassword, true, true)) { return false; // indicates the expansion of the row is refused } } } } } if (m_xTreeView->get_children_on_demand(rEntryIter)) { Fill(&rEntryIter); } return true; } MacroManagerDialog::MacroManagerDialog(weld::Window* pParent, const css::uno::Reference& xDocFrame) : GenericDialogController(pParent, u"cui/ui/macromanagerdialog.ui"_ustr, u"MacroManagerDialog"_ustr) , m_xDocumentFrame(xDocFrame) , m_xScriptContainersListBox( new ScriptContainersListBox(m_xBuilder->weld_tree_view(u"scriptcontainers"_ustr), this)) , m_xScriptsListBox(new ScriptsListBox(m_xBuilder->weld_tree_view(u"scripts"_ustr))) , m_xScriptContainersListBoxLabel(m_xBuilder->weld_label(u"scriptcontainerlistboxlabel"_ustr)) , m_xScriptsListBoxLabel(m_xBuilder->weld_label(u"scriptslistboxlabel"_ustr)) , m_xRunButton(m_xBuilder->weld_button(u"run"_ustr)) , m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr)) , m_xDescriptionText(m_xBuilder->weld_text_view(u"description"_ustr)) , m_xDescriptionFrame(m_xBuilder->weld_frame(u"descriptionframe"_ustr)) , m_xNewLibraryButton(m_xBuilder->weld_button(u"newlibrary"_ustr)) , m_xNewModuleButton(m_xBuilder->weld_button(u"newmodule"_ustr)) , m_xNewDialogButton(m_xBuilder->weld_button(u"newdialog"_ustr)) , m_xLibraryModuleDialogEditButton(m_xBuilder->weld_button(u"librarymoduledialogedit"_ustr)) , m_xLibraryModuleDialogRenameButton(m_xBuilder->weld_button(u"librarymoduledialogrename"_ustr)) , m_xLibraryModuleDialogDeleteButton(m_xBuilder->weld_button(u"librarymoduledialogdelete"_ustr)) , m_xLibraryPasswordButton(m_xBuilder->weld_button(u"librarypassword"_ustr)) , m_xLibraryImportButton(m_xBuilder->weld_button(u"libraryimport"_ustr)) , m_xLibraryExportButton(m_xBuilder->weld_button(u"libraryexport"_ustr)) , m_xMacroEditButton(m_xBuilder->weld_button(u"macroedit"_ustr)) , m_xMacroDeleteButton(m_xBuilder->weld_button(u"macrodelete"_ustr)) , m_xMacroCreateButton(m_xBuilder->weld_button(u"macrocreate"_ustr)) , m_xMacroRenameButton(m_xBuilder->weld_button(u"macrorename"_ustr)) , m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr)) { m_aScriptsListBoxLabelBaseStr = m_xScriptsListBoxLabel->get_label(); m_xScriptContainersListBox->SetScriptsListBox(m_xScriptsListBox.get()); m_xScriptContainersListBox->Init(comphelper::getProcessComponentContext(), m_xDocumentFrame); m_xScriptContainersListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl)); m_xScriptsListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl)); m_xScriptsListBox->connect_row_activated( LINK(this, MacroManagerDialog, FunctionDoubleClickHdl)); m_xScriptsListBox->connect_popup_menu(LINK(this, MacroManagerDialog, ContextMenuHdl)); m_xAssignButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xRunButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xCloseButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xNewLibraryButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xNewModuleButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xNewDialogButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryModuleDialogEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryModuleDialogRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryModuleDialogDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryPasswordButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryImportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xLibraryExportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroCreateButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); m_xMacroDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); StartListening(*SfxGetpApp()); } MacroManagerDialog::~MacroManagerDialog() { EndListening(*SfxGetpApp()); } void MacroManagerDialog::Notify(SfxBroadcaster&, const SfxHint& rHint) { if (rHint.GetId() == SfxHintId::ScriptDocumentChanged) { weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); auto get_path = [&rScriptContainersTreeView](const weld::TreeIter* pIter) { std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(pIter); OUString sPath = rScriptContainersTreeView.get_text(*xIter); while (rScriptContainersTreeView.iter_parent(*xIter)) sPath = rScriptContainersTreeView.get_text(*xIter) + "|" + sPath; return sPath; }; std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(); // for use to restore the script container tree scroll position int nOldScrollPos = rScriptContainersTreeView.vadjustment_get_value(); // save the current path of the selection in the script containers list for reselection // and the selected entry in the scripts list box OUString sScriptContainersListBoxSelectedEntryPath; OUString sScriptsListBoxSelectedEntry; if (rScriptContainersTreeView.get_selected(xIter.get())) { sScriptContainersListBoxSelectedEntryPath = get_path(xIter.get()); sScriptsListBoxSelectedEntry = m_xScriptsListBox->GetSelectedScriptName(); } // create a set containing paths for use to restore the script containers tree expand state std::unordered_set aExpandedSet; if (!rScriptContainersTreeView.get_iter_first(*xIter)) // no entries? return; do { if (rScriptContainersTreeView.get_row_expanded(*xIter)) aExpandedSet.insert(get_path(xIter.get())); } while (rScriptContainersTreeView.iter_next(*xIter)); // fill rScriptContainersTreeView.freeze(); m_xScriptContainersListBox->Fill(nullptr); rScriptContainersTreeView.thaw(); // restore script container tree expand state or at least try if (!rScriptContainersTreeView.get_iter_first(*xIter)) { UpdateUI(); return; } do { if (aExpandedSet.erase(get_path(xIter.get()))) rScriptContainersTreeView.expand_row(*xIter); } while (aExpandedSet.size() && rScriptContainersTreeView.iter_next(*xIter)); // restore the script containers tree scroll position rScriptContainersTreeView.vadjustment_set_value(nOldScrollPos); // if possible select the saved scripts container list entry if (sScriptContainersListBoxSelectedEntryPath.isEmpty()) { UpdateUI(); return; } bool bFound = false; while (true) { if (!rScriptContainersTreeView.get_iter_first(*xIter)) { UpdateUI(); return; } do { if (get_path(xIter.get()) == sScriptContainersListBoxSelectedEntryPath) { rScriptContainersTreeView.select(*xIter); bFound = true; break; } } while (rScriptContainersTreeView.iter_next(*xIter)); if (bFound) break; // when not found remove the last node from path and try again auto i = sScriptContainersListBoxSelectedEntryPath.lastIndexOf('|'); if (i == -1) { // didn't find UpdateUI(); return; } sScriptContainersListBoxSelectedEntryPath = sScriptContainersListBoxSelectedEntryPath.copy(0, i); } // fill the scripts list box and set label m_xScriptContainersListBox->ScriptContainerSelected(); m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + rScriptContainersTreeView.get_text(*xIter)); // reselect the macro in the scripts list box if (!sScriptsListBoxSelectedEntry.isEmpty()) { weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); xIter = rScriptsTreeView.make_iterator(); if (!rScriptsTreeView.get_iter_first(*xIter)) { UpdateUI(); return; } bool bIsIterValid = true; while (bIsIterValid && rScriptsTreeView.get_text(*xIter) != sScriptsListBoxSelectedEntry) bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter); if (bIsIterValid) { rScriptsTreeView.scroll_to_row(*xIter); rScriptsTreeView.select(*xIter); } } UpdateUI(); } } IMPL_LINK(MacroManagerDialog, SelectHdl, weld::TreeView&, rTreeView, void) { if (&rTreeView == &m_xScriptContainersListBox->get_widget()) { m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr); m_xScriptsListBox->ClearAll(); std::unique_ptr xSelectedEntryIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedEntryIter.get())) { UpdateUI(); return; } auto nSelectedEntryDepth = rTreeView.get_iter_depth(*xSelectedEntryIter); bool bBasic = m_xScriptContainersListBox->GetContainerName(*xSelectedEntryIter, ScriptContainerType::LANGUAGE) == u"Basic"_ustr; if (nSelectedEntryDepth > 1) { if (nSelectedEntryDepth > (!bBasic ? 1 : 2)) { ScriptContainerInfo* pScriptContainerInfo = weld::fromId(rTreeView.get_id(*xSelectedEntryIter)); // pBrowseNode is nullptr for Basic Dialog entries if (pScriptContainerInfo->pBrowseNode) { // fill the scripts list box and set the label m_xScriptContainersListBox->ScriptContainerSelected(); m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + rTreeView.get_text(*xSelectedEntryIter)); } } } } UpdateUI(); } // IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&, bool) // cui/source/customize/cfgutil.cxx IMPL_LINK_NOARG(MacroManagerDialog, FunctionDoubleClickHdl, weld::TreeView&, bool) { if (m_xRunButton->get_sensitive()) ClickHdl(*m_xRunButton); return true; } // IMPL_LINK(SvxScriptSelectorDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) // cui/source/customize/cfgutil.cxx // and // IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool) // basctl/source/basicide/macrodlg.cxx IMPL_LINK(MacroManagerDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) { weld::TreeView& xTreeView = m_xScriptsListBox->get_widget(); if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !xTreeView.n_children()) return false; std::unique_ptr xBuilder( Application::CreateBuilder(&xTreeView, u"modules/BasicIDE/ui/sortmenu.ui"_ustr)); std::unique_ptr xPopup(xBuilder->weld_menu(u"sortmenu"_ustr)); std::unique_ptr xDropMenu(xBuilder->weld_menu(u"sortsubmenu"_ustr)); xDropMenu->set_active(u"alphabetically"_ustr, xTreeView.get_sort_order()); xDropMenu->set_active(u"properorder"_ustr, !xTreeView.get_sort_order()); OUString sCommand( xPopup->popup_at_rect(&xTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))); if (sCommand == "alphabetically") { xTreeView.make_sorted(); } else if (sCommand == "properorder") { xTreeView.make_unsorted(); m_xScriptContainersListBox->ScriptContainerSelected(); } else if (!sCommand.isEmpty()) { SAL_WARN("cui.dialogs", "Unknown context menu action: " << sCommand); } return true; } // same as OUString SvxScriptOrgDialog::getBoolProperty((Reference const& xProps, OUString const& propName) // cui/source/dialogs/scriptdlg.cxx bool MacroManagerDialog::getBoolProperty( css::uno::Reference const& xProps, OUString const& propName) { bool result = false; try { xProps->getPropertyValue(propName) >>= result; } catch (css::uno::Exception&) { return result; } return result; } css::uno::Reference MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter) { if (&rTreeView == m_xScriptContainersListBox->m_xTreeView.get()) { ScriptContainerInfo* pScriptContainerInfo; pScriptContainerInfo = weld::fromId(rTreeView.get_id(rTreeIter)); if (pScriptContainerInfo) return pScriptContainerInfo->pBrowseNode; } else { ScriptInfo* pScriptInfo = weld::fromId(rTreeView.get_id(rTreeIter)); if (pScriptInfo) return pScriptInfo->pBrowseNode; } return nullptr; } void MacroManagerDialog::UpdateUI() { OUString sDescriptionText = ScriptsListBox::GetDescriptionText(m_xScriptsListBox->get_selected_id()); weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (rTreeView.get_selected(xSelectedIter.get()) && rTreeView.get_iter_depth(*xSelectedIter) == 2) // library { if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE) == "Basic") { basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(xSelectedIter.get()); if (aDocument.isAlive()) { // if this is a Basic linked library use the link url name for the description string css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); OUString aLibName = rTreeView.get_text(*xSelectedIter); if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && xModLibContainer->isLibraryLink(aLibName)) { 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 xScriptContainersSelectedIter = rScriptContainersTreeView.make_iterator(); if (rScriptContainersTreeView.get_selected(xScriptContainersSelectedIter.get())) { if (auto nSelectedIterDepth = rScriptContainersTreeView.get_iter_depth(*xScriptContainersSelectedIter)) { std::unique_ptr xLocationContainerIter = rScriptContainersTreeView.make_iterator(xScriptContainersSelectedIter.get()); while (rScriptContainersTreeView.get_iter_depth(*xLocationContainerIter)) rScriptContainersTreeView.iter_parent(*xLocationContainerIter); bool bSharedLocationContainer = getBrowseNode(rScriptContainersTreeView, *xLocationContainerIter)->getName() == u"share"_ustr; bool bBasic = m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LANGUAGE) == u"Basic"_ustr; if (nSelectedIterDepth == 1) // language node { if (!bSharedLocationContainer) { if (bBasic) { bSensitiveNewLibraryButton = true; bSensitiveLibraryImportButton = true; } else { css::uno::Reference node = getBrowseNode( rScriptContainersTreeView, *xScriptContainersSelectedIter); if (node.is()) { css::uno::Reference xProps( node, css::uno::UNO_QUERY); if (xProps.is()) { if (getBoolProperty(xProps, "Creatable")) { bSensitiveNewLibraryButton = true; } } } } } } else if (bBasic && nSelectedIterDepth == 2) // library node { basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); if (!aDocument.isAlive()) return; OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY); css::uno::Reference xPasswd( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) && !xPasswd->isLibraryPasswordVerified(aLibName)) { bSensitiveLibraryPasswordButton = true; } else if (bSharedLocationContainer) { bSensitiveLibraryModuleDialogEditButton = true; } else { // check, if library is readonly css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); bool bReadOnly = xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && xModLibContainer->isLibraryReadOnly(aLibName); bSensitiveNewModuleButton = !bReadOnly; bSensitiveNewDialogButton = !bReadOnly; bSensitiveLibraryModuleDialogEditButton = true; if (aLibName != u"Standard"_ustr) // need to use a ResId? { bSensitiveLibraryModuleDialogRenameButton = !bReadOnly; bSensitiveLibraryModuleDialogDeleteButton = true; //!bReadOnly; bSensitiveLibraryPasswordButton = !bReadOnly; // why not export for "Standard"? bSensitiveLibraryExportButton = true; } } } else if (bBasic && nSelectedIterDepth == 3) // module/dialog node { if (bSharedLocationContainer) { bSensitiveLibraryModuleDialogEditButton = true; } else { basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); assert(aDocument.isAlive()); OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY); css::uno::Reference xModLibContainer( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); css::uno::Reference xDlgLibContainer( aDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); bool bReadOnly = (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && (xModLibContainer->isLibraryReadOnly(aLibName) || xModLibContainer->isLibraryLink(aLibName))) || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) && (xDlgLibContainer->isLibraryReadOnly(aLibName) || xDlgLibContainer->isLibraryLink(aLibName))); bSensitiveLibraryModuleDialogEditButton = true; bSensitiveLibraryModuleDialogRenameButton = !bReadOnly; bSensitiveLibraryModuleDialogDeleteButton = !bReadOnly; } } if (!bSharedLocationContainer && nSelectedIterDepth > 1) { css::uno::Reference node = getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter); if (node.is()) { css::uno::Reference xProps(node, css::uno::UNO_QUERY); if (xProps.is()) { if (getBoolProperty(xProps, "Creatable") && rScriptContainersTreeView.get_iter_depth( *xScriptContainersSelectedIter) == 2) // library entry { bSensitiveMacroCreateButton = true; } if (getBoolProperty(xProps, "Editable")) { bSensitiveLibraryModuleDialogEditButton = true; } if (getBoolProperty(xProps, "Deletable")) { bSensitiveLibraryModuleDialogDeleteButton = true; } if (getBoolProperty(xProps, "Renamable")) { bSensitiveLibraryModuleDialogRenameButton = true; } } } } // scripts list box state dependant buttons weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); std::unique_ptr xScriptsSelectedIter = rScriptsTreeView.make_iterator(); if (rScriptsTreeView.n_children() && rScriptsTreeView.get_selected(xScriptsSelectedIter.get())) { bSensitiveAssignButton = true; css::uno::Reference node; node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter); if (node.is()) { bSensitiveMacroRunButton = true; css::uno::Reference xProps(node, css::uno::UNO_QUERY); if (xProps.is()) { if (getBoolProperty(xProps, "Editable")) { bSensitiveMacroEditButton = true; } if (!bSharedLocationContainer) { if (getBoolProperty(xProps, "Deletable")) { bSensitiveMacroDeleteButton = true; } if (getBoolProperty(xProps, "Renamable")) { bSensitiveMacroRenameButton = true; } } } } } } } m_xNewLibraryButton->set_sensitive(bSensitiveNewLibraryButton); m_xNewModuleButton->set_sensitive(bSensitiveNewModuleButton); m_xNewDialogButton->set_sensitive(bSensitiveNewDialogButton); m_xLibraryModuleDialogEditButton->set_sensitive(bSensitiveLibraryModuleDialogEditButton); m_xLibraryModuleDialogRenameButton->set_sensitive(bSensitiveLibraryModuleDialogRenameButton); m_xLibraryModuleDialogDeleteButton->set_sensitive(bSensitiveLibraryModuleDialogDeleteButton); m_xLibraryPasswordButton->set_sensitive(bSensitiveLibraryPasswordButton); m_xLibraryImportButton->set_sensitive(bSensitiveLibraryImportButton); m_xLibraryExportButton->set_sensitive(bSensitiveLibraryExportButton); m_xRunButton->set_sensitive(bSensitiveMacroRunButton); m_xMacroCreateButton->set_sensitive(bSensitiveMacroCreateButton); m_xMacroEditButton->set_sensitive(bSensitiveMacroEditButton); m_xMacroRenameButton->set_sensitive(bSensitiveMacroRenameButton); m_xMacroDeleteButton->set_sensitive(bSensitiveMacroDeleteButton); m_xAssignButton->set_sensitive(bSensitiveAssignButton); } // void createLibImpl(weld::Window* pWin, const ScriptDocument& rDocument, // weld::TreeView* pLibBox, SbTreeListBox* pBasicBox) // basctl/source/basicide/moduldl2.cxx void MacroManagerDialog::BasicScriptsCreateLibrary(const basctl::ScriptDocument& rDocument) { // create a unique library name OUString aLibName = CuiResId(STR_LIBRARY) + OUString::number(1); for (sal_uInt32 i = 1; rDocument.hasLibrary(basctl::E_SCRIPTS, aLibName) || rDocument.hasLibrary(basctl::E_DIALOGS, aLibName); aLibName = CuiResId(STR_LIBRARY) + OUString::number(++i)) ; InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL)); aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE)); aInputDlg.SetEntryText(aLibName); aInputDlg.HideHelpBtn(); aInputDlg.setCheckEntry([&](OUString sNewName) { if (sNewName.isEmpty() || rDocument.hasLibrary(basctl::E_SCRIPTS, sNewName) || rDocument.hasLibrary(basctl::E_DIALOGS, sNewName) || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) return false; return true; }); if (!aInputDlg.run()) return; aLibName = aInputDlg.GetEntryText(); try { // create library container for modules rDocument.getOrCreateLibrary(basctl::E_SCRIPTS, aLibName); // create a module OUString aModName = rDocument.createObjectName(basctl::E_SCRIPTS, aLibName); OUString sModuleCode; if (!rDocument.createModule(aLibName, aModName, true, sModuleCode)) throw css::uno::Exception("could not create module " + aModName, nullptr); // tdf#151741 - store all libraries to the file system, otherwise they // cannot be renamed/moved since the SfxLibraryContainer::renameLibrary // moves the folders/files on the file system css::uno::Reference xModLibContainer( rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); css::uno::Reference xModPersLibContainer( xModLibContainer, css::uno::UNO_QUERY); if (xModPersLibContainer.is()) xModPersLibContainer->storeLibraries(); // update Basic IDE object catalog SbxItem aModuleSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, basctl::SBX_TYPE_MODULE); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, { &aModuleSbxItem }); } catch (const css::uno::Exception&) { DBG_UNHANDLED_EXCEPTION("basctl.basicide"); } } void MacroManagerDialog::BasicScriptsCreateModule(const basctl::ScriptDocument& rDocument) { // library name is the selected tree entry weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen OUString aLibName = rTreeView.get_text(*xSelectedIter); // create an unused module name OUString aModName = CuiResId(STR_MODULE) + OUString::number(1); for (sal_uInt32 i = 1; rDocument.hasModule(aLibName, aModName); aModName = CuiResId(STR_MODULE) + OUString::number(++i)) ; InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWMODULELABEL)); aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWMODULETITLE)); aInputDlg.SetEntryText(aModName); aInputDlg.HideHelpBtn(); aInputDlg.setCheckEntry([&](OUString sNewName) { if (sNewName.isEmpty() || rDocument.hasModule(aLibName, sNewName) || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) return false; return true; }); if (!aInputDlg.run()) return; aModName = aInputDlg.GetEntryText(); OUString sModuleCode; if (!rDocument.createModule(aLibName, aModName, true /*create main sub*/, sModuleCode)) return; // update Basic IDE object catalog SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, basctl::SBX_TYPE_MODULE); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) { pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, { &aSbxItem }); } } void MacroManagerDialog::BasicScriptsCreateDialog(const basctl::ScriptDocument& rDocument) { // library name is the selected tree entry weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen OUString aLibName = rTreeView.get_text(*xSelectedIter); // create an unused dialog name OUString sDialogName = CuiResId(STR_DIALOG) + OUString::number(1); for (sal_uInt32 i = 1; rDocument.hasDialog(aLibName, sDialogName); sDialogName = CuiResId(STR_DIALOG) + OUString::number(++i)) ; InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWDIALOGLABEL)); aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWDIALOGTITLE)); aInputDlg.SetEntryText(sDialogName); aInputDlg.HideHelpBtn(); aInputDlg.setCheckEntry([&](OUString sNewName) { if (sNewName.isEmpty() || rDocument.hasDialog(aLibName, sNewName) || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) return false; return true; }); if (!aInputDlg.run()) return; sDialogName = aInputDlg.GetEntryText(); try { rDocument.getOrCreateLibrary(basctl::E_DIALOGS, aLibName); css::uno::Reference xISP; if (!rDocument.createDialog(aLibName, sDialogName, xISP)) return; // update Basic IDE object catalog SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, sDialogName, basctl::SBX_TYPE_DIALOG); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) { pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, { &aSbxItem }); } } catch (const css::container::ElementExistException&) { std::unique_ptr xError(Application::CreateMessageDialog( m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, CuiResId(STR_SBXNAMEALLREADYUSED))); xError->run(); } catch (const css::container::NoSuchElementException&) { DBG_UNHANDLED_EXCEPTION("basctl.basicide"); } } void MacroManagerDialog::BasicScriptsLibraryModuleDialogEdit( const basctl::ScriptDocument& rDocument) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen m_xDialog->hide(); // show the Basic IDE SfxAllItemSet aArgs(SfxGetpApp()->GetPool()); SfxRequest aRequest(SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs); SfxGetpApp()->ExecuteSlot(aRequest); if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library { SfxUnoAnyItem aDocItem(SID_BASICIDE_ARG_DOCUMENT_MODEL, css::uno::Any(rDocument.getDocumentOrNull())); SfxStringItem aLibNameItem(SID_BASICIDE_ARG_LIBNAME, m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY)); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) pDispatcher->ExecuteList(SID_BASICIDE_LIBSELECTED, SfxCallMode::ASYNCHRON, { &aDocItem, &aLibNameItem }); } else // module/dialog { ScriptContainerInfo* pScriptContainerInfo = weld::fromId(rTreeView.get_id(*xSelectedIter)); // pScriptContainerInfo->pBrowseNode is nullptr for Dialog entries SbxItem aSbxItem( SID_BASICIDE_ARG_SBX, rDocument, m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), pScriptContainerInfo->pBrowseNode ? basctl::SBX_TYPE_MODULE : basctl::SBX_TYPE_DIALOG); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) pDispatcher->ExecuteList(SID_BASICIDE_SHOWSBX, SfxCallMode::ASYNCHRON, { &aSbxItem }); } // close the MacroManagerDialog m_xDialog->response(0); } IMPL_LINK(MacroManagerDialog, CheckPasswordHdl, SvxPasswordDialog*, pDlg, bool) { basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); if (!aDocument.isAlive()) return false; bool bRet = false; css::uno::Reference xPasswd( aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); if (xPasswd.is()) { try { OUString aOldPassword(pDlg->GetOldPassword()); OUString aNewPassword(pDlg->GetNewPassword()); OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY); xPasswd->changeLibraryPassword(aLibName, aOldPassword, aNewPassword); bRet = true; } catch (...) { } } return bRet; } basctl::ScriptDocument ScriptContainersListBox::GetScriptDocument(const weld::TreeIter* pIter) { std::unique_ptr xIter = m_xTreeView->make_iterator(pIter); if (pIter == nullptr) { if (!m_xTreeView->get_selected(xIter.get())) return basctl::ScriptDocument::getApplicationScriptDocument(); } while (m_xTreeView->get_iter_depth(*xIter)) m_xTreeView->iter_parent(*xIter); ScriptContainerInfo* pScriptContainerInfo = weld::fromId(m_xTreeView->get_id(*xIter)); if (pScriptContainerInfo && pScriptContainerInfo->pBrowseNode) { css::uno::Reference aRootNode; aRootNode = pScriptContainerInfo->pBrowseNode; if (aRootNode->getName() == u"user"_ustr || aRootNode->getName() == u"share"_ustr) return basctl::ScriptDocument::getApplicationScriptDocument(); return basctl::ScriptDocument::getDocumentWithURLOrCaption(aRootNode->getName()); } return basctl::ScriptDocument::getApplicationScriptDocument(); } IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void) { if (&rButton == m_xCloseButton.get()) { m_xDialog->response(RET_CANCEL); return; } if (&rButton == m_xRunButton.get()) { SaveLastUsedMacro(); m_xDialog->response(RET_OK); return; } if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE) == "Basic") { basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); if (!aDocument.isAlive()) return; if (&rButton == m_xNewLibraryButton.get()) { BasicScriptsCreateLibrary(aDocument); } else if (&rButton == m_xNewModuleButton.get()) { BasicScriptsCreateModule(aDocument); } else if (&rButton == m_xNewDialogButton.get()) { BasicScriptsCreateDialog(aDocument); } else if (&rButton == m_xLibraryModuleDialogEditButton.get()) { BasicScriptsLibraryModuleDialogEdit(aDocument); } else if (&rButton == m_xLibraryModuleDialogRenameButton.get()) { BasicScriptsLibraryModuleDialogRename(aDocument); } else if (&rButton == m_xLibraryModuleDialogDeleteButton.get()) { BasicScriptsLibraryModuleDialogDelete(aDocument); } else if (&rButton == m_xLibraryPasswordButton.get()) { BasicScriptsLibraryPassword(aDocument); } else if (&rButton == m_xLibraryImportButton.get()) { auto insert_entries = [this]() { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen m_xScriptContainersListBox->Fill(xSelectedIter.get()); rTreeView.expand_row(*xSelectedIter); rTreeView.select(*xSelectedIter); }; basctl::ImportLib(aDocument, m_xDialog.get(), {}, {}, insert_entries); } else if (&rButton == m_xLibraryExportButton.get()) { basctl::Export(aDocument, m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY), m_xDialog.get()); } else if (&rButton == m_xMacroEditButton.get()) { BasicScriptsMacroEdit(aDocument); } else if (&rButton == m_xMacroDeleteButton.get()) { // todo // see: void MacroChooser::DeleteMacro() return; } else if (&rButton == m_xAssignButton.get()) { SfxAllItemSet Args(SfxGetpApp()->GetPool()); SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool()); if (m_xDocumentFrame.is()) aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame)); SfxRequest aRequest(SID_CONFIGACCEL, SfxCallMode::SYNCHRON, Args, aInternalSet); SfxMacroInfoItem aMacroInfoItem( SID_MACROINFO, aDocument.getBasicManager(), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), m_xScriptsListBox->GetSelectedScriptName(), OUString(), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LOCATION)); aRequest.AppendItem(aMacroInfoItem); SfxGetpApp()->ExecuteSlot(aRequest); } return; } // // button operations on Scripting Framework languages // if (&rButton == m_xNewLibraryButton.get()) { ScriptingFrameworkScriptsCreateEntry(InputDialogMode::NEWLIB); } else if (&rButton == m_xMacroCreateButton.get()) { ScriptingFrameworkScriptsCreateEntry(InputDialogMode::NEWMACRO); } else if (&rButton == m_xMacroEditButton.get()) { weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen css::uno::Reference node = getBrowseNode(rTreeView, *xSelectedIter); css::uno::Reference xInv(node, css::uno::UNO_QUERY); if (xInv.is()) { m_xDialog->response(RET_CANCEL); css::uno::Sequence args(0); css::uno::Sequence outArgs(0); css::uno::Sequence outIndex; try { // ISSUE need code to run script here xInv->invoke(u"Editable"_ustr, args, outIndex, outArgs); } catch (css::uno::Exception const&) { TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke"); } } } else if (&rButton == m_xLibraryModuleDialogDeleteButton.get()) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen ScriptingFrameworkScriptsDeleteEntry(rTreeView, *xSelectedIter); } else if (&rButton == m_xMacroDeleteButton.get()) { weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen ScriptingFrameworkScriptsDeleteEntry(rTreeView, *xSelectedIter); } else if (&rButton == m_xLibraryModuleDialogRenameButton.get()) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen ScriptingFrameworkScriptsRenameEntry(rTreeView, *xSelectedIter); } else if (&rButton == m_xMacroRenameButton.get()) { weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen ScriptingFrameworkScriptsRenameEntry(rTreeView, *xSelectedIter); } else if (&rButton == m_xAssignButton.get()) { SfxAllItemSet Args(SfxGetpApp()->GetPool()); SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool()); if (m_xDocumentFrame.is()) aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame)); SfxRequest aRequest(SID_CONFIGACCEL, SfxCallMode::SYNCHRON, Args, aInternalSet); SfxMacroInfoItem aMacroInfoItem( SID_MACROINFO, nullptr, m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), OUString(), m_xScriptsListBox->GetSelectedScriptName(), OUString(), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LOCATION)); aRequest.AppendItem(aMacroInfoItem); SfxGetpApp()->ExecuteSlot(aRequest); } } bool MacroManagerDialog::IsLibraryReadOnlyOrFailedPasswordQuery( const basctl::ScriptDocument& rDocument, weld::TreeIter* pIter) { css::uno::Reference xModLibContainer( rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); css::uno::Reference xDlgLibContainer( rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); OUString aLibName = m_xScriptContainersListBox->GetContainerName(*pIter, ScriptContainerType::LIBRARY); // check if library is readonly if ((xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && xModLibContainer->isLibraryReadOnly(aLibName) && !xModLibContainer->isLibraryLink(aLibName)) || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) && xDlgLibContainer->isLibraryReadOnly(aLibName) && !xDlgLibContainer->isLibraryLink(aLibName))) { std::unique_ptr xErrorBox( Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, CuiResId(STR_LIBISREADONLY))); xErrorBox->run(); return true; } // password if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) /*&& !xModLibContainer->isLibraryLoaded(aLibName)*/) { bool bOK = true; // check password css::uno::Reference xPasswd(xModLibContainer, css::uno::UNO_QUERY); if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) && !xPasswd->isLibraryPasswordVerified(aLibName)) { OUString sPassword; bOK = basctl::QueryPassword(m_xDialog.get(), xModLibContainer, aLibName, sPassword, true, true); } if (!bOK) return true; } return false; } // adapted from LibPage inline renaming // IMPL_LINK(LibPage, EditingEntryHdl, const weld::TreeIter&, rIter, bool) // IMPL_LINK(LibPage, EditedEntryHdl, const IterString&, rIterString, bool) // basctl/source/basicide/moduldl2.cxx void MacroManagerDialog::BasicScriptsLibraryModuleDialogRename( const basctl::ScriptDocument& rDocument) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen if (IsLibraryReadOnlyOrFailedPasswordQuery(rDocument, xSelectedIter.get())) return; OUString sOldName = rTreeView.get_text(*xSelectedIter); if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library { InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_RENAMELIBRARYLABEL)); aInputDlg.HideHelpBtn(); aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_RENAMELIBRARYTITLE)); aInputDlg.SetEntryText(sOldName); aInputDlg.setCheckEntry([&](OUString sNewName) { if (sNewName != sOldName && (sNewName.isEmpty() || rDocument.hasLibrary(basctl::E_SCRIPTS, sNewName) || rDocument.hasLibrary(basctl::E_DIALOGS, sNewName) || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName))) return false; return true; }); if (!aInputDlg.run()) return; OUString sNewName = aInputDlg.GetEntryText(); if (sNewName == sOldName) return; bool bSuccess = true; try { css::uno::Reference xModLibContainer( rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); if (xModLibContainer.is() && xModLibContainer->hasByName(sOldName)) xModLibContainer->renameLibrary(sOldName, sNewName); css::uno::Reference xDlgLibContainer( rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(sOldName)) xDlgLibContainer->renameLibrary(sOldName, sNewName); } catch (css::uno::Exception const&) { bSuccess = false; TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename"); } if (bSuccess) { basctl::MarkDocumentModified(rDocument); // rTreeView.set_text(*xSelectedIter, sNewName); } } else { // module/dialog ScriptContainerInfo* pScriptContainerInfo = weld::fromId(rTreeView.get_id(*xSelectedIter)); if (!pScriptContainerInfo) return; // should never happen OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY); InputDialog aInputDlg(m_xDialog.get(), CuiResId(pScriptContainerInfo->pBrowseNode ? STR_INPUTDIALOG_RENAMEMODULELABEL : STR_INPUTDIALOG_RENAMEDIALOGLABEL)); aInputDlg.HideHelpBtn(); aInputDlg.set_title(CuiResId(pScriptContainerInfo->pBrowseNode ? STR_INPUTDIALOG_RENAMEMODULETITLE : STR_INPUTDIALOG_RENAMEMODULETITLE)); aInputDlg.SetEntryText(sOldName); aInputDlg.setCheckEntry([&](OUString sNewName) { if (sNewName != sOldName && (sNewName.isEmpty() || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName) || pScriptContainerInfo->pBrowseNode ? rDocument.hasModule(aLibName, sNewName) : rDocument.hasDialog(aLibName, sNewName))) return false; return true; }); if (!aInputDlg.run()) return; OUString sNewName = aInputDlg.GetEntryText(); if (sNewName == sOldName) return; if (pScriptContainerInfo->pBrowseNode ? rDocument.renameModule(aLibName, sOldName, sNewName) : rDocument.renameDialog(aLibName, sOldName, sNewName, nullptr)) { basctl::MarkDocumentModified(rDocument); // rTreeView.set_text(*xSelectedIter, sNewName); } } } void MacroManagerDialog::BasicScriptsLibraryModuleDialogDelete( const basctl::ScriptDocument& rDocument) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen if (IsLibraryReadOnlyOrFailedPasswordQuery(rDocument, xSelectedIter.get())) return; if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library { // see: void LibPage::DeleteCurrent() // basctl/source/basicide/moduldl2.cxx OUString aLibName = rTreeView.get_text(*xSelectedIter); // check, if library is link bool bIsLibraryLink = false; css::uno::Reference xModLibContainer( rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); css::uno::Reference xDlgLibContainer( rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); if ((xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && xModLibContainer->isLibraryLink(aLibName)) || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) && xDlgLibContainer->isLibraryLink(aLibName))) { bIsLibraryLink = true; } if (!basctl::QueryDelLib(aLibName, bIsLibraryLink, m_xDialog.get())) return; // inform BasicIDE SfxUnoAnyItem aDocItem(SID_BASICIDE_ARG_DOCUMENT_MODEL, css::uno::Any(rDocument.getDocumentOrNull())); SfxStringItem aLibNameItem(SID_BASICIDE_ARG_LIBNAME, aLibName); if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) pDispatcher->ExecuteList(SID_BASICIDE_LIBREMOVED, SfxCallMode::SYNCHRON, { &aDocItem, &aLibNameItem }); // remove library from module and dialog library containers if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) xModLibContainer->removeLibrary(aLibName); if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)) xDlgLibContainer->removeLibrary(aLibName); basctl::MarkDocumentModified(rDocument); } else { // delete Basic module or dialog // adapted from void ObjectPage::DeleteCurrent() basctl/source/basicide/moduldlg.cxx ScriptContainerInfo* pScriptContainerInfo = weld::fromId(rTreeView.get_id(*xSelectedIter)); if (!pScriptContainerInfo) return; // shouldn't happen // pBrowseNode points to nullptr for dialog entries if (pScriptContainerInfo->pBrowseNode) { if (!basctl::QueryDelModule(m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), m_xDialog.get())) return; } else { if (!basctl::QueryDelDialog(m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), m_xDialog.get())) return; } bool bSuccess = false; if (pScriptContainerInfo->pBrowseNode) bSuccess = rDocument.removeModule(m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG)); else bSuccess = rDocument.removeDialog(m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG)); if (bSuccess) { if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) { SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), pScriptContainerInfo->pBrowseNode ? basctl::SBX_TYPE_MODULE : basctl::SBX_TYPE_DIALOG); pDispatcher->ExecuteList(SID_BASICIDE_SBXDELETED, SfxCallMode::SYNCHRON, { &aSbxItem }); } basctl::MarkDocumentModified(rDocument); } } } // inspired by IMPL_LINK( LibPage, ButtonHdl, weld::Button&, rButton, void ) // else if (&rButton == m_xPasswordButton.get()) // basctl/source/basicide/moduldl2.cxx void MacroManagerDialog::BasicScriptsLibraryPassword(const basctl::ScriptDocument& rDocument) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen OUString aLibName = rTreeView.get_text(*xSelectedIter); // load module library (if not loaded) css::uno::Reference xModLibContainer = rDocument.getLibraryContainer(basctl::E_SCRIPTS); if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) && !xModLibContainer->isLibraryLoaded(aLibName)) { xModLibContainer->loadLibrary(aLibName); } // check if library is password protected --> this is for setting and removing password if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) { css::uno::Reference xPasswd(xModLibContainer, css::uno::UNO_QUERY); if (xPasswd.is()) { if (xPasswd->isLibraryPasswordProtected(aLibName) && !xPasswd->isLibraryPasswordVerified(aLibName)) { // password not verified OUString sPassword; if (basctl::QueryPassword(m_xDialog.get(), xModLibContainer, aLibName, sPassword, true, true)) { CheckButtons(); } return; } // set/change password dialog SvxPasswordDialog aDlg(m_xDialog.get(), !xPasswd->isLibraryPasswordProtected(aLibName)); aDlg.SetCheckPasswordHdl(LINK(this, MacroManagerDialog, CheckPasswordHdl)); if (aDlg.run() == RET_OK) { if (xPasswd->isLibraryPasswordProtected(aLibName)) rTreeView.set_image(*xSelectedIter, RID_CUIBMP_LOCKED); else rTreeView.set_image(*xSelectedIter, RID_CUIBMP_LIB); basctl::MarkDocumentModified(rDocument); } rTreeView.grab_focus(); } } } void MacroManagerDialog::BasicScriptsMacroEdit(const basctl::ScriptDocument& rDocument) { // hide the scripts organizer selector dialog before opening the basic ide m_xDialog->hide(); // open the basic ide SfxAllItemSet aArgs(SfxGetpApp()->GetPool()); SfxRequest aRequest(SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs); SfxGetpApp()->ExecuteSlot(aRequest); // navigate to the method SbxItem aSbxItem( SID_BASICIDE_ARG_SBX, rDocument, m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), m_xScriptContainersListBox->GetSelectedEntryContainerName( ScriptContainerType::MODULEORDIALOG), m_xScriptsListBox->GetSelectedScriptName(), basctl::SBX_TYPE_METHOD); // need to use basctl::GetDispatcher() to have expected results with qt5 and x11, // gtk3 works with SfxGetpApp()->GetDispatcher() if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) pDispatcher->ExecuteList(SID_BASICIDE_SHOWSBX, SfxCallMode::ASYNCHRON, { &aSbxItem }); // alternate way to do this // BasicManager* pBasMgr = rDocument.getBasicManager(); // SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModName, aMethodName, OUString() ); // if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) // pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, SfxCallMode::ASYNCHRON, { &aInfoItem }); // now it is safe to close the scripts organizer selector dialog m_xDialog->response(0); } // modified version of void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) // cui/source/dialogs/scriptdlg.cxx void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rTreeView, const weld::TreeIter& rEntry) { css::uno::Reference xBrowseNode = getBrowseNode(rTreeView, rEntry); css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); if (xInv.is()) { OUString aNewName = xBrowseNode->getName(); sal_Int32 extnPos = aNewName.lastIndexOf('.'); if (extnPos > 0) { aNewName = aNewName.copy(0, extnPos); } InputDialog aInputDlg(m_xDialog.get(), xBrowseNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER ? CuiResId(STR_INPUTDIALOG_RENAMELIBRARYLABEL) : CuiResId(STR_INPUTDIALOG_RENAMEMACROLABEL)); aInputDlg.set_title(xBrowseNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER ? CuiResId(STR_INPUTDIALOG_RENAMELIBRARYTITLE) : CuiResId(STR_INPUTDIALOG_RENAMEMACROTITLE)); aInputDlg.SetEntryText(aNewName); aInputDlg.HideHelpBtn(); // doesn't check if the name already exists, that will be caught below by invoke aInputDlg.setCheckEntry([](OUString sNewName) { if (sNewName.isEmpty() || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) return false; return true; }); if (!aInputDlg.run()) return; aNewName = aInputDlg.GetEntryText(); css::uno::Sequence args{ css::uno::Any(aNewName) }; css::uno::Sequence outArgs; css::uno::Sequence outIndex; try { css::uno::Any aResult = xInv->invoke(u"Renamable"_ustr, args, outIndex, outArgs); xBrowseNode.set(aResult, css::uno::UNO_QUERY); } catch (css::uno::Exception const&) { TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename"); } } if (xBrowseNode.is()) { if (xBrowseNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER) { m_xScriptContainersListBox->ScriptContainerSelected(); } else { ScriptInfo* pScriptInfo = weld::fromId(m_xScriptsListBox->get_id(rEntry)); if (pScriptInfo) { css::uno::Reference xPropSet(xBrowseNode, css::uno::UNO_QUERY); if (xPropSet.is()) { OUString sURI; try { css::uno::Any value = xPropSet->getPropertyValue(u"URI"_ustr); value >>= sURI; } catch (css::uno::Exception&) { // do nothing, the URI will be empty } pScriptInfo->sURL = sURI; } } } rTreeView.set_text(rEntry, xBrowseNode->getName()); rTreeView.set_cursor(rEntry); } else { //ISSUE L10N & message from exception? OUString aError(CuiResId(RID_CUISTR_RENAMEFAILED)); std::unique_ptr xErrorBox(Application::CreateMessageDialog( m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, aError)); xErrorBox->set_title(CuiResId(RID_CUISTR_RENAMEFAILED_TITLE)); xErrorBox->run(); } } // for Scripting Framework entries // duplicate of OUString SvxScriptOrgDialog::getListOfChildren // cui/source/dialogs/scriptdlg.cxx OUString MacroManagerDialog::getListOfChildren( const css::uno::Reference& node, int depth) { OUStringBuffer result = "\n"; for (int i = 0; i <= depth; i++) { result.append("\t"); } result.append(node->getName()); try { if (node->hasChildNodes()) { const css::uno::Sequence> children = node->getChildNodes(); for (const css::uno::Reference& n : children) { result.append(getListOfChildren(n, depth + 1)); } } } catch (css::uno::Exception&) { // ignore, will return an empty string } return result.makeStringAndClear(); } // modified verson of void SvxScriptOrgDialog::deleteEntry(const weld::TreeIter& rEntry) // cui/source/dialogs/scriptdlg.cxx void MacroManagerDialog::ScriptingFrameworkScriptsDeleteEntry(weld::TreeView& rTreeView, const weld::TreeIter& rEntry) { bool result = false; css::uno::Reference node = getBrowseNode(rTreeView, rEntry); // ISSUE L10N string & can we center list? OUString aQuery = CuiResId(RID_CUISTR_DELQUERY) + getListOfChildren(node, 0); std::unique_ptr xQueryBox(Application::CreateMessageDialog( m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, aQuery)); xQueryBox->set_title(CuiResId(RID_CUISTR_DELQUERY_TITLE)); if (xQueryBox->run() == RET_NO) { return; } css::uno::Reference xInv(node, css::uno::UNO_QUERY); if (xInv.is()) { css::uno::Sequence args(0); css::uno::Sequence outArgs(0); css::uno::Sequence outIndex; try { css::uno::Any aResult = xInv->invoke(u"Deletable"_ustr, args, outIndex, outArgs); aResult >>= result; // or do we just assume true if no exception ? } catch (css::uno::Exception const&) { TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to delete"); } } if (result) { if (&rTreeView == &m_xScriptContainersListBox->get_widget()) { m_xScriptContainersListBox->Remove(&rEntry, true); SelectHdl(rTreeView); } else { m_xScriptsListBox->Remove(rEntry); } UpdateUI(); } else { //ISSUE L10N & message from exception? std::unique_ptr xErrorBox( Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, CuiResId(RID_CUISTR_DELFAILED))); xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); xErrorBox->run(); } } // Modified version of SvxScriptOrgDialog::CreateEntry // cui/source/dialogs/scriptdlg.cxx void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eInputDialogMode) { weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xSelectedIter = rTreeView.make_iterator(); if (!rTreeView.get_selected(xSelectedIter.get())) return; // should never happen css::uno::Reference aChildNode; css::uno::Reference xBrowseNode = getBrowseNode(rTreeView, *xSelectedIter); css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); // Currently, invocation is not implemented for python, only beanshell, javascript, and java. if (xInv.is()) { OUString aNewName; OUString aNewStdName; if (eInputDialogMode == InputDialogMode::NEWLIB) { aNewStdName = CuiResId(STR_LIBRARY); } else { aNewStdName = CuiResId(STR_MACRO); } bool bValid = false; sal_Int32 i = 1; css::uno::Sequence> childNodes; // no children => ok to create Parcel1 or Script1 without checking ? try { if (!xBrowseNode->hasChildNodes()) { aNewName = aNewStdName + OUString::number(i); bValid = true; } else { childNodes = xBrowseNode->getChildNodes(); } } catch (css::uno::Exception&) { // ignore, will continue on with empty sequence } OUString extn; while (!bValid) { aNewName = aNewStdName + OUString::number(i); bool bFound = false; if (childNodes.hasElements()) { OUString nodeName = childNodes[0]->getName(); sal_Int32 extnPos = nodeName.lastIndexOf('.'); if (extnPos > 0) extn = nodeName.copy(extnPos); } for (const css::uno::Reference& n : childNodes) { if (Concat2View(aNewName + extn) == n->getName()) { bFound = true; break; } } if (bFound) { i++; } else { bValid = true; } } InputDialog aInputDlg(m_xDialog.get(), eInputDialogMode == InputDialogMode::NEWLIB ? CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL) : CuiResId(STR_INPUTDIALOG_NEWMACROLABEL)); aInputDlg.set_title(eInputDialogMode == InputDialogMode::NEWLIB ? CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE) : CuiResId(STR_INPUTDIALOG_NEWMACROTITLE)); aInputDlg.SetEntryText(aNewName); aInputDlg.HideHelpBtn(); // setCheckEntry doesn't check if the name already exists. It is checked after the dialog // in the Creatable invocation call - this could be improved by including a check for // existing name aInputDlg.setCheckEntry([](OUString sNewName) { if (sNewName.isEmpty() || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) return false; return true; }); do { if (aInputDlg.run()) { OUString aUserSuppliedName = aInputDlg.GetEntryText(); bValid = true; for (const css::uno::Reference& n : childNodes) { if (Concat2View(aUserSuppliedName + extn) == n->getName()) { bValid = false; OUString aError = CuiResId(RID_CUISTR_CREATEFAILED) + CuiResId(RID_CUISTR_CREATEFAILEDDUP); std::unique_ptr xErrorBox( Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, aError)); xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); xErrorBox->run(); aInputDlg.SetEntryText(aNewName); break; } } if (bValid) aNewName = aUserSuppliedName; } else { // user hit cancel return; } } while (!bValid); // open up parent node (which ensures it's loaded) rTreeView.expand_row(*xSelectedIter); css::uno::Sequence args{ css::uno::Any(aNewName) }; css::uno::Sequence outArgs; css::uno::Sequence outIndex; try { css::uno::Any aResult = xInv->invoke(u"Creatable"_ustr, args, outIndex, outArgs); aChildNode.set(aResult, css::uno::UNO_QUERY); } catch (css::uno::Exception const&) { TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Create"); } } if (aChildNode.is()) { if (rTreeView.get_iter_depth(*xSelectedIter) == 1) // language node { m_xScriptContainersListBox->Fill(xSelectedIter.get()); rTreeView.expand_row(*xSelectedIter); rTreeView.select(*xSelectedIter); } else { m_xScriptContainersListBox->ScriptContainerSelected(); } UpdateUI(); } else { //ISSUE L10N & message from exception? OUString aError(CuiResId(RID_CUISTR_CREATEFAILED)); std::unique_ptr xErrorBox(Application::CreateMessageDialog( m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, aError)); xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); xErrorBox->run(); } } // called from OUString AbstractMacroManagerDialog_Impl::GetScriptURL() const // cui/source/factory/dlgfact.cxx OUString MacroManagerDialog::GetScriptURL() const { OUString result; std::unique_ptr xIter = m_xScriptsListBox->make_iterator(); if (m_xScriptsListBox->get_selected(xIter.get())) { ScriptInfo* pScriptInfo = weld::fromId(m_xScriptsListBox->get_id(*xIter)); if (pScriptInfo) result = pScriptInfo->sURL; } return result; } constexpr OUString MACRO_MANAGER_CONFIGNAME = u"MacroManagerDialog"_ustr; constexpr OUString LAST_RUN_MACRO_INFO = u"LastRunMacro"_ustr; // adapted from SvxScriptSelectorDialog::SaveLastUsedMacro() // cui/source/customize/cfgutil.cxx void MacroManagerDialog::SaveLastUsedMacro() { // Gets the current selection in the dialog as a series of selected entries OUString sMacroInfo = m_xScriptsListBox->GetSelectedScriptName(); weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(); if (!rScriptContainersTreeView.get_selected(xIter.get())) return; do { sMacroInfo = rScriptContainersTreeView.get_text(*xIter) + "|" + sMacroInfo; } while (rScriptContainersTreeView.iter_parent(*xIter)); SvtViewOptions(EViewType::Dialog, MACRO_MANAGER_CONFIGNAME) .SetUserItem(LAST_RUN_MACRO_INFO, css::uno::Any(sMacroInfo)); } // adapted from SvxScriptSelectorDialog::LoadLastUsedMacro() // cui/source/customize/cfgutil.cxx void MacroManagerDialog::LoadLastUsedMacro() { SvtViewOptions aDlgOpt(EViewType::Dialog, MACRO_MANAGER_CONFIGNAME); if (!aDlgOpt.Exists()) return; OUString sMacroInfo; aDlgOpt.GetUserItem(LAST_RUN_MACRO_INFO) >>= sMacroInfo; if (sMacroInfo.isEmpty()) return; // Counts how many entries exist in the macro info string sal_Int16 nInfoParts = 0; sal_Int16 nLastIndex = sMacroInfo.indexOf('|'); if (nLastIndex > -1) { nInfoParts = 1; while (nLastIndex != -1) { nInfoParts++; nLastIndex = sMacroInfo.indexOf('|', nLastIndex + 1); } } weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(); if (!rScriptContainersTreeView.get_iter_first(*xIter)) return; // Expand the nodes in the script containers tree OUString sNodeToExpand; bool bIsIterValid; sal_Int16 nOpenedNodes = 0; for (sal_Int16 i = 0; i < nInfoParts - 1; i++) { sNodeToExpand = sMacroInfo.getToken(i, '|'); bIsIterValid = true; while (bIsIterValid && rScriptContainersTreeView.get_text(*xIter) != sNodeToExpand) bIsIterValid = rScriptContainersTreeView.iter_next_sibling(*xIter); if (bIsIterValid) { rScriptContainersTreeView.expand_row(*xIter); nOpenedNodes++; } if (rScriptContainersTreeView.iter_has_child(*xIter)) (void)rScriptContainersTreeView.iter_children(*xIter); else if (nOpenedNodes < nInfoParts - 1) // If the number of levels in the tree is smaller than the // number of parts in the macro info string, then return return; } rScriptContainersTreeView.select(*xIter); rScriptContainersTreeView.scroll_to_row(*xIter); // fill the scripts list box and set the label m_xScriptContainersListBox->ScriptContainerSelected(); m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + rScriptContainersTreeView.get_text(*xIter)); // Select the macro in the scripts tree weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); xIter = rScriptsTreeView.make_iterator(); if (rScriptsTreeView.get_iter_first(*xIter)) { OUString sMacroName = sMacroInfo.getToken(nInfoParts - 1, '|'); bIsIterValid = true; while (bIsIterValid && rScriptsTreeView.get_text(*xIter) != sMacroName) bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter); if (bIsIterValid) { rScriptsTreeView.scroll_to_row(*xIter); rScriptsTreeView.select(*xIter); } } UpdateUI(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */