e8083bdfe899be28918806eba83c0072ce1b28b2
[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: http://www.qt-project.org/
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     const QRect r = itemScreenRect(item());
62
63     if (!r.isValid()) {
64         qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r;
65     }
66     return r;
67 }
68
69 QRect QAccessibleQuickItem::viewRect() const
70 {
71     // ### no canvas in some cases.
72     if (!item()->canvas()) {
73         return QRect();
74     }
75
76     QQuickCanvas *canvas = item()->canvas();
77     QPoint screenPos = canvas->mapToGlobal(QPoint(0,0));
78     return QRect(screenPos, canvas->size());
79 }
80
81
82 bool QAccessibleQuickItem::clipsChildren() const
83 {
84     return static_cast<QQuickItem *>(item())->clip();
85 }
86
87
88 QAccessibleInterface *QAccessibleQuickItem::parent() const
89 {
90     QQuickItem *parent = item()->parentItem();
91     if (parent) {
92         QQuickCanvas *canvas = item()->canvas();
93         // Jump out to the scene widget if the parent is the root item.
94         // There are two root items, QQuickCanvas::rootItem and
95         // QQuickView::declarativeRoot. The former is the true root item,
96         // but is not a part of the accessibility tree. Check if we hit
97         // it here and return an interface for the scene instead.
98         if (parent == canvas->rootItem()) {
99             return QAccessible::queryAccessibleInterface(canvas);
100         } else {
101             return QAccessible::queryAccessibleInterface(parent);
102         }
103     }
104     return 0;
105 }
106
107 QAccessibleInterface *QAccessibleQuickItem::child(int index) const
108 {
109     QList<QQuickItem *> children = childItems();
110
111     if (index < 0 || index >= children.count())
112         return 0;
113
114     QQuickItem *child = children.at(index);
115     if (!child) // FIXME can this happen?
116         return 0;
117
118     return QAccessible::queryAccessibleInterface(child);
119 }
120
121 int QAccessibleQuickItem::navigate(QAccessible::RelationFlag rel, int entry, QAccessibleInterface **target) const
122 {
123     Q_UNUSED(rel);
124     Q_UNUSED(entry);
125     Q_UNUSED(target);
126     *target = 0;
127     return -1;
128 }
129
130 int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
131 {
132     QList<QQuickItem*> kids = childItems();
133     return kids.indexOf(static_cast<QQuickItem*>(iface->object()));
134 }
135
136 QList<QQuickItem *> QAccessibleQuickItem::childItems() const
137 {
138     if (    role() == QAccessible::Button ||
139             role() == QAccessible::CheckBox ||
140             role() == QAccessible::RadioButton ||
141             role() == QAccessible::SpinBox ||
142             role() == QAccessible::EditableText ||
143             role() == QAccessible::Slider ||
144             role() == QAccessible::PageTab ||
145             role() == QAccessible::ProgressBar)
146         return QList<QQuickItem *>();
147     return item()->childItems();
148 }
149
150 QAccessible::State QAccessibleQuickItem::state() const
151 {
152     QAccessible::State state;
153
154     if (item()->hasActiveFocus())
155         state.focused = true;
156
157     QAccessible::Role r = role();
158     switch (r) {
159     case QAccessible::Button: {
160         QVariant checkable = item()->property("checkable");
161         if (!checkable.toBool())
162             break;
163         // fall through
164     }
165     case QAccessible::CheckBox:
166     case QAccessible::RadioButton: {
167         // FIXME when states are extended: state.checkable = true;
168         state.checked = item()->property("checked").toBool();
169         break;
170     }
171     default:
172         break;
173     }
174
175     return state;
176 }
177
178 QAccessible::Role QAccessibleQuickItem::role() const
179 {
180     // Workaround for setAccessibleRole() not working for
181     // Text items. Text items are special since they are defined
182     // entirely from C++ (setting the role from QML works.)
183     if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
184         return QAccessible::StaticText;
185
186     QVariant v = QQuickAccessibleAttached::property(item(), "role");
187     bool ok;
188     QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
189     if (!ok)    // Not sure if this check is needed.
190         role = QAccessible::Pane;
191     return role;
192 }
193
194 bool QAccessibleQuickItem::isAccessible() const
195 {
196     return item()->d_func()->isAccessible;
197 }
198
199 QString QAccessibleQuickItem::text(QAccessible::Text textType) const
200 {
201     // handles generic behavior not specific to an item
202     switch (textType) {
203     case QAccessible::Name: {
204         QVariant accessibleName = QQuickAccessibleAttached::property(object(), "name");
205         if (!accessibleName.isNull())
206             return accessibleName.toString();
207         break;}
208     case QAccessible::Description: {
209         QVariant accessibleDecription = QQuickAccessibleAttached::property(object(), "description");
210         if (!accessibleDecription.isNull())
211             return accessibleDecription.toString();
212         break;}
213 #ifdef Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
214     case QAccessible::DebugDescription: {
215         QString debugString;
216         debugString = QString::fromAscii(object()->metaObject()->className()) + QLatin1Char(' ');
217         debugString += isAccessible() ? QLatin1String("enabled") : QLatin1String("disabled");
218         return debugString;
219         break; }
220 #endif
221     case QAccessible::Value:
222     case QAccessible::Help:
223     case QAccessible::Accelerator:
224     default:
225         break;
226     }
227
228     // the following blocks handles item-specific behavior
229     if (role() == QAccessible::EditableText) {
230         if (textType == QAccessible::Value) {
231             QVariant text = object()->property("text");
232             return text.toString();
233         } else if (textType == QAccessible::Name) {
234             return object()->objectName();
235         }
236     } else {
237         if (textType == QAccessible::Name) {
238             QVariant text = object()->property("text");
239             return text.toString();
240         }
241     }
242
243     return QString();
244 }
245
246 void *QAccessibleQuickItemValueInterface::interface_cast(QAccessible::InterfaceType t)
247 {
248     if (t == QAccessible::ValueInterface)
249        return static_cast<QAccessibleValueInterface*>(this);
250     return QAccessibleQuickItem::interface_cast(t);
251 }
252
253 QVariant QAccessibleQuickItemValueInterface::currentValue() const
254 {
255     return item()->property("value");
256 }
257
258 void QAccessibleQuickItemValueInterface::setCurrentValue(const QVariant &value)
259 {
260     item()->setProperty("value", value);
261 }
262
263 QVariant QAccessibleQuickItemValueInterface::maximumValue() const
264 {
265     return item()->property("maximumValue");
266 }
267
268 QVariant QAccessibleQuickItemValueInterface::minimumValue() const
269 {
270     return item()->property("minimumValue");
271 }
272
273 /*!
274   \internal
275   Shared between QAccessibleQuickItem and QAccessibleQuickView
276 */
277 QRect itemScreenRect(QQuickItem *item)
278 {
279     // ### no canvas in some cases.
280     // ### Should we really check for 0 opacity?
281     if (!item->canvas() ||!item->isVisible() || qFuzzyIsNull(item->opacity())) {
282         return QRect();
283     }
284
285     QSize itemSize((int)item->width(), (int)item->height());
286     // ### If the bounding rect fails, we first try the implicit size, then we go for the
287     // parent size. WE MIGHT HAVE TO REVISIT THESE FALLBACKS.
288     if (itemSize.isEmpty()) {
289         itemSize = QSize((int)item->implicitWidth(), (int)item->implicitHeight());
290         if (itemSize.isEmpty())
291             // ### Seems that the above fallback is not enough, fallback to use the parent size...
292             itemSize = QSize((int)item->parentItem()->width(), (int)item->parentItem()->height());
293     }
294
295     QPointF scenePoint = item->mapToScene(QPointF(0, 0));
296     QPoint screenPos = item->canvas()->mapToGlobal(scenePoint.toPoint());
297     return QRect(screenPos, itemSize);
298 }
299
300
301
302 QT_END_NAMESPACE