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