Skip to content

Commit 9c870b2

Browse files
authored
Merge 5a7e57e into 47695ac
2 parents 47695ac + 5a7e57e commit 9c870b2

6 files changed

Lines changed: 85 additions & 0 deletions

File tree

source/braille.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from config.configFlags import (
4545
ShowMessages,
4646
TetherTo,
47+
ParagraphStartMarker,
4748
BrailleMode,
4849
ReportTableHeaders,
4950
OutputMode,
@@ -1142,6 +1143,14 @@ def getFormatFieldBraille(field, fieldCache, isAtStart, formatConfig):
11421143
"""
11431144
textList = []
11441145
if isAtStart:
1146+
brailleConfig = config.conf["braille"]
1147+
if brailleConfig["readByParagraph"]:
1148+
index = brailleConfig["paragraphStartMarker"]
1149+
paragraphStartMarker = [x.value for x in ParagraphStartMarker][index]
1150+
else:
1151+
paragraphStartMarker = None
1152+
if paragraphStartMarker:
1153+
textList.append(brailleConfig["paragraphStartMarker"])
11451154
if formatConfig["reportLineNumber"]:
11461155
lineNumber = field.get("line-number")
11471156
if lineNumber:
@@ -1899,6 +1908,21 @@ def _set_windowEndPos(self, endPos):
18991908
break
19001909
except ValueError:
19011910
pass
1911+
# When word wrap is enabled, the first block of spaces may be removed from the current window.
1912+
# This may prevent displaying the start of paragraphs.
1913+
brailleConfig = config.conf["braille"]
1914+
if brailleConfig["readByParagraph"]:
1915+
index = brailleConfig["paragraphStartMarker"]
1916+
paragraphStartMarker = [x.value for x in ParagraphStartMarker][index]
1917+
else:
1918+
paragraphStartMarker = None
1919+
if paragraphStartMarker and self.regions[-1].rawText.startswith(
1920+
paragraphStartMarker + TEXT_SEPARATOR,
1921+
):
1922+
region, regionStart, regionEnd = list(self.regionsWithPositions)[-1]
1923+
# Show paragraph start indicator if it is now at the left of the current braille window
1924+
if startPos <= len(paragraphStartMarker) + 1:
1925+
startPos = self.regionPosToBufferPos(region, regionStart)
19021926
self.windowStartPos = startPos
19031927

19041928
def _nextWindow(self):

source/config/configFlags.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,30 @@ def _displayStringLabels(self):
251251
# Translators: A label for an option to choose a method of reporting information, e.g. font attributes.
252252
self.SPEECH_AND_BRAILLE: _("Speech and braille"),
253253
}
254+
255+
256+
class ParagraphStartMarker(DisplayStringStrEnum):
257+
NONE = ""
258+
SPACE = " "
259+
# Translators: This is a paragraph start marker used in braille.
260+
# The default symbol is the pilcrow,
261+
# a symbol also known as "paragraph symbol" or "paragraph marker".
262+
# This symbol should translate in braille via LibLouis automatically.
263+
# If there is a more appropriate character for your locale,
264+
# consider overwriting this (e.g. for Ge'ez ፨).
265+
# You can also use Unicode Braille such as ⠘⠏.
266+
# Ensure this is consistent with other strings with the context "paragraphMarker".
267+
PILCROW = pgettext("paragraphMarker", "¶")
268+
269+
@property
270+
def _displayStringLabels(self):
271+
return {
272+
# Translators: This is a label for a paragraph start marker.
273+
self.NONE: pgettext("paragraphMarker", "No paragraph start marker (default)"),
274+
# Translators: This is a label for a paragraph start marker.
275+
self.SPACE: pgettext("paragraphMarker", "Double space ( )"),
276+
# Translators: This is a label for a paragraph start marker.
277+
# Pilcrow is a symbol also known as "paragraph symbol" or "paragraph marker".
278+
# Ensure this is consistent with other strings with the context "paragraphMarker".
279+
self.PILCROW: pgettext("paragraphMarker", "Pilcrow (¶)"),
280+
}

source/config/configSpec.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
reviewRoutingMovesSystemCaret = featureFlag(\
8686
optionsEnum="ReviewRoutingMovesSystemCaretFlag", behaviorOfDefault="NEVER")
8787
readByParagraph = boolean(default=false)
88+
paragraphStartMarker = integer(min=0, max=2, default=0)
8889
wordWrap = boolean(default=true)
8990
unicodeNormalization = featureFlag(optionsEnum="BoolFlag", behaviorOfDefault="disabled")
9091
focusContextPresentation = option("changedContext", "fill", "scroll", default="changedContext")

source/gui/settingsDialogs.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
NVDAKey,
3232
ShowMessages,
3333
TetherTo,
34+
ParagraphStartMarker,
3435
ReportLineIndentation,
3536
ReportTableHeaders,
3637
ReportCellBorders,
@@ -4386,8 +4387,22 @@ def makeSettings(self, settingsSizer):
43864387
wx.CheckBox(self.followCursorGroupBox, label=readByParagraphText),
43874388
)
43884389
self.bindHelpEvent("BrailleSettingsReadByParagraph", self.readByParagraphCheckBox)
4390+
self.readByParagraphCheckBox.Bind(wx.EVT_CHECKBOX, self.onReadByParagraphChange)
43894391
self.readByParagraphCheckBox.Value = config.conf["braille"]["readByParagraph"]
43904392

4393+
# Translators: This is a label for a combo-box in the Braille settings panel to select paragraph start markers.
4394+
labelText = _("Paragraph start marker:")
4395+
self.paragraphStartMarkersComboBox = followCursorGroupHelper.addLabeledControl(
4396+
labelText,
4397+
wx.Choice,
4398+
choices=[marker.displayString for marker in ParagraphStartMarker],
4399+
)
4400+
self.bindHelpEvent("BrailleParagraphStartMarkers", self.paragraphStartMarkersComboBox)
4401+
index = config.conf["braille"]["paragraphStartMarker"]
4402+
self.paragraphStartMarkersComboBox.SetSelection(index)
4403+
if not self.readByParagraphCheckBox.GetValue():
4404+
self.paragraphStartMarkersComboBox.Disable()
4405+
43914406
# Translators: The label for a setting in braille settings to select how the context for the focus object should be presented on a braille display.
43924407
focusContextPresentationLabelText = _("Focus context presentation:")
43934408
self.focusContextPresentationValues = [x[0] for x in braille.focusContextPresentations]
@@ -4494,6 +4509,7 @@ def onSave(self):
44944509
braille.handler.setTether(tetherChoice, auto=False)
44954510
self.brailleReviewRoutingMovesSystemCaretCombo.saveCurrentValueToConf()
44964511
config.conf["braille"]["readByParagraph"] = self.readByParagraphCheckBox.Value
4512+
config.conf["braille"]["paragraphStartMarker"] = self.paragraphStartMarkersComboBox.GetSelection()
44974513
config.conf["braille"]["wordWrap"] = self.wordWrapCheckBox.Value
44984514
self.unicodeNormalizationCombo.saveCurrentValueToConf()
44994515
config.conf["braille"]["focusContextPresentation"] = self.focusContextPresentationValues[
@@ -4520,6 +4536,9 @@ def onTetherToChange(self, evt: wx.CommandEvent) -> None:
45204536
tetherChoice = [x.value for x in TetherTo][evt.GetSelection()]
45214537
self.brailleReviewRoutingMovesSystemCaretCombo.Enable(tetherChoice != TetherTo.FOCUS.value)
45224538

4539+
def onReadByParagraphChange(self, evt: wx.CommandEvent):
4540+
self.paragraphStartMarkersComboBox.Enable(evt.IsChecked())
4541+
45234542
def _onModeChange(self, evt: wx.CommandEvent):
45244543
self.followCursorGroupBox.Enable(not evt.GetSelection())
45254544

user_docs/en/changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
The available options are:
1414
* Liblouis (default): Uses formatting markers defined in the selected braille table.
1515
* Tags: Uses start and end tags to denote where certain font attributes begin and end. (#16864)
16+
* When the "Read by paragraph" option is enabled, NVDA can now be configured to indicate the start of paragraphs in braille. (#16895, @nvdaes)
1617
* The timeout to perform a multiple keypress is now configurable; this may be especially useful for people with dexterity impairment. (#11929, @CyrilleB79)
1718

1819
### Changes

user_docs/en/userGuide.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,6 +2163,19 @@ This means that you do not have to scroll the display at the end of each line ev
21632163
This may allow for more fluent reading of large amounts of text.
21642164
It is disabled by default.
21652165

2166+
##### Paragraph start marker {#BrailleParagraphStartMarkers}
2167+
2168+
If "Read by paragraph" is checked, the selected start marker will be displayed to indicate the start of a paragraph.
2169+
This can be especially helpful in applications used to read large pieces of text, like structured documents or books.
2170+
In such documents, knowing where paragraphs start may be useful to understand the structure of the content, or to set bookmarks or annotations based on paragraph position.
2171+
2172+
The options include using double space for softer paragraph breaks, or alternatively the paragraph symbol, Pilcrow (¶), for more obvious paragraph breaks.
2173+
2174+
| . {.hideHeaderRow} |.|
2175+
|---|---|
2176+
|Options |No paragraph start marker, Double space ( ), Pilcrow (¶)|
2177+
|Default |No paragraph start marker|
2178+
21662179
##### Focus context presentation {#BrailleSettingsFocusContextPresentation}
21672180

21682181
This option allows you to choose what context information NVDA will show on the braille display when an object gets focus.

0 commit comments

Comments
 (0)