Spaces:
Running
Running
File size: 5,181 Bytes
399b80c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import platform
from openspace.utils.logging import Logger
from typing import Dict, Any, Optional
logger = Logger.get_logger(__name__)
platform_name = platform.system()
class AccessibilityHelper:
def __init__(self):
self.platform = platform_name
self.adapter = None
try:
if platform_name == "Darwin":
from ..platform_adapters.macos_adapter import MacOSAdapter
self.adapter = MacOSAdapter()
elif platform_name == "Linux":
from ..platform_adapters.linux_adapter import LinuxAdapter
self.adapter = LinuxAdapter()
elif platform_name == "Windows":
from ..platform_adapters.windows_adapter import WindowsAdapter
self.adapter = WindowsAdapter()
except ImportError as e:
logger.warning(f"Failed to import platform adapter: {e}")
def get_tree(self, max_depth: int = 10) -> Dict[str, Any]:
if not self.adapter:
return {
'error': f'No adapter available for {self.platform}',
'platform': self.platform
}
try:
return self.adapter.get_accessibility_tree(max_depth=max_depth)
except Exception as e:
logger.error(f"Failed to get accessibility tree: {e}")
return {
'error': str(e),
'platform': self.platform
}
def is_available(self) -> bool:
return self.adapter is not None and hasattr(self.adapter, 'available') and self.adapter.available
def find_element_by_name(self, tree: Dict[str, Any], name: str) -> Optional[Dict[str, Any]]:
if not tree or 'tree' not in tree:
return None
return self._search_tree(tree['tree'], 'name', name)
def find_element_by_role(self, tree: Dict[str, Any], role: str) -> Optional[Dict[str, Any]]:
if not tree or 'tree' not in tree:
return None
return self._search_tree(tree['tree'], 'role', role)
def _search_tree(self, node: Dict[str, Any], key: str, value: str) -> Optional[Dict[str, Any]]:
if not node:
return None
# Check current node
if key in node and node[key] == value:
return node
# Recursively search child nodes
if 'children' in node:
for child in node['children']:
result = self._search_tree(child, key, value)
if result:
return result
return None
def flatten_tree(self, tree: Dict[str, Any]) -> list:
if not tree or 'tree' not in tree:
return []
result = []
self._flatten_node(tree['tree'], result)
return result
def _flatten_node(self, node: Dict[str, Any], result: list):
"""Recursively flatten nodes"""
if not node:
return
# Add current node (remove children)
node_copy = {k: v for k, v in node.items() if k != 'children'}
result.append(node_copy)
# Recursively process child nodes
if 'children' in node:
for child in node['children']:
self._flatten_node(child, result)
def get_visible_elements(self, tree: Dict[str, Any]) -> list:
all_elements = self.flatten_tree(tree)
visible = []
for element in all_elements:
if self.platform == "Linux":
if 'states' in element and 'showing' in element.get('states', []):
visible.append(element)
elif self.platform == "Darwin":
if element.get('enabled', False):
visible.append(element)
elif self.platform == "Windows":
if element.get('states', {}).get('is_visible', False):
visible.append(element)
return visible
def get_clickable_elements(self, tree: Dict[str, Any]) -> list:
all_elements = self.flatten_tree(tree)
clickable_roles = [
'button', 'push-button', 'toggle-button', 'radio-button',
'link', 'menu-item', 'AXButton', 'AXLink', 'AXMenuItem'
]
clickable = []
for element in all_elements:
role = element.get('role', '').lower()
if any(cr in role for cr in clickable_roles):
clickable.append(element)
return clickable
def get_statistics(self, tree: Dict[str, Any]) -> Dict[str, Any]:
all_elements = self.flatten_tree(tree)
# Count roles
roles = {}
for element in all_elements:
role = element.get('role', 'unknown')
roles[role] = roles.get(role, 0) + 1
return {
'total_elements': len(all_elements),
'visible_elements': len(self.get_visible_elements(tree)),
'clickable_elements': len(self.get_clickable_elements(tree)),
'roles': roles,
'platform': self.platform
}
|