Initial commit
This commit is contained in:
105
src/widgets/accessible_text_dialog.py
Normal file
105
src/widgets/accessible_text_dialog.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Accessible text display dialog - single point of truth for showing text to screen reader users
|
||||
Based on the implementation from Bifrost
|
||||
"""
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QTextEdit, QDialogButtonBox
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
|
||||
class AccessibleTextDialog(QDialog):
|
||||
"""
|
||||
Single reusable dialog for displaying text content accessibly to screen readers.
|
||||
Provides keyboard navigation, text selection, and proper focus management.
|
||||
"""
|
||||
|
||||
def __init__(self, title: str, content: str, dialogType: str = "info", parent=None):
|
||||
"""
|
||||
Initialize accessible text dialog
|
||||
|
||||
Args:
|
||||
title: Window title
|
||||
content: Text content to display
|
||||
dialogType: "info", "error", "success", or "warning" - affects accessible name
|
||||
parent: Parent widget
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle(title)
|
||||
self.setModal(True)
|
||||
|
||||
# Size based on content length
|
||||
if len(content) > 500:
|
||||
self.setMinimumSize(600, 400)
|
||||
elif len(content) > 200:
|
||||
self.setMinimumSize(500, 300)
|
||||
else:
|
||||
self.setMinimumSize(400, 200)
|
||||
|
||||
self.setupUi(content, dialogType)
|
||||
|
||||
def setupUi(self, content: str, dialogType: str):
|
||||
"""Setup the dialog UI with accessible text widget"""
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
# Create accessible text edit widget
|
||||
self.textEdit = QTextEdit()
|
||||
self.textEdit.setPlainText(content)
|
||||
self.textEdit.setReadOnly(True)
|
||||
|
||||
# Set accessible name based on dialog type
|
||||
accessibleNames = {
|
||||
"info": "Information Text",
|
||||
"error": "Error Details",
|
||||
"warning": "Warning Information",
|
||||
"success": "Success Information"
|
||||
}
|
||||
self.textEdit.setAccessibleName(accessibleNames.get(dialogType, "Dialog Text"))
|
||||
|
||||
# Enable keyboard text selection and navigation
|
||||
self.textEdit.setTextInteractionFlags(
|
||||
Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse
|
||||
)
|
||||
|
||||
layout.addWidget(self.textEdit)
|
||||
|
||||
# Button box
|
||||
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
|
||||
buttonBox.accepted.connect(self.accept)
|
||||
layout.addWidget(buttonBox)
|
||||
|
||||
# Focus the text edit first so user can immediately read content
|
||||
self.textEdit.setFocus()
|
||||
|
||||
@classmethod
|
||||
def showInfo(cls, title: str, content: str, parent=None):
|
||||
"""Convenience method for info dialogs"""
|
||||
dialog = cls(title, content, "info", parent)
|
||||
dialog.exec()
|
||||
|
||||
@classmethod
|
||||
def showError(cls, title: str, message: str, details: str = None, parent=None):
|
||||
"""Convenience method for error dialogs with optional details"""
|
||||
if details:
|
||||
content = f"{message}\n\nError Details:\n{details}"
|
||||
else:
|
||||
content = message
|
||||
dialog = cls(title, content, "error", parent)
|
||||
dialog.exec()
|
||||
|
||||
@classmethod
|
||||
def showSuccess(cls, title: str, message: str, details: str = None, parent=None):
|
||||
"""Convenience method for success dialogs with optional details"""
|
||||
if details:
|
||||
content = f"{message}\n\n{details}"
|
||||
else:
|
||||
content = message
|
||||
dialog = cls(title, content, "success", parent)
|
||||
dialog.exec()
|
||||
|
||||
@classmethod
|
||||
def showWarning(cls, title: str, content: str, parent=None):
|
||||
"""Convenience method for warning dialogs"""
|
||||
dialog = cls(title, content, "warning", parent)
|
||||
dialog.exec()
|
||||
Reference in New Issue
Block a user