%PDF- %PDF-
Direktori : /usr/lib/python3/dist-packages/orca/ |
Current File : //usr/lib/python3/dist-packages/orca/ax_value.py |
# Orca # # Copyright 2024 Igalia, S.L. # Copyright 2024 GNOME Foundation Inc. # Author: Joanmarie Diggs <jdiggs@igalia.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., Franklin Street, Fifth Floor, # Boston MA 02110-1301 USA. """ Utilities for obtaining value-related information about accessible objects. These utilities are app-type- and toolkit-agnostic. Utilities that might have different implementations or results depending on the type of app (e.g. terminal, chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). N.B. There are currently utilities that should never have custom implementations that live in script_utilities.py files. These will be moved over time. """ __id__ = "$Id$" __version__ = "$Revision$" __date__ = "$Date$" __copyright__ = "Copyright (c) 2024 Igalia, S.L." \ "Copyright (c) 2024 GNOME Foundation Inc." __license__ = "LGPL" import threading import time import gi gi.require_version("Atspi", "2.0") from gi.repository import Atspi from . import debug from .ax_object import AXObject from .ax_utilities import AXUtilities class AXValue: """Utilities for obtaining value-related information about accessible objects.""" LAST_KNOWN_VALUE = {} _lock = threading.Lock() @staticmethod def _clear_stored_data(): """Clears any data we have cached for objects""" while True: time.sleep(60) msg = "AXValue: Clearing local cache." debug.printMessage(debug.LEVEL_INFO, msg, True) AXValue.LAST_KNOWN_VALUE.clear() @staticmethod def start_cache_clearing_thread(): """Starts thread to periodically clear cached details.""" thread = threading.Thread(target=AXValue._clear_stored_data) thread.daemon = True thread.start() @staticmethod def did_value_change(obj): """Returns True if the current value changed.""" if not AXObject.supports_value(obj): return False old_value = AXValue.LAST_KNOWN_VALUE.get(hash(obj)) result = old_value != AXValue._get_current_value(obj) if result: tokens = ["AXValue: Previous value of", obj, f"was {old_value}"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return result @staticmethod def _get_current_value(obj): """Returns the current value of obj.""" if not AXObject.supports_value(obj): return 0 try: value = Atspi.Value.get_current_value(obj) except Exception as error: msg = f"AXValue: Exception in _get_current_value: {error}" debug.printMessage(debug.LEVEL_INFO, msg, True) return 0 tokens = ["AXValue: Current value of", obj, f"is {value}"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return value @staticmethod def get_current_value(obj): """Returns the current value of obj.""" if not AXObject.supports_value(obj): return 0 value = AXValue._get_current_value(obj) AXValue.LAST_KNOWN_VALUE[hash(obj)] = value return value @staticmethod def get_current_value_text(obj): """Returns the app-provided text-alternative for the current value of obj.""" text = AXObject.get_attribute(obj, "valuetext", False) or "" if text: tokens = ["AXValue: valuetext attribute for", obj, f"is '{text}'"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return text if not AXObject.supports_value(obj): return "" try: value = Atspi.Value.get_text(obj) except Exception as error: msg = f"AXValue: Exception in get_current_value_text: {error}" debug.printMessage(debug.LEVEL_INFO, msg, True) value = "" tokens = ["AXValue: Value text of", obj, f"is '{value}'"] debug.printTokens(debug.LEVEL_INFO, tokens, True) if value: return value current = AXValue._get_current_value(obj) if abs(current) < 1 and current != 0: str_current = str(current) decimal_places = len(str_current.split('.')[1]) else: decimal_places = 0 return f"{current:.{decimal_places}f}" @staticmethod def get_value_as_percent(obj): """Returns the current value as a percent, or None if that is not applicable.""" if not AXObject.supports_value(obj): return None value = AXValue._get_current_value(obj) if AXUtilities.is_indeterminate(obj) and value <= 0: tokens = ["AXValue:", obj, "has state indeterminate"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return None minimum = AXValue.get_minimum_value(obj) maximum = AXValue.get_maximum_value(obj) if minimum == maximum: return None result = int((value / (maximum - minimum)) * 100) tokens = ["AXValue: Current value of", obj, f"as percent is is {result}"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return result @staticmethod def get_minimum_value(obj): """Returns the minimum value of obj.""" if not AXObject.supports_value(obj): return 0 try: value = Atspi.Value.get_minimum_value(obj) except Exception as error: msg = f"AXValue: Exception in get_minimum_value: {error}" debug.printMessage(debug.LEVEL_INFO, msg, True) return 0 tokens = ["AXValue: Minimum value of", obj, f"is {value}"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return value @staticmethod def get_maximum_value(obj): """Returns the maximum value of obj.""" if not AXObject.supports_value(obj): return 0 try: value = Atspi.Value.get_maximum_value(obj) except Exception as error: msg = f"AXValue: Exception in get_maximum_value: {error}" debug.printMessage(debug.LEVEL_INFO, msg, True) return 0 tokens = ["AXValue: Maximum value of", obj, f"is {value}"] debug.printTokens(debug.LEVEL_INFO, tokens, True) return value AXValue.start_cache_clearing_thread()