Accessibility: Improve handling of read-only state

We have been rather sloppy in how read-only versus editable is handled.
According to the definition, editable signifies that in principle a
widget allows the user to change its text. Read-only means that this
ability is (currently) disabled.

Task-number: QTBUG-75002
Change-Id: I5d71843abcdaac52f4a60a1abcac2604341f6c96
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
Frederik Gladhorn 2019-05-06 13:02:57 +02:00
parent 48a12735d8
commit eba3b567d6
6 changed files with 39 additions and 3 deletions

View File

@ -79,7 +79,7 @@ quint64 spiStatesFromQState(QAccessible::State state)
if (state.checkStateMixed)
setSpiStateBit(&spiState, ATSPI_STATE_INDETERMINATE);
if (state.readOnly)
unsetSpiStateBit(&spiState, ATSPI_STATE_EDITABLE);
setSpiStateBit(&spiState, ATSPI_STATE_READ_ONLY);
// if (state.HotTracked)
if (state.defaultButton)
setSpiStateBit(&spiState, ATSPI_STATE_IS_DEFAULT);

View File

@ -454,6 +454,13 @@ QAccessible::Role QAccessibleDisplay::role() const
return QAccessibleWidget::role();
}
QAccessible::State QAccessibleDisplay::state() const
{
QAccessible::State s = QAccessibleWidget::state();
s.readOnly = true;
return s;
}
QString QAccessibleDisplay::text(QAccessible::Text t) const
{
QString str;
@ -732,10 +739,9 @@ QAccessible::State QAccessibleLineEdit::state() const
QAccessible::State state = QAccessibleWidget::state();
QLineEdit *l = lineEdit();
state.editable = true;
if (l->isReadOnly())
state.readOnly = true;
else
state.editable = true;
if (l->echoMode() != QLineEdit::Normal)
state.passwordEdit = true;

View File

@ -116,6 +116,7 @@ public:
QString text(QAccessible::Text t) const override;
QAccessible::Role role() const override;
QAccessible::State state() const override;
QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >relations(QAccessible::Relation match = QAccessible::AllRelations) const override;
void *interface_cast(QAccessible::InterfaceType t) override;

View File

@ -1369,6 +1369,12 @@ void QLineEdit::setReadOnly(bool enable)
QEvent event(QEvent::ReadOnlyChange);
QCoreApplication::sendEvent(this, &event);
update();
#ifndef QT_NO_ACCESSIBILITY
QAccessible::State changedState;
changedState.readOnly = true;
QAccessibleStateChangeEvent ev(this, changedState);
QAccessible::updateAccessibility(&ev);
#endif
}
}

View File

@ -2045,6 +2045,15 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(!iface->state().selectable);
QVERIFY(iface->state().selectableText);
QVERIFY(!iface->state().hasPopup);
QVERIFY(!iface->state().readOnly);
QVERIFY(iface->state().editable);
le->setReadOnly(true);
QVERIFY(iface->state().editable);
QVERIFY(iface->state().readOnly);
le->setReadOnly(false);
QVERIFY(!iface->state().readOnly);
QCOMPARE(bool(iface->state().focused), le->hasFocus());
QString secret(QLatin1String("secret"));
@ -3640,6 +3649,12 @@ void tst_QAccessibility::labelTest()
QVERIFY(acc_label);
QCOMPARE(acc_label->text(QAccessible::Name), text);
QCOMPARE(acc_label->state().editable, false);
QCOMPARE(acc_label->state().passwordEdit, false);
QCOMPARE(acc_label->state().disabled, false);
QCOMPARE(acc_label->state().focused, false);
QCOMPARE(acc_label->state().focusable, false);
QCOMPARE(acc_label->state().readOnly, true);
QVector<QPair<QAccessibleInterface *, QAccessible::Relation> > rels = acc_label->relations();
QCOMPARE(rels.count(), 1);

View File

@ -251,6 +251,8 @@ void tst_QAccessibilityLinux::testLabel()
QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label"));
QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u);
QCOMPARE(getParent(labelInterface), mainWindow->path());
QVERIFY(!hasState(labelInterface, ATSPI_STATE_EDITABLE));
QVERIFY(hasState(labelInterface, ATSPI_STATE_READ_ONLY));
l->setText("New text");
QCOMPARE(labelInterface->property("Name").toString(), l->text());
@ -303,6 +305,12 @@ void tst_QAccessibilityLinux::testLineEdit()
QCOMPARE(lineEdit->selectionStart(), -1);
QCOMPARE(textInterface->call(QDBus::Block, "GetNSelections").arguments().first().toInt(), 0);
QVERIFY(hasState(accessibleInterface, ATSPI_STATE_EDITABLE));
QVERIFY(!hasState(accessibleInterface, ATSPI_STATE_READ_ONLY));
lineEdit->setReadOnly(true);
QVERIFY(hasState(accessibleInterface, ATSPI_STATE_EDITABLE));
QVERIFY(hasState(accessibleInterface, ATSPI_STATE_READ_ONLY));
m_window->clearChildren();
delete accessibleInterface;
delete textInterface;