1
0
Fork 0
libreoffice/cui/source/tabpages/macroass.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

402 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <macroass.hxx>
#include <o3tl/safeint.hxx>
#include <o3tl/string_view.hxx>
#include <osl/diagnose.h>
#include <comphelper/string.hxx>
#include <comphelper/processfactory.hxx>
#include <svl/macitem.hxx>
#include <svx/svxids.hrc>
#include <tools/debug.hxx>
#include <vcl/idle.hxx>
#include <cfgutil.hxx>
#include <sfx2/evntconf.hxx>
#include <headertablistbox.hxx>
using ::com::sun::star::uno::Reference;
using ::com::sun::star::frame::XFrame;
class SfxMacroTabPage_Impl
{
public:
SfxMacroTabPage_Impl();
OUString m_aStaticMacroLBLabel;
std::unique_ptr<weld::Button> m_xAssignPB;
std::unique_ptr<weld::Button> m_xDeletePB;
std::unique_ptr<MacroEventListBox> m_xEventLB;
std::unique_ptr<weld::Widget> m_xGroupFrame;
std::unique_ptr<CuiConfigGroupListBox> m_xGroupLB;
std::unique_ptr<weld::Frame> m_xMacroFrame;
std::unique_ptr<CuiConfigFunctionListBox> m_xMacroLB;
Idle m_aFillGroupIdle { "cui SfxMacroTabPage m_aFillGroupIdle" };
bool m_bGotEvents;
};
SfxMacroTabPage_Impl::SfxMacroTabPage_Impl()
: m_bGotEvents(false)
{
}
static sal_uInt16 aPageRg[] = {
SID_ATTR_MACROITEM, SID_ATTR_MACROITEM,
0
};
static OUString ConvertToUIName_Impl( SvxMacro const *pMacro )
{
OUString aName( pMacro->GetMacName() );
if ( pMacro->GetLanguage() != "JavaScript" )
{
const sal_Int32 nCount = comphelper::string::getTokenCount(aName, '.');
OUString aEntry = aName.getToken( nCount-1, '.' );
if ( nCount > 2 )
{
aEntry += OUString::Concat("(") + o3tl::getToken(aName, 0, '.' ) + "." + o3tl::getToken(aName, nCount-2, '.' ) + ")";
}
return aEntry;
}
else
return aName;
}
void SfxMacroTabPage::EnableButtons()
{
// don't do anything as long as the eventbox is empty
weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox();
int nSelected = rTreeView.get_selected_index();
if (nSelected != -1)
{
// get bound macro
const SvxMacro* pM = aTbl.Get(static_cast<SvMacroItemId>(rTreeView.get_selected_id().toInt32()));
mpImpl->m_xDeletePB->set_sensitive(nullptr != pM);
OUString sEventMacro = rTreeView.get_text(nSelected, 1);
OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro));
}
else
mpImpl->m_xAssignPB->set_sensitive(false);
}
SfxMacroTabPage::SfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet )
: SfxTabPage(pPage, pController, u"cui/ui/eventassignpage.ui"_ustr, u"EventAssignPage"_ustr, &rAttrSet)
{
mpImpl.reset(new SfxMacroTabPage_Impl);
mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST );
mpImpl->m_xEventLB.reset(new MacroEventListBox(m_xBuilder->weld_tree_view(u"assignments"_ustr)));
mpImpl->m_xAssignPB = m_xBuilder->weld_button(u"assign"_ustr);
mpImpl->m_xDeletePB = m_xBuilder->weld_button(u"delete"_ustr);
mpImpl->m_xGroupFrame = m_xBuilder->weld_widget(u"groupframe"_ustr);
mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view(u"libraries"_ustr)));
mpImpl->m_xMacroFrame = m_xBuilder->weld_frame(u"macroframe"_ustr);
mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label();
mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view(u"macros"_ustr)));
SetFrame( rxDocumentFrame );
InitAndSetHandler();
ScriptChanged();
}
SfxMacroTabPage::~SfxMacroTabPage()
{
mpImpl.reset();
}
void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId)
{
weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox();
rTreeView.append(OUString::number(static_cast<sal_Int32>(nEventId)), rEventName);
// if the table is valid already
SvxMacro* pM = aTbl.Get(nEventId);
if (pM)
{
OUString sNew(ConvertToUIName_Impl(pM));
rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1);
}
}
void SfxMacroTabPage::ScriptChanged()
{
// get new areas and their functions
mpImpl->m_xGroupFrame->show();
mpImpl->m_xMacroFrame->show();
EnableButtons();
}
bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet )
{
SvxMacroItem aItem( GetWhich( aPageRg[0] ) );
const_cast<SvxMacroTableDtor&>(aItem.GetMacroTable()) = aTbl;
const SfxPoolItem* pItem = nullptr;
SfxItemState eState = GetItemSet().GetItemState(aItem.Which(), true, &pItem);
if (eState == SfxItemState::DEFAULT && aTbl.empty())
{
// Don't touch the item set if there was no input and our table is empty.
return false;
}
if (SfxItemState::SET != eState || aItem != *static_cast<const SvxMacroItem*>(pItem))
{
rSet->Put( aItem );
return true;
}
return false;
}
void SfxMacroTabPage::LaunchFillGroup()
{
if (! mpImpl->m_aFillGroupIdle.IsActive() )
mpImpl->m_aFillGroupIdle.Start();
}
void SfxMacroTabPage::ActivatePage( const SfxItemSet& )
{
LaunchFillGroup();
}
void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet)
{
if( mpImpl->m_bGotEvents )
return;
if( const SfxEventNamesItem* pEventsItem = aSet.GetItemIfSet( SID_EVENTCONFIG ) )
{
mpImpl->m_bGotEvents = true;
const SfxEventNamesList& rList = pEventsItem->GetEvents();
for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
{
const SfxEventName &rOwn = rList.at(nNo);
AddEvent( rOwn.maUIName, rOwn.mnId );
}
}
}
void SfxMacroTabPage::Reset( const SfxItemSet* rSet )
{
const SfxPoolItem* pItem;
if( SfxItemState::SET == rSet->GetItemState( GetWhich( aPageRg[0] ), true, &pItem ))
aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable();
const SfxEventNamesItem* pEventsItem;
if( !mpImpl->m_bGotEvents && (pEventsItem = rSet->GetItemIfSet( SID_EVENTCONFIG ) ) )
{
mpImpl->m_bGotEvents = true;
const SfxEventNamesList& rList = pEventsItem->GetEvents();
for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
{
const SfxEventName &rOwn = rList.at(nNo);
AddEvent( rOwn.maUIName, rOwn.mnId );
}
}
FillEvents();
weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
std::unique_ptr<weld::TreeIter> xIter(rListBox.make_iterator());
if (rListBox.get_iter_first(*xIter))
{
rListBox.set_cursor(*xIter);
EnableButtons();
}
}
bool SfxMacroTabPage::IsReadOnly() const
{
return false;
}
IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void)
{
weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
int nSelected = rListBox.get_selected_index();
if (nSelected == -1)
{
DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?");
return;
}
ScriptChanged();
EnableButtons();
}
IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void)
{
mpImpl->m_xGroupLB->GroupSelected();
const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
OUString aLabelText;
if( !sScriptURI.isEmpty() )
aLabelText = mpImpl->m_aStaticMacroLBLabel;
mpImpl->m_xMacroFrame->set_label( aLabelText );
EnableButtons();
}
IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void)
{
EnableButtons();
}
IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void)
{
AssignDeleteHdl(&rBtn);
}
IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, bool)
{
AssignDeleteHdl(&rBtn);
return true;
}
void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn)
{
weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
int nSelected = rListBox.get_selected_index();
if (nSelected == -1)
{
DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?");
return;
}
const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive();
// remove from the table
SvMacroItemId nEvent = static_cast<SvMacroItemId>(rListBox.get_selected_id().toInt32());
aTbl.Erase( nEvent );
OUString sScriptURI;
if( bAssEnabled )
{
sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
if( sScriptURI.startsWith( "vnd.sun.star.script:" ) )
{
aTbl.Insert(
nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_SF ) );
}
else
{
OSL_ENSURE( false, "SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" );
aTbl.Insert(
nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_STARBASIC ) );
}
}
rListBox.set_text(nSelected, sScriptURI, 1);
EnableButtons();
}
IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void )
{
// FillMacroList() can take a long time -> show wait cursor and disable input
weld::Window* pDialog = GetFrameWeld();
// perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr
std::unique_ptr<weld::WaitObject> xWait(pDialog ? new weld::WaitObject(pDialog) : nullptr);
// fill macro list
mpImpl->m_xGroupLB->Init(comphelper::getProcessComponentContext(), GetFrame(),
OUString(), false);
}
void SfxMacroTabPage::InitAndSetHandler()
{
weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
Link<weld::TreeView&,bool> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl));
mpImpl->m_xMacroLB->connect_row_activated( aLnk);
mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl));
mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl));
rListBox.connect_row_activated(aLnk);
rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl));
mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl));
mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl));
std::vector<int> aWidths
{
o3tl::narrowing<int>(rListBox.get_approximate_digit_width() * 35)
};
rListBox.set_column_fixed_widths(aWidths);
mpImpl->m_xEventLB->show();
mpImpl->m_xEventLB->set_sensitive(true);
mpImpl->m_xGroupLB->set_sensitive(true);
mpImpl->m_xMacroLB->set_sensitive(true);
mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get());
}
void SfxMacroTabPage::FillEvents()
{
weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
int nEntryCnt = rListBox.n_children();
// get events from the table and fill the EventListBox respectively
for (int n = 0 ; n < nEntryCnt; ++n)
{
OUString sOld = rListBox.get_text(n, 1);
OUString sNew;
SvMacroItemId nEventId = static_cast<SvMacroItemId>(rListBox.get_id(n).toInt32());
if (aTbl.IsKeyValid(nEventId))
sNew = ConvertToUIName_Impl(aTbl.Get(nEventId));
if (sOld == sNew)
continue;
rListBox.set_text(n, sNew, 1);
}
}
namespace
{
std::unique_ptr<SfxMacroTabPage> CreateSfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet)
{
return std::make_unique<SfxMacroTabPage>( pPage, pController, nullptr, rAttrSet );
}
}
std::unique_ptr<SfxTabPage> SfxMacroTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
{
return CreateSfxMacroTabPage(pPage, pController, *rAttrSet);
}
SfxMacroAssignDlg::SfxMacroAssignDlg(weld::Widget* pParent,
const Reference< XFrame >& rxDocumentFrame, std::unique_ptr<const SfxItemSet> xSet)
: SfxSingleTabDialogController(pParent, nullptr, u"cui/ui/eventassigndialog.ui"_ustr,
u"EventAssignDialog"_ustr),
mxItemSet(std::move(xSet))
{
SetInputSet(mxItemSet.get());
std::unique_ptr<SfxMacroTabPage> xPage = CreateSfxMacroTabPage(get_content_area(), this, *mxItemSet);
xPage->SetFrame(rxDocumentFrame);
SetTabPage(std::move(xPage));
GetTabPage()->LaunchFillGroup();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */