More pep8 fixes. A tiny bit of refactoring.
This commit is contained in:
@ -2,18 +2,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from collections import Counter
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from collections import Counter
|
||||
|
||||
|
||||
class AttributeManager():
|
||||
class AttributeManager:
|
||||
def __init__(self):
|
||||
self.currAttributes = None
|
||||
self.prevAttributes = None
|
||||
self.currAttributeDelta = ''
|
||||
self.currAttributeDelta = ""
|
||||
self.currAttributeCursor = None
|
||||
self.prefAttributeCursor = None
|
||||
self.init_default_attributes()
|
||||
@ -58,7 +59,7 @@ class AttributeManager():
|
||||
return self.currAttributeDelta
|
||||
|
||||
def reset_attribute_delta(self):
|
||||
self.currAttributeDelta = ''
|
||||
self.currAttributeDelta = ""
|
||||
|
||||
def set_attribute_delta(self, currAttributeDelta):
|
||||
self.currAttributeDelta = currAttributeDelta
|
||||
@ -92,10 +93,11 @@ class AttributeManager():
|
||||
try:
|
||||
return self.defaultAttributes[0]
|
||||
except Exception as e:
|
||||
self.env['runtime']['DebugManager'].write_debug_out(
|
||||
'AttributeManager get_attribute_by_xy: Error accessing default attributes: ' +
|
||||
str(e),
|
||||
debug.DebugLevel.ERROR)
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"AttributeManager get_attribute_by_xy: Error accessing default attributes: "
|
||||
+ str(e),
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
return None
|
||||
|
||||
def append_default_attributes(self, attribute):
|
||||
@ -107,18 +109,20 @@ class AttributeManager():
|
||||
|
||||
def init_default_attributes(self):
|
||||
self.defaultAttributes = [None]
|
||||
self.defaultAttributes.append([
|
||||
'default', # fg
|
||||
'default', # bg
|
||||
False, # bold
|
||||
False, # italics
|
||||
False, # underscore
|
||||
False, # strikethrough
|
||||
False, # reverse
|
||||
False, # blink
|
||||
'default', # fontsize
|
||||
'default' # fontfamily
|
||||
]) # end attribute
|
||||
self.defaultAttributes.append(
|
||||
[
|
||||
"default", # fg
|
||||
"default", # bg
|
||||
False, # bold
|
||||
False, # italics
|
||||
False, # underscore
|
||||
False, # strikethrough
|
||||
False, # reverse
|
||||
False, # blink
|
||||
"default", # fontsize
|
||||
"default", # fontfamily
|
||||
]
|
||||
) # end attribute
|
||||
|
||||
def is_default_attribute(self, attribute):
|
||||
return attribute in self.defaultAttributes
|
||||
@ -128,7 +132,9 @@ class AttributeManager():
|
||||
return False
|
||||
cursor_pos = cursor.copy()
|
||||
try:
|
||||
attribute = self.get_attribute_by_xy(cursor_pos['x'], cursor_pos['y'])
|
||||
attribute = self.get_attribute_by_xy(
|
||||
cursor_pos["x"], cursor_pos["y"]
|
||||
)
|
||||
|
||||
if update:
|
||||
self.set_last_cursor_attribute(attribute)
|
||||
@ -142,7 +148,7 @@ class AttributeManager():
|
||||
return False
|
||||
return True
|
||||
|
||||
def format_attributes(self, attribute, attribute_format_string=''):
|
||||
def format_attributes(self, attribute, attribute_format_string=""):
|
||||
# "black",
|
||||
# "red",
|
||||
# "green",
|
||||
@ -163,124 +169,149 @@ class AttributeManager():
|
||||
# "blink"
|
||||
# "fontsieze"
|
||||
# "fontfamily"
|
||||
if attribute_format_string == '':
|
||||
attribute_format_string = self.env['runtime']['SettingsManager'].get_setting(
|
||||
'general', 'attribute_format_string')
|
||||
if attribute_format_string == "":
|
||||
attribute_format_string = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "attribute_format_string")
|
||||
if not attribute_format_string:
|
||||
return ''
|
||||
if attribute_format_string == '':
|
||||
return ''
|
||||
return ""
|
||||
if attribute_format_string == "":
|
||||
return ""
|
||||
if not attribute:
|
||||
return ''
|
||||
return ""
|
||||
if len(attribute) != 10:
|
||||
return ''
|
||||
return ""
|
||||
|
||||
# 0 FG color (name)
|
||||
try:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFGColor', _(attribute[0]))
|
||||
"fenrirFGColor", _(attribute[0])
|
||||
)
|
||||
except Exception as e:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFGColor', '')
|
||||
"fenrirFGColor", ""
|
||||
)
|
||||
|
||||
# 1 BG color (name)
|
||||
try:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirBGColor', _(attribute[1]))
|
||||
"fenrirBGColor", _(attribute[1])
|
||||
)
|
||||
except Exception as e:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirBGColor', '')
|
||||
"fenrirBGColor", ""
|
||||
)
|
||||
|
||||
# 2 bold (True/ False)
|
||||
try:
|
||||
if attribute[2]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirBold', _('bold'))
|
||||
"fenrirBold", _("bold")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace('fenrirBold', '')
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
"fenrirBold", ""
|
||||
)
|
||||
|
||||
# 3 italics (True/ False)
|
||||
try:
|
||||
if attribute[3]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirItalics', _('italic'))
|
||||
"fenrirItalics", _("italic")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirItalics', '')
|
||||
"fenrirItalics", ""
|
||||
)
|
||||
|
||||
# 4 underline (True/ False)
|
||||
try:
|
||||
if attribute[4]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirUnderline', _('underline'))
|
||||
"fenrirUnderline", _("underline")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirUnderline', '')
|
||||
"fenrirUnderline", ""
|
||||
)
|
||||
|
||||
# 5 strikethrough (True/ False)
|
||||
try:
|
||||
if attribute[5]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirStrikethrough', _('strikethrough'))
|
||||
"fenrirStrikethrough", _("strikethrough")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirStrikethrough', '')
|
||||
"fenrirStrikethrough", ""
|
||||
)
|
||||
|
||||
# 6 reverse (True/ False)
|
||||
try:
|
||||
if attribute[6]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirReverse', _('reverse'))
|
||||
"fenrirReverse", _("reverse")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirReverse', '')
|
||||
"fenrirReverse", ""
|
||||
)
|
||||
|
||||
# 7 blink (True/ False)
|
||||
try:
|
||||
if attribute[7]:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirBlink', _('blink'))
|
||||
"fenrirBlink", _("blink")
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirBlink', '')
|
||||
"fenrirBlink", ""
|
||||
)
|
||||
|
||||
# 8 font size (int/ string)
|
||||
try:
|
||||
try:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFontSize', int(attribute[8]))
|
||||
"fenrirFontSize", int(attribute[8])
|
||||
)
|
||||
except Exception as e:
|
||||
self.env['runtime']['DebugManager'].write_debug_out(
|
||||
'AttributeManager formatAttributeToString: Error formatting font size as int: ' +
|
||||
str(e),
|
||||
debug.DebugLevel.ERROR)
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"AttributeManager formatAttributeToString: Error formatting font size as int: "
|
||||
+ str(e),
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
try:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFontSize', str(attribute[8]))
|
||||
"fenrirFontSize", str(attribute[8])
|
||||
)
|
||||
except Exception as e:
|
||||
self.env['runtime']['DebugManager'].write_debug_out(
|
||||
'AttributeManager formatAttributeToString: Error formatting font size as string: ' +
|
||||
str(e),
|
||||
debug.DebugLevel.ERROR)
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"AttributeManager formatAttributeToString: Error formatting font size as string: "
|
||||
+ str(e),
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFontSize', _('default'))
|
||||
"fenrirFontSize", _("default")
|
||||
)
|
||||
|
||||
# 9 font family (string)
|
||||
try:
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFont', attribute[9])
|
||||
"fenrirFont", attribute[9]
|
||||
)
|
||||
except Exception as e:
|
||||
pass
|
||||
attribute_format_string = attribute_format_string.replace(
|
||||
'fenrirFont', _('default'))
|
||||
"fenrirFont", _("default")
|
||||
)
|
||||
|
||||
return attribute_format_string
|
||||
|
||||
@ -296,7 +327,7 @@ class AttributeManager():
|
||||
- highlighted_text: string of characters that gained highlighting
|
||||
- cursor_position: dict {'x': col, 'y': row} of first highlighted char
|
||||
"""
|
||||
result = ''
|
||||
result = ""
|
||||
curr_cursor = None
|
||||
|
||||
# Early exit conditions - no attribute comparison possible
|
||||
@ -314,8 +345,8 @@ class AttributeManager():
|
||||
return result, curr_cursor
|
||||
|
||||
# Get current screen text to correlate with attribute changes
|
||||
text = self.env['runtime']['ScreenManager'].get_screen_text()
|
||||
text_lines = text.split('\n')
|
||||
text = self.env["runtime"]["ScreenManager"].get_screen_text()
|
||||
text_lines = text.split("\n")
|
||||
|
||||
# Sanity check: text lines must match attribute array dimensions
|
||||
if len(text_lines) != len(self.currAttributes):
|
||||
@ -327,32 +358,37 @@ class AttributeManager():
|
||||
# This line has attribute changes - examine each character
|
||||
# position
|
||||
for column in range(len(self.prevAttributes[line])):
|
||||
if self.prevAttributes[line][column] == self.currAttributes[line][column]:
|
||||
if (
|
||||
self.prevAttributes[line][column]
|
||||
== self.currAttributes[line][column]
|
||||
):
|
||||
# No change at this position
|
||||
continue
|
||||
# Attribute changed at this position - check if it's worth
|
||||
# announcing
|
||||
if self.is_useful_for_tracking(
|
||||
line, column, self.currAttributes, self.prevAttributes):
|
||||
line, column, self.currAttributes, self.prevAttributes
|
||||
):
|
||||
# First highlighted character becomes cursor position
|
||||
# for navigation
|
||||
if not curr_cursor:
|
||||
curr_cursor = {'x': column, 'y': line}
|
||||
curr_cursor = {"x": column, "y": line}
|
||||
# Accumulate highlighted characters
|
||||
result += text_lines[line][column]
|
||||
# Add space between lines of highlighted text for speech
|
||||
# clarity
|
||||
result += ' '
|
||||
result += " "
|
||||
return result, curr_cursor
|
||||
|
||||
def is_useful_for_tracking(
|
||||
self,
|
||||
line,
|
||||
column,
|
||||
currAttributes,
|
||||
prevAttributes,
|
||||
attribute=1,
|
||||
mode='zaxe'):
|
||||
self,
|
||||
line,
|
||||
column,
|
||||
currAttributes,
|
||||
prevAttributes,
|
||||
attribute=1,
|
||||
mode="zaxe",
|
||||
):
|
||||
"""
|
||||
Determines if an attribute change at a specific position is worth announcing.
|
||||
|
||||
@ -378,29 +414,46 @@ class AttributeManager():
|
||||
|
||||
useful = False
|
||||
|
||||
if mode == 'default':
|
||||
if mode == "default":
|
||||
# Simple mode: announce any non-default attribute
|
||||
useful = not self.is_default_attribute(currAttributes[line][column])
|
||||
useful = not self.is_default_attribute(
|
||||
currAttributes[line][column]
|
||||
)
|
||||
|
||||
elif (mode == 'zaxe') or (mode == ''):
|
||||
elif (mode == "zaxe") or (mode == ""):
|
||||
# Context-aware mode: only announce attributes that stand out from surroundings
|
||||
# This prevents announcing entire blocks of highlighted text character by character
|
||||
# by checking if the attribute differs from adjacent lines
|
||||
|
||||
if line == 0:
|
||||
# Top line: compare against lines below
|
||||
useful = (currAttributes[line][column][attribute] != currAttributes[line + 1][column][attribute]) and (
|
||||
currAttributes[line][column][attribute] != currAttributes[line + 2][column][attribute])
|
||||
useful = (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line + 1][column][attribute]
|
||||
) and (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line + 2][column][attribute]
|
||||
)
|
||||
elif line >= len(prevAttributes):
|
||||
# Bottom line: compare against lines above
|
||||
useful = (currAttributes[line][column][attribute] != currAttributes[line - 1][column][attribute]) and (
|
||||
currAttributes[line][column][attribute] != currAttributes[line - 2][column][attribute])
|
||||
useful = (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line - 1][column][attribute]
|
||||
) and (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line - 2][column][attribute]
|
||||
)
|
||||
else:
|
||||
# Middle lines: compare against both directions
|
||||
useful = (currAttributes[line][column][attribute] != currAttributes[line + 1][column][attribute]) and (
|
||||
currAttributes[line][column][attribute] != currAttributes[line - 1][column][attribute])
|
||||
useful = (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line + 1][column][attribute]
|
||||
) and (
|
||||
currAttributes[line][column][attribute]
|
||||
!= currAttributes[line - 1][column][attribute]
|
||||
)
|
||||
|
||||
elif mode == 'barrier':
|
||||
elif mode == "barrier":
|
||||
# Barrier mode: future enhancement for detecting screen
|
||||
# boundaries/separators
|
||||
useful = True
|
||||
|
Reference in New Issue
Block a user