6c13377b3fe4020e42575d440e6415b18628439b
[profile/ivi/qtdeclarative.git] / src / plugins / accessible / quick / qaccessiblequickitem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
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     : QQmlAccessible(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::indexOfChild(const QAccessibleInterface *iface) const
122 {
123     QList<QQuickItem*> kids = childItems();
124     return kids.indexOf(static_cast<QQuickItem*>(iface->object()));
125 }
126
127 QList<QQuickItem *> QAccessibleQuickItem::childItems() const
128 {
129     if (    role() == QAccessible::Button ||
130             role() == QAccessible::CheckBox ||
131             role() == QAccessible::RadioButton ||
132             role() == QAccessible::SpinBox ||
133             role() == QAccessible::EditableText ||
134             role() == QAccessible::Slider ||
135             role() == QAccessible::PageTab ||
136             role() == QAccessible::ProgressBar)
137         return QList<QQuickItem *>();
138     return item()->childItems();
139 }
140
141 QAccessible::State QAccessibleQuickItem::state() const
142 {
143     QAccessible::State state;
144
145     if (item()->hasActiveFocus())
146         state.focused = true;
147
148     QAccessible::Role r = role();
149     switch (r) {
150     case QAccessible::Button: {
151         QVariant checkable = item()->property("checkable");
152         if (!checkable.toBool())
153             break;
154         // fall through
155     }
156     case QAccessible::CheckBox:
157     case QAccessible::RadioButton: {
158         // FIXME when states are extended: state.checkable = true;
159         state.checked = item()->property("checked").toBool();
160         break;
161     }
162     default:
163         break;
164     }
165
166     return state;
167 }
168
169 QAccessible::Role QAccessibleQuickItem::role() const
170 {
171     // Workaround for setAccessibleRole() not working for
172     // Text items. Text items are special since they are defined
173     // entirely from C++ (setting the role from QML works.)
174     if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
175         return QAccessible::StaticText;
176
177     QVariant v = QQuickAccessibleAttached::property(item(), "role");
178     bool ok;
179     QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
180     if (!ok)    // Not sure if this check is needed.
181         role = QAccessible::Pane;
182     return role;
183 }
184
185 bool QAccessibleQuickItem::isAccessible() const
186 {
187     return item()->d_func()->isAccessible;
188 }
189
190 QString QAccessibleQuickItem::text(QAccessible::Text textType) const
191 {
192     // handles generic behavior not specific to an item
193     switch (textType) {
194     case QAccessible::Name: {
195         QVariant accessibleName = QQuickAccessibleAttached::property(object(), "name");
196         if (!accessibleName.isNull())
197             return accessibleName.toString();
198         break;}
199     case QAccessible::Description: {
200         QVariant accessibleDecription = QQuickAccessibleAttached::property(object(), "description");
201         if (!accessibleDecription.isNull())
202             return accessibleDecription.toString();
203         break;}
204 #ifdef Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
205     case QAccessible::DebugDescription: {
206         QString debugString;
207         debugString = QString::fromAscii(object()->metaObject()->className()) + QLatin1Char(' ');
208         debugString += isAccessible() ? QLatin1String("enabled") : QLatin1String("disabled");
209         return debugString;
210         break; }
211 #endif
212     case QAccessible::Value:
213     case QAccessible::Help:
214     case QAccessible::Accelerator:
215     default:
216         break;
217     }
218
219     // the following blocks handles item-specific behavior
220     if (role() == QAccessible::EditableText) {
221         if (textType == QAccessible::Value) {
222             QVariant text = object()->property("text");
223             return text.toString();
224         } else if (textType == QAccessible::Name) {
225             return object()->objectName();
226         }
227     } else {
228         if (textType == QAccessible::Name) {
229             QVariant text = object()->property("text");
230             return text.toString();
231         }
232     }
233
234     return QString();
235 }
236
237 void *QAccessibleQuickItemValueInterface::interface_cast(QAccessible::InterfaceType t)
238 {
239     if (t == QAccessible::ValueInterface)
240        return static_cast<QAccessibleValueInterface*>(this);
241     return QAccessibleQuickItem::interface_cast(t);
242 }
243
244 QVariant QAccessibleQuickItemValueInterface::currentValue() const
245 {
246     return item()->property("value");
247 }
248
249 void QAccessibleQuickItemValueInterface::setCurrentValue(const QVariant &value)
250 {
251     item()->setProperty("value", value);
252 }
253
254 QVariant QAccessibleQuickItemValueInterface::maximumValue() const
255 {
256     return item()->property("maximumValue");
257 }
258
259 QVariant QAccessibleQuickItemValueInterface::minimumValue() const
260 {
261     return item()->property("minimumValue");
262 }
263
264 /*!
265   \internal
266   Shared between QAccessibleQuickItem and QAccessibleQuickView
267 */
268 QRect itemScreenRect(QQuickItem *item)
269 {
270     // ### no canvas in some cases.
271     // ### Should we really check for 0 opacity?
272     if (!item->canvas() ||!item->isVisible() || qFuzzyIsNull(item->opacity())) {
273         return QRect();
274     }
275
276     QSize itemSize((int)item->width(), (int)item->height());
277     // ### If the bounding rect fails, we first try the implicit size, then we go for the
278     // parent size. WE MIGHT HAVE TO REVISIT THESE FALLBACKS.
279     if (itemSize.isEmpty()) {
280         itemSize = QSize((int)item->implicitWidth(), (int)item->implicitHeight());
281         if (itemSize.isEmpty() && item->parentItem())
282             // ### Seems that the above fallback is not enough, fallback to use the parent size...
283             itemSize = QSize((int)item->parentItem()->width(), (int)item->parentItem()->height());
284     }
285
286     QPointF scenePoint = item->mapToScene(QPointF(0, 0));
287     QPoint screenPos = item->canvas()->mapToGlobal(scenePoint.toPoint());
288     return QRect(screenPos, itemSize);
289 }
290
291
292
293 QT_END_NAMESPACE