fixed #15521: Fixed an accessibility for list view item

This commit is contained in:
Eism 2023-02-23 13:52:56 +02:00 committed by Elnur Ismailzada
parent 186dbacf08
commit 18fcb367db
12 changed files with 167 additions and 1 deletions

View file

@ -368,6 +368,12 @@ int AccessibleItem::accessibleCharacterCount() const
return static_cast<int>(text->plainText().size());
}
int AccessibleItem::accessibleRowIndex() const
{
NOT_IMPLEMENTED;
return 0;
}
bool AccessibleItem::accessibleState(State st) const
{
if (!registered()) {

View file

@ -85,6 +85,9 @@ public:
QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override;
int accessibleCharacterCount() const override;
// ListView item Interface
int accessibleRowIndex() const override;
async::Channel<Property, Val> accessiblePropertyChanged() const override;
async::Channel<State, bool> accessibleStateChanged() const override;

View file

@ -53,6 +53,7 @@ public:
CheckBox,
RadioButton,
ComboBox,
List,
ListItem,
MenuItem,
Range,
@ -148,6 +149,9 @@ public:
virtual QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const = 0;
virtual int accessibleCharacterCount() const = 0;
// ListView item Interface
virtual int accessibleRowIndex() const = 0;
virtual async::Channel<IAccessible::Property, Val> accessiblePropertyChanged() const = 0;
virtual void setState(State state, bool arg) = 0;

View file

@ -662,6 +662,11 @@ int AccessibilityController::accessibleCharacterCount() const
return 0;
}
int AccessibilityController::accessibleRowIndex() const
{
return 0;
}
mu::async::Channel<IAccessible::Property, mu::Val> AccessibilityController::accessiblePropertyChanged() const
{
static async::Channel<IAccessible::Property, Val> ch;

View file

@ -107,6 +107,9 @@ public:
QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override;
int accessibleCharacterCount() const override;
// ListView item Interface
int accessibleRowIndex() const override;
async::Channel<Property, Val> accessiblePropertyChanged() const override;
async::Channel<State, bool> accessibleStateChanged() const override;

View file

@ -153,9 +153,15 @@ QAccessible::State AccessibleItemInterface::state() const
state.focusable = true;
state.focused = item->accessibleState(IAccessible::State::Focused);
} break;
case IAccessible::Role::List: {
state.active = item->accessibleState(IAccessible::State::Active);
} break;
case IAccessible::Role::ListItem: {
state.focusable = true;
state.focused = item->accessibleState(IAccessible::State::Focused);
state.selectable = true;
state.selected = item->accessibleState(IAccessible::State::Selected);
} break;
case IAccessible::Role::Information: {
state.focusable = true;
@ -213,6 +219,7 @@ QAccessible::Role AccessibleItemInterface::role() const
case IAccessible::Role::CheckBox: return QAccessible::CheckBox;
case IAccessible::Role::RadioButton: return QAccessible::RadioButton;
case IAccessible::Role::ComboBox: return QAccessible::ComboBox;
case IAccessible::Role::List: return QAccessible::List;
case IAccessible::Role::ListItem: return QAccessible::ListItem;
case IAccessible::Role::MenuItem: return QAccessible::MenuItem;
case IAccessible::Role::Range: return QAccessible::Slider;
@ -386,6 +393,51 @@ QString AccessibleItemInterface::attributes(int, int* startOffset, int* endOffse
return QString();
}
bool AccessibleItemInterface::isSelected() const
{
return m_object->item()->accessibleState(IAccessible::State::Selected);
}
QList<QAccessibleInterface*> AccessibleItemInterface::columnHeaderCells() const
{
NOT_IMPLEMENTED;
return QList<QAccessibleInterface*>();
}
QList<QAccessibleInterface*> AccessibleItemInterface::rowHeaderCells() const
{
NOT_IMPLEMENTED;
return QList<QAccessibleInterface*>();
}
int AccessibleItemInterface::columnIndex() const
{
NOT_IMPLEMENTED;
return 0;
}
int AccessibleItemInterface::rowIndex() const
{
return m_object->item()->accessibleRowIndex();
}
int AccessibleItemInterface::columnExtent() const
{
NOT_IMPLEMENTED;
return 1;
}
int AccessibleItemInterface::rowExtent() const
{
NOT_IMPLEMENTED;
return 1;
}
QAccessibleInterface* AccessibleItemInterface::table() const
{
return parent();
}
void* AccessibleItemInterface::interface_cast(QAccessible::InterfaceType type)
{
QAccessible::Role itemRole = role();
@ -395,6 +447,17 @@ void* AccessibleItemInterface::interface_cast(QAccessible::InterfaceType type)
return static_cast<QAccessibleTextInterface*>(this);
}
bool isListType = type == QAccessible::InterfaceType::TableCellInterface;
#ifdef Q_OS_WIN
//! NOTE: Without Action and Text interfaces NVDA doesn't work
isListType |= type == QAccessible::InterfaceType::ActionInterface;
#endif
if (isListType && itemRole == QAccessible::ListItem) {
//! NOTE: Without Action and Text interfaces NVDA doesn't work
return static_cast<QAccessibleTableCellInterface*>(this);
}
//! NOTE Not implemented
return nullptr;
}

View file

@ -30,7 +30,8 @@
#include "ui/iinteractiveprovider.h"
namespace mu::accessibility {
class AccessibleItemInterface : public QAccessibleInterface, public QAccessibleValueInterface, public QAccessibleTextInterface
class AccessibleItemInterface : public QAccessibleInterface, public QAccessibleValueInterface, public QAccessibleTextInterface,
public QAccessibleTableCellInterface
{
INJECT(ui::IInteractiveProvider, interactiveProvider)
@ -84,6 +85,18 @@ public:
void scrollToSubstring(int startIndex, int endIndex) override;
QString attributes(int /* offset */, int* startOffset, int* endOffset) const override;
// Table cell(list view item) Interface
bool isSelected() const override;
QList<QAccessibleInterface*> columnHeaderCells() const override;
QList<QAccessibleInterface*> rowHeaderCells() const override;
int columnIndex() const override;
int rowIndex() const override;
int columnExtent() const override;
int rowExtent() const override;
QAccessibleInterface* table() const override;
protected:
void* interface_cast(QAccessible::InterfaceType t) override;

View file

@ -89,6 +89,8 @@ public:
QString accessibleTextAtOffset(int, TextBoundaryType, int*, int*) const override { return QString(); }
int accessibleCharacterCount() const override { return 0; }
int accessibleRowIndex() const override { return 0; }
async::Channel<IAccessible::Property, Val> accessiblePropertyChanged() const override
{
return m_propertyChanged;

View file

@ -365,6 +365,11 @@ mu::async::Channel<IAccessible::State, bool> AccessibleItem::accessibleStateChan
return m_accessibleStateChanged;
}
int AccessibleItem::accessibleRowIndex() const
{
return m_row;
}
void AccessibleItem::classBegin()
{
}
@ -440,6 +445,11 @@ int AccessibleItem::cursorPosition() const
return m_cursorPosition;
}
int AccessibleItem::row() const
{
return m_row;
}
bool AccessibleItem::ignored() const
{
return m_ignored;
@ -621,6 +631,16 @@ void AccessibleItem::setCursorPosition(int cursorPosition)
m_accessiblePropertyChanged.send(IAccessible::Property::TextCursor, Val());
}
void AccessibleItem::setRow(int row)
{
if (m_row == row) {
return;
}
m_row = row;
emit rowChanged();
}
void AccessibleItem::setIgnored(bool ignored)
{
if (m_ignored == ignored) {

View file

@ -56,6 +56,7 @@ public:
CheckBox,
RadioButton,
ComboBox,
List,
ListItem,
MenuItem,
Range,
@ -84,6 +85,8 @@ class AccessibleItem : public QObject, public QQmlParserStatus, public accessibi
Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged)
Q_PROPERTY(bool ignored READ ignored WRITE setIgnored NOTIFY ignoredChanged)
Q_PROPERTY(QQuickItem * visualItem READ visualItem WRITE setVisualItem NOTIFY visualItemChanged)
@ -133,6 +136,9 @@ public:
QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override;
int accessibleCharacterCount() const override;
// ListView item Interface
int accessibleRowIndex() const override;
async::Channel<Property, Val> accessiblePropertyChanged() const override;
void setState(State st, bool arg) override;
@ -159,6 +165,8 @@ public:
int selectionEnd() const;
int cursorPosition() const;
int row() const;
bool ignored() const;
QQuickItem* visualItem() const;
@ -178,6 +186,7 @@ public slots:
void setSelectionStart(int selectionStart);
void setSelectionEnd(int selectionEnd);
void setCursorPosition(int cursorPosition);
void setRow(int row);
void setIgnored(bool ignored);
void setVisualItem(QQuickItem* item);
void setWindow(QWindow* window);
@ -196,6 +205,7 @@ signals:
void selectionStartChanged();
void selectionEndChanged();
void cursorPositionChanged();
void rowChanged();
void ignoredChanged(bool ignored);
void visualItemChanged(QQuickItem* item);
void stateChanged();
@ -224,6 +234,7 @@ private:
int m_selectionStart = 0;
int m_selectionEnd = 0;
int m_cursorPosition = 0;
int m_row = 0;
bool m_ignored = false;
QQuickItem* m_visualItem = nullptr;
QWindow* m_window = nullptr;

View file

@ -40,6 +40,37 @@ ListView {
ScrollBar.vertical: root.arrowControlsAvailable ? null : scrollBarComp.createObject(root)
ScrollBar.horizontal: root.arrowControlsAvailable ? null : scrollBarComp.createObject(root)
property alias navigation: navPanel
property alias accessible: navPanel.accessible
NavigationPanel {
id: navPanel
name: root.objectName !== "" ? root.objectName : "ListView"
enabled: root.enabled && root.visible
accessible.role: MUAccessible.List
accessible.name: "List"
accessible.visualItem: root
accessible.enabled: navPanel.enabled
onNavigationEvent: function(event) {
if (event.type === NavigationEvent.AboutActive) {
for (var i = 0; i < root.count; ++i) {
var item = root.itemAtIndex(i)
if (item.isSelected) {
event.setData("controlIndex", [item.navigation.row, item.navigation.column])
return
}
}
var firstItem = root.itemAtIndex(0)
if (Boolean(firstItem)) {
event.setData("controlIndex", [firstItem.navigation.row, firstItem.navigation.column])
}
}
}
}
Component {
id: scrollBarComp

View file

@ -117,6 +117,9 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
accessible.accessibleParent: navPanel.accessible
accessible.name: titleLabel.text
onModelChanged: {
groupsView.currentIndex = Qt.binding(() => (root.currentGroupIndex))
}
@ -131,7 +134,9 @@ Item {
navigation.name: modelData
navigation.panel: navPanel
navigation.row: 2 + model.index
navigation.accessible.accessibleParent: groupsView.accessible
navigation.accessible.name: itemTitleLabel.text
navigation.accessible.row: model.index
StyledTextLabel {
id: itemTitleLabel