Accessibility: Checked state for check boxes and radio buttons.
authorFrederik Gladhorn <frederik.gladhorn@nokia.com>
Wed, 4 Jan 2012 13:37:27 +0000 (14:37 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 10 Jan 2012 12:47:53 +0000 (13:47 +0100)
Also adapt to new api in qtbase - state is now a bit field.

Change-Id: Ia4266f3d5094a6c32e0ace3499910b57c3e71c25
Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>
src/plugins/accessible/qtquick1/qaccessibledeclarativeitem.cpp
src/plugins/accessible/qtquick1/qaccessibledeclarativeitem.h
src/plugins/accessible/quick/qaccessiblequickitem.cpp
src/plugins/accessible/quick/qaccessiblequickitem.h
src/plugins/accessible/quick/qaccessiblequickview.cpp
src/plugins/accessible/shared/qdeclarativeaccessible.cpp
src/plugins/accessible/shared/qdeclarativeaccessible.h
src/quick/items/qquickaccessibleattached.cpp
tests/auto/declarative/qdeclarativeaccessibility/data/checkbuttons.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativeaccessibility/tst_qdeclarativeaccessibility.cpp

index 6e4f27a..8786949 100644 (file)
@@ -171,13 +171,10 @@ int QAccessibleDeclarativeItem::indexOfChild(const QAccessibleInterface *iface)
     return index;
 }
 
-QFlags<QAccessible::StateFlag> QAccessibleDeclarativeItem::state() const
+QAccessible::State QAccessibleDeclarativeItem::state() const
 {
-    QAccessible::State state = QAccessible::Normal;
-
-    if (m_item->hasFocus()) {
-        state |= QAccessible::Focused;
-    }
+    QAccessible::State state;
+    state.focused = m_item->hasFocus();
     return state;
 }
 
index 29ff3d2..6f841a7 100644 (file)
@@ -65,7 +65,7 @@ public:
     int navigate(QAccessible::RelationFlag rel, int entry, QAccessibleInterface **target) const;
     int indexOfChild(const QAccessibleInterface *iface) const;
 
-    QFlags<QAccessible::StateFlag> state() const;
+    QAccessible::State state() const;
     QAccessible::Role role() const;
     QString text(QAccessible::Text) const;
 
index 7523f80..5cedfe6 100644 (file)
@@ -174,17 +174,34 @@ QList<QQuickItem *> QAccessibleQuickItem::childItems() const
     return item()->childItems();
 }
 
-QFlags<QAccessible::StateFlag> QAccessibleQuickItem::state() const
+QAccessible::State QAccessibleQuickItem::state() const
 {
-    QAccessible::State state = QAccessible::Normal;
-
-    if (item()->hasActiveFocus()) {
-        state |= QAccessible::Focused;
+    QAccessible::State state;
+
+    if (item()->hasActiveFocus())
+        state.focused = true;
+
+    QAccessible::Role r = role();
+    switch (r) {
+    case QAccessible::Button: {
+        QVariant checkable = item()->property("checkable");
+        if (!checkable.toBool())
+            break;
+        // fall through
+    }
+    case QAccessible::CheckBox:
+    case QAccessible::RadioButton: {
+        // FIXME when states are extended: state.checkable = true;
+        state.checked = item()->property("checked").toBool();
+        break;
+    }
+    default:
+        break;
     }
+
     return state;
 }
 
-
 QAccessible::Role QAccessibleQuickItem::role() const
 {
     // Workaround for setAccessibleRole() not working for
index d412fcb..5ef3a19 100644 (file)
@@ -67,7 +67,7 @@ public:
     int indexOfChild(const QAccessibleInterface *iface) const;
     QList<QQuickItem *> childItems() const;
 
-    QFlags<QAccessible::StateFlag> state() const;
+    QAccessible::State state() const;
     QAccessible::Role role() const;
     QString text(QAccessible::Text) const;
 
index f4e8136..6a896ef 100644 (file)
@@ -82,7 +82,7 @@ QAccessible::Role QAccessibleQuickView::role() const
 
 QAccessible::State QAccessibleQuickView::state() const
 {
-    return QAccessible::Normal; // FIXME
+    return QAccessible::State(); // FIXME
 }
 
 QRect QAccessibleQuickView::rect() const
index e3e0560..7db5f07 100644 (file)
@@ -82,7 +82,7 @@ QAccessibleInterface *QDeclarativeAccessible::childAt(int x, int y) const
 
     for (int i = childCount() - 1; i >= 0; --i) {
         QAccessibleInterface *childIface = child(i);
-        if (childIface && !(childIface->state() & QAccessible::Invisible)) {
+        if (childIface && !childIface->state().invisible) {
             if (childIface->rect().contains(x, y))
                 return childIface;
         }
@@ -91,9 +91,9 @@ QAccessibleInterface *QDeclarativeAccessible::childAt(int x, int y) const
     return 0;
 }
 
-QFlags<QAccessible::StateFlag> QDeclarativeAccessible::state() const
+QAccessible::State QDeclarativeAccessible::state() const
 {
-    QAccessible::State state;// = state();
+    QAccessible::State state;
 
     //QRect viewRect(QPoint(0, 0), m_implementation->size());
     //QRect itemRect(m_item->scenePos().toPoint(), m_item->boundingRect().size().toSize());
@@ -104,24 +104,24 @@ QFlags<QAccessible::StateFlag> QDeclarativeAccessible::state() const
    // qDebug() << "viewRect" << viewRect << "itemRect" << itemRect;
     // error case:
     if (viewRect_.isNull() || itemRect.isNull()) {
-        state |= QAccessible::Invisible;
+        state.invisible = true;
     }
 
     if (!viewRect_.intersects(itemRect)) {
-        state |= QAccessible::Offscreen;
-        // state |= QAccessible::Invisible; // no set at this point to ease development
+        state.offscreen = true;
+        // state.invisible = true; // no set at this point to ease development
     }
 
     if (!object()->property("visible").toBool() || qFuzzyIsNull(object()->property("opacity").toDouble())) {
-        state |= QAccessible::Invisible;
+        state.invisible = true;
     }
 
     if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool()) {
-        state |= QAccessible::Checked;
+        state.checked = true;
     }
 
     if (role() == QAccessible::EditableText)
-        state |= QAccessible::Focusable;
+        state.focusable = true;
 
     //qDebug() << "state?" << m_item->property("state").toString() << m_item->property("status").toString() << m_item->property("visible").toString();
 
index 7908092..9193e1a 100644 (file)
@@ -78,7 +78,7 @@ public:
     virtual QRect viewRect() const = 0;
     QFlags<QAccessible::RelationFlag> relationTo(const QAccessibleInterface*) const;
     QAccessibleInterface *childAt(int, int) const;
-    QFlags<QAccessible::StateFlag> state() const;
+    QAccessible::State state() const;
     QVariant invokeMethod(QAccessible::Method, const QVariantList &);
 
     QStringList actionNames() const;
index f7faf8f..213920b 100644 (file)
@@ -102,6 +102,35 @@ QT_BEGIN_NAMESPACE
         Accessible.role: Accessible.Button
     }
     \endqml
+
+    Some roles have special semantics.
+    In order to implement check boxes for example a "checked" property is expected.
+
+    \table
+    \header
+        \o \bold {Role}
+        \o \bold {Expected property}
+        \o
+
+    \row
+       \o CheckBox
+       \o checked
+       \o The check state of the check box.
+    \row
+       \o RadioButton
+       \o checked
+       \o The selected state of the radio button.
+    \row
+       \o Button
+       \o checkable
+       \o Whether the button is checkable.
+    \row
+       \o Button
+       \o checked
+       \o Whether the button is checked (only if checkable is true).
+
+    \endtable
+
 */
 
 QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
diff --git a/tests/auto/declarative/qdeclarativeaccessibility/data/checkbuttons.qml b/tests/auto/declarative/qdeclarativeaccessibility/data/checkbuttons.qml
new file mode 100644 (file)
index 0000000..22cdad1
--- /dev/null
@@ -0,0 +1,47 @@
+import QtQuick 2.0
+
+Item {
+    width: 400
+    height: 400
+
+    // button, not checkable
+    Rectangle {
+        y: 20
+        width: 100; height: 20
+        Accessible.role : Accessible.Button
+    }
+
+    // button, checkable, not checked
+    Rectangle {
+        y: 40
+        width: 100; height: 20
+        Accessible.role : Accessible.Button
+        property bool checkable: true
+        property bool checked: false
+    }
+
+    // button, checkable, checked
+    Rectangle {
+        y: 60
+        width: 100; height: 20
+        Accessible.role : Accessible.Button
+        property bool checkable: true
+        property bool checked: true
+    }
+
+    // check box, checked
+    Rectangle {
+        y: 80
+        width: 100; height: 20
+        Accessible.role : Accessible.CheckBox
+        property bool checked: true
+    }
+    // check box, not checked
+    Rectangle {
+        y: 100
+        width: 100; height: 20
+        Accessible.role : Accessible.CheckBox
+        property bool checked: false
+    }
+}
+
index 9064d24..725d282 100644 (file)
@@ -203,6 +203,7 @@ private slots:
     void declarativeAttachedProperties();
     void basicPropertiesTest();
     void hitTest();
+    void checkableTest();
 };
 
 tst_QDeclarativeAccessibility::tst_QDeclarativeAccessibility()
@@ -287,48 +288,6 @@ QString eventName(const int ev)
     }
 }
 
-static QString stateNames(int state)
-{
-    QString stateString;
-    if (state == 0x00000000) stateString += " Normal";
-    if (state & 0x00000001) stateString += " Unavailable";
-    if (state & 0x00000002) stateString += " Selected";
-    if (state & 0x00000004) stateString += " Focused";
-    if (state & 0x00000008) stateString += " Pressed";
-    if (state & 0x00000010) stateString += " Checked";
-    if (state & 0x00000020) stateString += " Mixed";
-    if (state & 0x00000040) stateString += " ReadOnly";
-    if (state & 0x00000080) stateString += " HotTracked";
-    if (state & 0x00000100) stateString += " DefaultButton";
-    if (state & 0x00000200) stateString += " Expanded";
-    if (state & 0x00000400) stateString += " Collapsed";
-    if (state & 0x00000800) stateString += " Busy";
-    if (state & 0x00001000) stateString += " Floating";
-    if (state & 0x00002000) stateString += " Marqueed";
-    if (state & 0x00004000) stateString += " Animated";
-    if (state & 0x00008000) stateString += " Invisible";
-    if (state & 0x00010000) stateString += " Offscreen";
-    if (state & 0x00020000) stateString += " Sizeable";
-    if (state & 0x00040000) stateString += " Moveable";
-    if (state & 0x00080000) stateString += " SelfVoicing";
-    if (state & 0x00100000) stateString += " Focusable";
-    if (state & 0x00200000) stateString += " Selectable";
-    if (state & 0x00400000) stateString += " Linked";
-    if (state & 0x00800000) stateString += " Traversed";
-    if (state & 0x01000000) stateString += " MultiSelectable";
-    if (state & 0x02000000) stateString += " ExtSelectable";
-    if (state & 0x04000000) stateString += " AlertLow";
-    if (state & 0x08000000) stateString += " AlertMedium";
-    if (state & 0x10000000) stateString += " AlertHigh";
-    if (state & 0x20000000) stateString += " Protected";
-    if (state & 0x3fffffff) stateString += " Valid";
-
-    if (stateString.isEmpty())
-        stateString = "Unknown state " + QString::number(state);
-
-    return stateString;
-}
-
 void tst_QDeclarativeAccessibility::declarativeAttachedProperties()
 {
     {
@@ -492,6 +451,32 @@ void tst_QDeclarativeAccessibility::hitTest()
 
     delete canvas;
 }
+
+void tst_QDeclarativeAccessibility::checkableTest()
+{
+    QQuickView *canvas = new QQuickView();
+    canvas->setSource(testFileUrl("checkbuttons.qml"));
+    canvas->show();
+
+    QAI iface = QAI(QAccessible::queryAccessibleInterface(canvas));
+    QVERIFY(iface.data());
+    QAI root = QAI(iface->child(0));
+
+    QAI button1 = QAI(root->child(0));
+    QCOMPARE(button1->role(), QAccessible::Button);
+    QVERIFY(!(button1->state().checked));
+    QAI button2 = QAI(root->child(1));
+    QVERIFY(!(button2->state().checked));
+    QAI button3 = QAI(root->child(2));
+    QVERIFY(button3->state().checked);
+
+    QAI checkBox1 = QAI(root->child(3));
+    QCOMPARE(checkBox1->role(), QAccessible::CheckBox);
+    QVERIFY((checkBox1->state().checked));
+    QAI checkBox2 = QAI(root->child(4));
+    QVERIFY(!(checkBox2->state().checked));
+}
+
 QTEST_MAIN(tst_QDeclarativeAccessibility)
 
 #include "tst_qdeclarativeaccessibility.moc"