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