1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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"
49 QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
50 : QQmlAccessible(item)
54 int QAccessibleQuickItem::childCount() const
56 return childItems().count();
59 QRect QAccessibleQuickItem::rect() const
61 const QRect r = itemScreenRect(item());
64 qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r;
69 QRect QAccessibleQuickItem::viewRect() const
71 // ### no canvas in some cases.
72 if (!item()->canvas()) {
76 QQuickCanvas *canvas = item()->canvas();
77 QPoint screenPos = canvas->mapToGlobal(QPoint(0,0));
78 return QRect(screenPos, canvas->size());
82 bool QAccessibleQuickItem::clipsChildren() const
84 return static_cast<QQuickItem *>(item())->clip();
88 QAccessibleInterface *QAccessibleQuickItem::parent() const
90 QQuickItem *parent = item()->parentItem();
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);
101 return QAccessible::queryAccessibleInterface(parent);
107 QAccessibleInterface *QAccessibleQuickItem::child(int index) const
109 QList<QQuickItem *> children = childItems();
111 if (index < 0 || index >= children.count())
114 QQuickItem *child = children.at(index);
115 if (!child) // FIXME can this happen?
118 return QAccessible::queryAccessibleInterface(child);
121 int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
123 QList<QQuickItem*> kids = childItems();
124 return kids.indexOf(static_cast<QQuickItem*>(iface->object()));
127 QList<QQuickItem *> QAccessibleQuickItem::childItems() const
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();
141 QAccessible::State QAccessibleQuickItem::state() const
143 QAccessible::State state;
145 if (item()->hasActiveFocus())
146 state.focused = true;
148 QAccessible::Role r = role();
150 case QAccessible::Button: {
151 QVariant checkable = item()->property("checkable");
152 if (!checkable.toBool())
156 case QAccessible::CheckBox:
157 case QAccessible::RadioButton: {
158 // FIXME when states are extended: state.checkable = true;
159 state.checked = item()->property("checked").toBool();
169 QAccessible::Role QAccessibleQuickItem::role() const
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;
177 QVariant v = QQuickAccessibleAttached::property(item(), "role");
179 QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
180 if (!ok) // Not sure if this check is needed.
181 role = QAccessible::Pane;
185 bool QAccessibleQuickItem::isAccessible() const
187 return item()->d_func()->isAccessible;
190 QString QAccessibleQuickItem::text(QAccessible::Text textType) const
192 // handles generic behavior not specific to an item
194 case QAccessible::Name: {
195 QVariant accessibleName = QQuickAccessibleAttached::property(object(), "name");
196 if (!accessibleName.isNull())
197 return accessibleName.toString();
199 case QAccessible::Description: {
200 QVariant accessibleDecription = QQuickAccessibleAttached::property(object(), "description");
201 if (!accessibleDecription.isNull())
202 return accessibleDecription.toString();
204 #ifdef Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
205 case QAccessible::DebugDescription: {
207 debugString = QString::fromAscii(object()->metaObject()->className()) + QLatin1Char(' ');
208 debugString += isAccessible() ? QLatin1String("enabled") : QLatin1String("disabled");
212 case QAccessible::Value:
213 case QAccessible::Help:
214 case QAccessible::Accelerator:
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();
228 if (textType == QAccessible::Name) {
229 QVariant text = object()->property("text");
230 return text.toString();
237 void *QAccessibleQuickItemValueInterface::interface_cast(QAccessible::InterfaceType t)
239 if (t == QAccessible::ValueInterface)
240 return static_cast<QAccessibleValueInterface*>(this);
241 return QAccessibleQuickItem::interface_cast(t);
244 QVariant QAccessibleQuickItemValueInterface::currentValue() const
246 return item()->property("value");
249 void QAccessibleQuickItemValueInterface::setCurrentValue(const QVariant &value)
251 item()->setProperty("value", value);
254 QVariant QAccessibleQuickItemValueInterface::maximumValue() const
256 return item()->property("maximumValue");
259 QVariant QAccessibleQuickItemValueInterface::minimumValue() const
261 return item()->property("minimumValue");
266 Shared between QAccessibleQuickItem and QAccessibleQuickView
268 QRect itemScreenRect(QQuickItem *item)
270 // ### no canvas in some cases.
271 // ### Should we really check for 0 opacity?
272 if (!item->canvas() ||!item->isVisible() || qFuzzyIsNull(item->opacity())) {
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());
286 QPointF scenePoint = item->mapToScene(QPointF(0, 0));
287 QPoint screenPos = item->canvas()->mapToGlobal(scenePoint.toPoint());
288 return QRect(screenPos, itemSize);