Accessibility: Checked state for check boxes and radio buttons.
[profile/ivi/qtdeclarative.git] / src / plugins / accessible / quick / qaccessiblequickitem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qaccessiblequickitem.h"
43 #include "QtQuick/private/qquickitem_p.h"
44 #include "QtQuick/private/qquicktext_p.h"
45 #include "QtQuick/private/qquickaccessibleattached_p.h"
46
47 QT_BEGIN_NAMESPACE
48
49 QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
50     : QDeclarativeAccessible(item)
51 {
52 }
53
54 int QAccessibleQuickItem::childCount() const
55 {
56     return childItems().count();
57 }
58
59 QRect QAccessibleQuickItem::rect() const
60 {
61     // ### no canvas in some cases.
62     // ### Should we really check for 0 opacity?
63     if (!item()->canvas() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) {
64         return QRect();
65     }
66
67     QSizeF size = QSizeF(item()->width(), item()->height());
68     // ### If the bounding rect fails, we first try the implicit size, then we go for the
69     // parent size. WE MIGHT HAVE TO REVISIT THESE FALLBACKS.
70     if (size.isEmpty()) {
71         size = QSizeF(item()->implicitWidth(), item()->implicitHeight());
72         if (size.isEmpty())
73             // ### Seems that the above fallback is not enough, fallback to use the parent size...
74             size = QSizeF(item()->parentItem()->width(), item()->parentItem()->height());
75     }
76
77     QRectF sceneRect = item()->mapRectToScene(QRectF(QPointF(0, 0), size));
78     QPoint screenPos = item()->canvas()->mapToGlobal(sceneRect.topLeft().toPoint());
79
80     QRect r = QRect(screenPos, sceneRect.size().toSize());
81
82     if (!r.isValid()) {
83         qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r;
84     }
85     return r;
86 }
87
88 QRect QAccessibleQuickItem::viewRect() const
89 {
90     // ### no canvas in some cases.
91     if (!item()->canvas()) {
92         return QRect();
93     }
94
95     QQuickCanvas *canvas = item()->canvas();
96     QPoint screenPos = canvas->mapToGlobal(QPoint(0,0));
97     return QRect(screenPos, canvas->size());
98 }
99
100
101 bool QAccessibleQuickItem::clipsChildren() const
102 {
103     return static_cast<QQuickItem *>(item())->clip();
104 }
105
106
107 QAccessibleInterface *QAccessibleQuickItem::parent() const
108 {
109     QQuickItem *parent = item()->parentItem();
110     if (parent) {
111         QQuickCanvas *canvas = item()->canvas();
112         // Jump out to the scene widget if the parent is the root item.
113         // There are two root items, QQuickCanvas::rootItem and
114         // QQuickView::declarativeRoot. The former is the true root item,
115         // but is not a part of the accessibility tree. Check if we hit
116         // it here and return an interface for the scene instead.
117         if (parent == canvas->rootItem()) {
118             return QAccessible::queryAccessibleInterface(canvas);
119         } else {
120             QDeclarativeAccessible *ancestor = new QAccessibleQuickItem(parent);
121             return ancestor;
122         }
123     }
124     return 0;
125 }
126
127 QAccessibleInterface *QAccessibleQuickItem::child(int index) const
128 {
129     QList<QQuickItem *> children = childItems();
130
131     if (index < 0 || index >= children.count())
132         return 0;
133
134     QQuickItem *child = children.at(index);
135     if (!child) // FIXME can this happen?
136         return 0;
137
138     return new QAccessibleQuickItem(child);
139 }
140
141 int QAccessibleQuickItem::navigate(QAccessible::RelationFlag rel, int entry, QAccessibleInterface **target) const
142 {
143     Q_UNUSED(rel);
144     Q_UNUSED(entry);
145     Q_UNUSED(target);
146     *target = 0;
147     if (entry == 0) {
148         *target = new QAccessibleQuickItem(item());
149         return 0;
150     }
151     return -1;
152 }
153
154 int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
155 {
156     QList<QQuickItem*> kids = childItems();
157     int idx = kids.indexOf(static_cast<QQuickItem*>(iface->object()));
158     if (idx != -1)
159         ++idx;
160     return idx;
161 }
162
163 QList<QQuickItem *> QAccessibleQuickItem::childItems() const
164 {
165     if (    role() == QAccessible::Button ||
166             role() == QAccessible::CheckBox ||
167             role() == QAccessible::RadioButton ||
168             role() == QAccessible::SpinBox ||
169             role() == QAccessible::EditableText ||
170             role() == QAccessible::Slider ||
171             role() == QAccessible::PageTab ||
172             role() == QAccessible::ProgressBar)
173         return QList<QQuickItem *>();
174     return item()->childItems();
175 }
176
177 QAccessible::State QAccessibleQuickItem::state() const
178 {
179     QAccessible::State state;
180
181     if (item()->hasActiveFocus())
182         state.focused = true;
183
184     QAccessible::Role r = role();
185     switch (r) {
186     case QAccessible::Button: {
187         QVariant checkable = item()->property("checkable");
188         if (!checkable.toBool())
189             break;
190         // fall through
191     }
192     case QAccessible::CheckBox:
193     case QAccessible::RadioButton: {
194         // FIXME when states are extended: state.checkable = true;
195         state.checked = item()->property("checked").toBool();
196         break;
197     }
198     default:
199         break;
200     }
201
202     return state;
203 }
204
205 QAccessible::Role QAccessibleQuickItem::role() const
206 {
207     // Workaround for setAccessibleRole() not working for
208     // Text items. Text items are special since they are defined
209     // entirely from C++ (setting the role from QML works.)
210     if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
211         return QAccessible::StaticText;
212
213     QVariant v = QQuickAccessibleAttached::property(item(), "role");
214     bool ok;
215     QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
216     if (!ok)    // Not sure if this check is needed.
217         role = QAccessible::Pane;
218     return role;
219 }
220
221 bool QAccessibleQuickItem::isAccessible() const
222 {
223     return item()->d_func()->isAccessible;
224 }
225
226 QString QAccessibleQuickItem::text(QAccessible::Text textType) const
227 {
228     // handles generic behavior not specific to an item
229     switch (textType) {
230     case QAccessible::Name: {
231         QVariant accessibleName = QQuickAccessibleAttached::property(object(), "name");
232         if (!accessibleName.isNull())
233             return accessibleName.toString();
234         break;}
235     case QAccessible::Description: {
236         QVariant accessibleDecription = QQuickAccessibleAttached::property(object(), "description");
237         if (!accessibleDecription.isNull())
238             return accessibleDecription.toString();
239         break;}
240 #ifdef Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
241     case QAccessible::DebugDescription: {
242         QString debugString;
243         debugString = QString::fromAscii(object()->metaObject()->className()) + QLatin1Char(' ');
244         debugString += isAccessible() ? QLatin1String("enabled") : QLatin1String("disabled");
245         return debugString;
246         break; }
247 #endif
248     case QAccessible::Value:
249     case QAccessible::Help:
250     case QAccessible::Accelerator:
251     default:
252         break;
253     }
254
255     // the following blocks handles item-specific behavior
256     if (role() == QAccessible::EditableText) {
257         if (textType == QAccessible::Value) {
258             QVariant text = object()->property("text");
259             return text.toString();
260         } else if (textType == QAccessible::Name) {
261             return object()->objectName();
262         }
263     } else {
264         if (textType == QAccessible::Name) {
265             QVariant text = object()->property("text");
266             return text.toString();
267         }
268     }
269
270     return QString();
271 }
272
273 void *QAccessibleQuickItemValueInterface::interface_cast(QAccessible::InterfaceType t)
274 {
275     if (t == QAccessible::ValueInterface)
276        return static_cast<QAccessibleValueInterface*>(this);
277     return QAccessibleQuickItem::interface_cast(t);
278 }
279
280 QVariant QAccessibleQuickItemValueInterface::currentValue() const
281 {
282     return item()->property("value");
283 }
284
285 void QAccessibleQuickItemValueInterface::setCurrentValue(const QVariant &value)
286 {
287     item()->setProperty("value", value);
288 }
289
290 QVariant QAccessibleQuickItemValueInterface::maximumValue() const
291 {
292     return item()->property("maximumValue");
293 }
294
295 QVariant QAccessibleQuickItemValueInterface::minimumValue() const
296 {
297     return item()->property("minimumValue");
298 }
299
300
301 QT_END_NAMESPACE