tdf#123159 Make Hyperlinks keyboard accessible

Extend .uno:OpenHyperlinkOnCursor to open all hyperlinks
in a cell, when not in edit mode.

The UNO command can be assigned to a keyboard shortcut from
`Tools > Customize > Keyboard`. If the active cell is not in
edit mode, then pressing the shortcut opens all the hyperlinks
in the cell. If in edit mode, pressing the shortcut opens the
hyperlink under the caret "|".

Change-Id: I7ffdab54fa31b9f7f614e04cc3158d8be217825e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157666
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
This commit is contained in:
Sahil Gautam 2024-03-24 00:48:22 +05:30 committed by Michael Weghorn
parent dbb0892ad1
commit 14396a5361
6 changed files with 111 additions and 11 deletions

View file

@ -58,6 +58,7 @@ interface TableDocument
SID_CHART_ADDSOURCE [ ExecMethod = Execute; ]
FID_AUTO_CALC [ ExecMethod = Execute; StateMethod = GetState; ]
FID_RECALC [ ExecMethod = Execute; StateMethod = GetState; ]
SID_OPEN_HYPERLINK [ ExecMethod = Execute; StateMethod = GetState; ]
FID_HARD_RECALC [ ExecMethod = Execute; StateMethod = GetState; ]
SID_UPDATETABLINKS [ ExecMethod = Execute; ]
SID_REIMPORT_AFTER_LOAD [ ExecMethod = Execute; ]

View file

@ -74,7 +74,6 @@ interface TableText
SID_HYPERLINK_SETLINK [ ExecMethod = Execute; ]
SID_HYPERLINK_GETLINK [ StateMethod = GetState; ]
SID_OPEN_HYPERLINK [ ExecMethod = Execute; StateMethod = GetState; ]
SID_EDIT_HYPERLINK [ ExecMethod = Execute; StateMethod = GetState; ]
SID_COPY_HYPERLINK_LOCATION [ ExecMethod = Execute; StateMethod = GetState; ]
SID_REMOVE_HYPERLINK [ ExecMethod = Execute; StateMethod = GetState; ]

View file

@ -401,6 +401,54 @@ void ScDocShell::Execute( SfxRequest& rReq )
rReq.Done();
}
break;
case SID_OPEN_HYPERLINK:
{
ScViewData* pViewData = GetViewData();
if ( !pViewData )
{
rReq.Ignore();
break;
}
if (SC_MOD()->IsEditMode())
{
if (EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart()))
{
const SvxFieldItem* pFieldItem = pEditView->GetFieldAtSelection(/*bAlsoCheckBeforeCursor=*/true);
const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
{
ScGlobal::OpenURL(pURLField->GetURL(), pURLField->GetTargetFrame(), true);
rReq.Done();
break;
}
}
rReq.Ignore();
break;
}
ScGridWindow* pWin = pViewData->GetActiveWin();
if ( !pWin )
{
rReq.Ignore();
break;
}
ScAddress aCell {pViewData->GetCurPos()};
std::vector<UrlData> vUrls = pWin->GetEditUrls(aCell);
if (vUrls.empty())
{
rReq.Ignore();
break;
}
for (UrlData& data : vUrls)
{
ScGlobal::OpenURL(data.aUrl, data.aTarget, true);
}
rReq.Done();
}
break;
case FID_RECALC:
DoRecalc( rReq.IsAPI() );
rReq.Done();

View file

@ -81,6 +81,13 @@ class ScLokRTLContext;
#define SC_PD_BREAK_H 16
#define SC_PD_BREAK_V 32
struct UrlData
{
OUString aName;
OUString aUrl;
OUString aTarget;
};
// predefines
namespace sdr::overlay { class OverlayObjectList; }
@ -509,6 +516,8 @@ public:
void initiatePageBreaks();
std::vector<UrlData> GetEditUrls(const ScAddress& rSelectedCell);
protected:
void ImpCreateOverlayObjects();
void ImpDestroyOverlayObjects();

View file

@ -639,15 +639,6 @@ void ScEditShell::Execute( SfxRequest& rReq )
}
}
break;
case SID_OPEN_HYPERLINK:
{
const SvxFieldItem* pFieldItem
= pEditView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
ScGlobal::OpenURL( pURLField->GetURL(), pURLField->GetTargetFrame(), true );
return;
}
case SID_EDIT_HYPERLINK:
{
// Ensure the field is selected first
@ -832,7 +823,6 @@ void ScEditShell::GetState( SfxItemSet& rSet )
}
break;
case SID_OPEN_HYPERLINK:
case SID_EDIT_HYPERLINK:
case SID_COPY_HYPERLINK_LOCATION:
case SID_REMOVE_HYPERLINK:

View file

@ -5798,6 +5798,59 @@ static void lcl_SetEngineTextKeepingDefaults(const std::shared_ptr<ScFieldEditEn
}
}
static std::vector<std::unique_ptr<SvxFieldItem>> lcl_GetEditEngineFields(std::shared_ptr<ScFieldEditEngine> pEditEngine)
{
std::vector<std::unique_ptr<SvxFieldItem>> vFieldVect;
sal_Int32 nPara = pEditEngine->GetParagraphCount();
for (sal_Int32 nCurrPara = 0; nCurrPara < nPara; ++nCurrPara)
{
sal_Int16 nField = pEditEngine->GetFieldCount(nCurrPara);
for (sal_Int16 nCurrField = 0; nCurrField < nField; ++nCurrField)
{
EFieldInfo aFieldInfo = pEditEngine->GetFieldInfo(nCurrPara, nCurrField);
vFieldVect.push_back(std::move(aFieldInfo.pFieldItem));
}
}
return vFieldVect;
}
std::vector<UrlData> ScGridWindow::GetEditUrls(const ScAddress& rSelectedCell)
{
ScDocShell* pDocSh = mrViewData.GetDocShell();
ScDocument& rDoc = pDocSh->GetDocument();
SCCOL nPosX = rSelectedCell.Col();
SCROW nPosY = rSelectedCell.Row();
SCTAB nTab = rSelectedCell.Tab();
OUString sURL;
ScRefCellValue aCell;
std::vector<UrlData> vUrls;
if (!lcl_GetHyperlinkCell(rDoc, nPosX, nPosY, nTab, aCell, sURL))
return vUrls;
if (nPosX != rSelectedCell.Col())
return vUrls;
const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab );
std::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, *pPattern);
lcl_SetEngineTextKeepingDefaults(pEngine, rDoc, aCell, sURL);
std::vector<std::unique_ptr<SvxFieldItem>> vFieldItems = lcl_GetEditEngineFields(pEngine);
for (auto& pFieldItem : vFieldItems)
{
UrlData aData;
bool bIsUrl = extractURLInfo(pFieldItem.get(), &aData.aName, &aData.aUrl, &aData.aTarget);
if (bIsUrl && !aData.aUrl.isEmpty())
vUrls.push_back(aData);
}
return vUrls;
}
bool ScGridWindow::GetEditUrl( const Point& rPos,
OUString* pName, OUString* pUrl, OUString* pTarget )
{