Skip to content

Commit

Permalink
Merge branch 'master' into messageDialogApi
Browse files Browse the repository at this point in the history
# Conflicts:
#	user_docs/en/changes.md
  • Loading branch information
SaschaCowley committed Dec 13, 2024
2 parents 0dce0e9 + 82fefa5 commit 0c99151
Show file tree
Hide file tree
Showing 29 changed files with 618 additions and 1,107 deletions.
2 changes: 1 addition & 1 deletion appveyor/scripts/pushPackagingInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ $ErrorActionPreference = "Stop";
.\venvUtils\exportPackageList.bat installed_python_packages.txt
Push-AppveyorArtifact installed_python_packages.txt
$appVeyorUrl = "https://ci.appveyor.com"
$exe = Get-ChildItem -Name output\*.exe
$exe = Get-ChildItem -Name output\nvda_*.exe
if($?){
$exeUrl="$appVeyorUrl/api/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/output/$exe"
if ($env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null) {
Expand Down
18 changes: 0 additions & 18 deletions launcher/nvdaLauncher.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ CRCCheck on

ReserveFile "${NSISDIR}\Plugins\x86-unicode\system.dll"
ReserveFile "${NSISDIR}\Plugins\x86-unicode\banner.dll"
ReserveFile "..\miscDeps\launcher\nvda_logo.wav"

Name "NVDA"
VIProductVersion "${VERSION_YEAR}.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}" ;Needs to be here so other version info shows up
Expand Down Expand Up @@ -85,9 +84,6 @@ ${GetParameters} $0
; Sets the error flag if the option is missing.
; Reference: https://nsis.sourceforge.io/Docs/AppendixE.html#getoptions
${GetOptions} $0 "--minimal" $1
${If} ${Errors}
Call PlayLogoSound
${EndIf}
CreateDirectory "$PLUGINSDIR\app"
setOutPath "$PLUGINSDIR\app"
file /R "${NVDADistDir}\"
Expand All @@ -98,17 +94,3 @@ execWait "$PLUGINSDIR\app\nvda_noUIAccess.exe $0 --launcher" $1
;If exit code is 3 then execute again (restart)
intcmp $1 3 exec +1
SectionEnd

Function PlayLogoSound
File "..\miscDeps\launcher\nvda_logo.wav"
Push "$PLUGINSDIR\nvda_logo.wav"
Call PlaySound
FunctionEnd

Function PlaySound
; Retrieve the file to play
pop $9
; The code below is derived from the code example at http://nsis.sourceforge.io/WinAPI:winmm:PlaySound
IntOp $0 "SND_ASYNC" || 1
System::Call 'winmm::PlaySound(t r9, i 0, i r0) b'
FunctionEnd
2 changes: 1 addition & 1 deletion miscDeps
10 changes: 10 additions & 0 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from typing import (
Dict,
Optional,
TYPE_CHECKING,
)
import weakref
import textUtils
Expand Down Expand Up @@ -45,6 +46,9 @@
import aria
from winAPI.sessionTracking import isLockScreenModeActive

if TYPE_CHECKING:
from utils.urlUtils import _LinkData


class NVDAObjectTextInfo(textInfos.offsets.OffsetsTextInfo):
"""A default TextInfo which is used to enable text review of information about widgets that don't support text content.
Expand Down Expand Up @@ -1642,3 +1646,9 @@ def _get_linkType(self) -> controlTypes.State | None:
if not isinstance(ti, BrowseModeDocumentTreeInterceptor):
return None
return ti.getLinkTypeInDocument(self.value)

linkData: "_LinkData | None"

def _get_linkData(self) -> "_LinkData | None":
"""If the object has an associated link, returns the link's data (target and text)."""
raise NotImplementedError
31 changes: 16 additions & 15 deletions source/NVDAObjects/window/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import config
from config.configFlags import ReportCellBorders
import textInfos
from utils.urlUtils import _LinkData
import colors
import eventHandler
import api
Expand Down Expand Up @@ -1368,21 +1369,6 @@ def _getFormatFieldAndOffsets(self, offset, formatConfig, calculateOffsets=True)
def _get_locationText(self):
return self.obj.getCellPosition()

def _getLinkDataAtCaretPosition(self) -> textInfos._Link | None:
links = self.obj.excelCellObject.Hyperlinks
if links.count == 0:
return None
link = links(1)
if link.Type == MsoHyperlink.RANGE:
text = link.TextToDisplay
else:
log.debugWarning(f"No text to display for link type {link.Type}")
text = None
return textInfos._Link(
displayText=text,
destination=link.Address,
)


NVCELLINFOFLAG_ADDRESS = 0x1
NVCELLINFOFLAG_TEXT = 0x2
Expand Down Expand Up @@ -1710,6 +1696,21 @@ def _get_role(self):
return controlTypes.Role.LINK
return controlTypes.Role.TABLECELL

def _get_linkData(self) -> _LinkData | None:
links = self.excelCellObject.Hyperlinks
if links.count == 0:
return None
link = links(1)
if link.Type == MsoHyperlink.RANGE:
text = link.TextToDisplay
else:
log.debugWarning(f"No text to display for link type {link.Type}")
text = None
return _LinkData(
displayText=text,
destination=link.Address,
)

TextInfo = ExcelCellTextInfo

def _isEqual(self, other):
Expand Down
5 changes: 3 additions & 2 deletions source/NVDAObjects/window/winword.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from enum import IntEnum
import documentBase
from utils.displayString import DisplayStringIntEnum
from utils.urlUtils import _LinkData

if TYPE_CHECKING:
import inputCore
Expand Down Expand Up @@ -915,7 +916,7 @@ def _getShapeAtCaretPosition(self) -> comtypes.client.lazybind.Dispatch | None:
return shapes[1]
return None

def _getLinkDataAtCaretPosition(self) -> textInfos._Link | None:
def _getLinkDataAtCaretPosition(self) -> _LinkData | None:
link = self._getLinkAtCaretPosition()
if not link:
return None
Expand All @@ -928,7 +929,7 @@ def _getLinkDataAtCaretPosition(self) -> textInfos._Link | None:
case _:
log.debugWarning(f"No text to display for link type {link.Type}")
text = None
return textInfos._Link(
return _LinkData(
displayText=text,
destination=link.Address,
)
Expand Down
82 changes: 62 additions & 20 deletions source/appModules/powerpnt.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import ctypes

import comtypes.client.lazybind
import config
import oleacc
import comHelper
import ui
Expand All @@ -27,6 +28,7 @@
from treeInterceptorHandler import DocumentTreeInterceptor
from NVDAObjects import NVDAObjectTextInfo
from displayModel import DisplayModelTextInfo, EditableTextDisplayModelTextInfo
import textInfos
import textInfos.offsets
import eventHandler
import appModuleHandler
Expand All @@ -41,6 +43,7 @@
import scriptHandler
from locationHelper import RectLTRB
from NVDAObjects.window._msOfficeChart import OfficeChart
from utils.urlUtils import _LinkData

# Translators: The name of a category of NVDA commands.
SCRCAT_POWERPOINT = _("PowerPoint")
Expand Down Expand Up @@ -994,6 +997,19 @@ def _get_mathMl(self):
except: # noqa: E722
raise LookupError("Couldn't get MathML from MathType")

def _get_linkData(self) -> _LinkData | None:
mouseClickSetting = self.ppObject.ActionSettings(ppMouseClick)
if mouseClickSetting.action == ppActionHyperlink:
if self.value:
text = f"{self.roleText} {self.value}"
else:
text = self.roleText
return _LinkData(
displayText=text,
destination=mouseClickSetting.Hyperlink.Address,
)
return None

__gestures = {
"kb:leftArrow": "moveHorizontal",
"kb:rightArrow": "moveHorizontal",
Expand Down Expand Up @@ -1160,6 +1176,23 @@ def _getBoundingRectFromOffset(self, offset: int) -> RectLTRB:
bottom = self.obj.documentWindow.ppObjectModel.pointsToScreenPixelsY(rangeTop + rangeHeight)
return RectLTRB(left, top, right, bottom)

def _getCurrentRun(
self,
offset: int,
) -> tuple[comtypes.client.lazybind.Dispatch | None, int, int]:
runs = self.obj.ppObject.textRange.runs()
for run in runs:
start = run.start - 1
end = start + run.length
if start <= offset < end:
startOffset = start
endOffset = end
curRun = run
break
else:
curRun, startOffset, endOffset = None, 0, 0
return curRun, startOffset, endOffset

def _getFormatFieldAndOffsets(
self,
offset: int,
Expand All @@ -1169,15 +1202,7 @@ def _getFormatFieldAndOffsets(
formatField = textInfos.FormatField()
curRun = None
if calculateOffsets:
runs = self.obj.ppObject.textRange.runs()
for run in runs:
start = run.start - 1
end = start + run.length
if start <= offset < end:
startOffset = start
endOffset = end
curRun = run
break
curRun, startOffset, endOffset = self._getCurrentRun(self)
if not curRun:
curRun = self.obj.ppObject.textRange.characters(offset + 1)
startOffset, endOffset = offset, self._endOffset
Expand Down Expand Up @@ -1213,6 +1238,17 @@ def _getFormatFieldAndOffsets(
formatField["link"] = True
return formatField, (startOffset, endOffset)

def _getLinkDataAtCaretPosition(self) -> _LinkData | None:
offset = self._getCaretOffset()
curRun, _startOffset, _endOffset = self._getCurrentRun(offset)
mouseClickSetting = curRun.actionSettings(ppMouseClick)
if mouseClickSetting.action == ppActionHyperlink:
return textInfos._LinkData(
displayText=mouseClickSetting.Hyperlink.TextToDisplay,
destination=mouseClickSetting.Hyperlink.Address,
)
return None

def _setCaretOffset(self, offset: int) -> None:
return self._setSelectionOffsets(offset, offset)

Expand Down Expand Up @@ -1386,16 +1422,9 @@ def __contains__(self, obj):
def event_treeInterceptor_gainFocus(self):
braille.handler.handleGainFocus(self)
self.rootNVDAObject.reportFocus()
self.reportNewSlide(self.hadFocusOnce)
if not self.hadFocusOnce:
self.hadFocusOnce = True
self.reportNewSlide()
else:
info = self.selection
if not info.isCollapsed:
speech.speakPreselectedText(info.text)
else:
info.expand(textInfos.UNIT_LINE)
speech.speakTextInfo(info, reason=controlTypes.OutputReason.CARET, unit=textInfos.UNIT_LINE)

def event_gainFocus(self, obj, nextHandler):
pass
Expand All @@ -1405,9 +1434,22 @@ def event_gainFocus(self, obj, nextHandler):
def makeTextInfo(self, position):
return self.TextInfo(self, position)

def reportNewSlide(self):
self.makeTextInfo(textInfos.POSITION_FIRST).updateCaret()
sayAll.SayAllHandler.readText(sayAll.CURSOR.CARET)
def reportNewSlide(self, suppressSayAll: bool = False):
"""Reports a new slide, activating say all when appropriate.
:param suppressSayAll: When say all should be suppressed always, e.g.
because tree interceptor gets focus multiple times.
"""
doSayAll = not suppressSayAll and config.conf["virtualBuffers"]["autoSayAllOnPageLoad"]
if doSayAll:
self.makeTextInfo(textInfos.POSITION_FIRST).updateCaret()
sayAll.SayAllHandler.readText(sayAll.CURSOR.CARET)
else:
info = self.selection
if not info.isCollapsed:
speech.speakPreselectedText(info.text)
else:
info.expand(textInfos.UNIT_LINE)
speech.speakTextInfo(info, reason=controlTypes.OutputReason.CARET, unit=textInfos.UNIT_LINE)

@scriptHandler.script(
description=_(
Expand Down
Loading

0 comments on commit 0c99151

Please sign in to comment.