~loic.molinari/+junk/qtdeclarative-opensource-src-qtquickitem-theme-pointer

« back to all changes in this revision

Viewing changes to src/quick/accessible/qaccessiblequickitem.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2015-02-13 06:17:15 UTC
  • mfrom: (0.1.24 experimental)
  • Revision ID: package-import@ubuntu.com-20150213061715-rlmavkexpjqk7pqp
Tags: 5.4.0-4ubuntu1
* New upstream release.
* Switch to using xvfb-run for tests
* Bump dependencies
* Drop patches:
  - freebsd_registers.diff
  - Avoid-race-condition-in-QQmlEngine-on-shutdown.patch
  - Fix-crashes-when-calling-Array.sort-with-imperfect-s.patch
* Update symbols and mark private ones
* Sync with Debian 5.4.0-4
  - Keep gles packages support, transitional packages, tests enablement 
    and additional patches
* debian/patches/Fix-regression-where-QQuickScreenAttached-overwrites.patch:
  - Fix orientation not working (LP: #1418370)
* debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch:
  - Comment out, needs rebasing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtQuick module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL21$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia. For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing. For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 or version 3 as published by the Free
 
20
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
 
21
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
 
22
** following information to ensure the GNU Lesser General Public License
 
23
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 
24
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
25
**
 
26
** In addition, as a special exception, Digia gives you certain additional
 
27
** rights. These rights are described in the Digia Qt LGPL Exception
 
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
29
**
 
30
** $QT_END_LICENSE$
 
31
**
 
32
****************************************************************************/
 
33
 
 
34
#include "qaccessiblequickitem_p.h"
 
35
 
 
36
#include <QtGui/qtextdocument.h>
 
37
 
 
38
#include "QtQuick/private/qquickitem_p.h"
 
39
#include "QtQuick/private/qquicktext_p.h"
 
40
#include "QtQuick/private/qquickaccessibleattached_p.h"
 
41
#include "QtQuick/qquicktextdocument.h"
 
42
QT_BEGIN_NAMESPACE
 
43
 
 
44
#ifndef QT_NO_ACCESSIBILITY
 
45
 
 
46
QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
 
47
    : QQmlAccessible(item), m_doc(textDocument())
 
48
{
 
49
}
 
50
 
 
51
int QAccessibleQuickItem::childCount() const
 
52
{
 
53
    return childItems().count();
 
54
}
 
55
 
 
56
QRect QAccessibleQuickItem::rect() const
 
57
{
 
58
    const QRect r = itemScreenRect(item());
 
59
 
 
60
    if (!r.isValid()) {
 
61
        qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r;
 
62
    }
 
63
    return r;
 
64
}
 
65
 
 
66
QRect QAccessibleQuickItem::viewRect() const
 
67
{
 
68
    // ### no window in some cases.
 
69
    if (!item()->window()) {
 
70
        return QRect();
 
71
    }
 
72
 
 
73
    QQuickWindow *window = item()->window();
 
74
    QPoint screenPos = window->mapToGlobal(QPoint(0,0));
 
75
    return QRect(screenPos, window->size());
 
76
}
 
77
 
 
78
 
 
79
bool QAccessibleQuickItem::clipsChildren() const
 
80
{
 
81
    return static_cast<QQuickItem *>(item())->clip();
 
82
}
 
83
 
 
84
QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
 
85
{
 
86
    if (item()->clip()) {
 
87
        if (!rect().contains(x, y))
 
88
            return 0;
 
89
    }
 
90
 
 
91
    const QList<QQuickItem*> kids = accessibleUnignoredChildren(item(), true);
 
92
    for (int i = kids.count() - 1; i >= 0; --i) {
 
93
        QAccessibleInterface *childIface = QAccessible::queryAccessibleInterface(kids.at(i));
 
94
        if (QAccessibleInterface *childChild = childIface->childAt(x, y))
 
95
            return childChild;
 
96
        if (childIface && !childIface->state().invisible) {
 
97
            if (childIface->rect().contains(x, y))
 
98
                return childIface;
 
99
        }
 
100
    }
 
101
 
 
102
    return 0;
 
103
}
 
104
 
 
105
QAccessibleInterface *QAccessibleQuickItem::parent() const
 
106
{
 
107
    QQuickItem *parent = item()->parentItem();
 
108
    QQuickWindow *window = item()->window();
 
109
    QQuickItem *ci = window ? window->contentItem() : 0;
 
110
    while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci)
 
111
        parent = parent->parentItem();
 
112
 
 
113
    if (parent) {
 
114
        if (parent == ci) {
 
115
            // Jump out to the scene widget if the parent is the root item.
 
116
            // There are two root items, QQuickWindow::rootItem and
 
117
            // QQuickView::declarativeRoot. The former is the true root item,
 
118
            // but is not a part of the accessibility tree. Check if we hit
 
119
            // it here and return an interface for the scene instead.
 
120
            return QAccessible::queryAccessibleInterface(window);
 
121
        } else {
 
122
            while (parent && !parent->d_func()->isAccessible)
 
123
                parent = parent->parentItem();
 
124
            return QAccessible::queryAccessibleInterface(parent);
 
125
        }
 
126
    }
 
127
    return 0;
 
128
}
 
129
 
 
130
QAccessibleInterface *QAccessibleQuickItem::child(int index) const
 
131
{
 
132
    QList<QQuickItem *> children = childItems();
 
133
 
 
134
    if (index < 0 || index >= children.count())
 
135
        return 0;
 
136
 
 
137
    QQuickItem *child = children.at(index);
 
138
    if (!child) // FIXME can this happen?
 
139
        return 0;
 
140
 
 
141
    return QAccessible::queryAccessibleInterface(child);
 
142
}
 
143
 
 
144
int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
 
145
{
 
146
    QList<QQuickItem*> kids = childItems();
 
147
    return kids.indexOf(static_cast<QQuickItem*>(iface->object()));
 
148
}
 
149
 
 
150
static void unignoredChildren(QQuickItem *item, QList<QQuickItem *> *items, bool paintOrder)
 
151
{
 
152
    QList<QQuickItem*> childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems()
 
153
                                               : item->childItems();
 
154
    Q_FOREACH (QQuickItem *child, childItems) {
 
155
        if (QQuickItemPrivate::get(child)->isAccessible) {
 
156
            items->append(child);
 
157
        } else {
 
158
            unignoredChildren(child, items, paintOrder);
 
159
        }
 
160
    }
 
161
}
 
162
 
 
163
QList<QQuickItem *> accessibleUnignoredChildren(QQuickItem *item, bool paintOrder)
 
164
{
 
165
    QList<QQuickItem *> items;
 
166
    unignoredChildren(item, &items, paintOrder);
 
167
    return items;
 
168
}
 
169
 
 
170
QList<QQuickItem *> QAccessibleQuickItem::childItems() const
 
171
{
 
172
    return accessibleUnignoredChildren(item());
 
173
}
 
174
 
 
175
QAccessible::State QAccessibleQuickItem::state() const
 
176
{
 
177
    QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item());
 
178
    if (!attached)
 
179
        return QAccessible::State();
 
180
 
 
181
    QAccessible::State st = attached->state();
 
182
 
 
183
    if (!item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
 
184
        st.invisible = true;
 
185
 
 
186
    if (item()->activeFocusOnTab())
 
187
        st.focusable = true;
 
188
    if (item()->hasActiveFocus())
 
189
        st.focused = true;
 
190
    return st;
 
191
}
 
192
 
 
193
QAccessible::Role QAccessibleQuickItem::role() const
 
194
{
 
195
    // Workaround for setAccessibleRole() not working for
 
196
    // Text items. Text items are special since they are defined
 
197
    // entirely from C++ (setting the role from QML works.)
 
198
    if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
 
199
        return QAccessible::StaticText;
 
200
 
 
201
    QVariant v = QQuickAccessibleAttached::property(item(), "role");
 
202
    bool ok;
 
203
    QAccessible::Role role = (QAccessible::Role)v.toInt(&ok);
 
204
    if (!ok)    // Not sure if this check is needed.
 
205
        role = QAccessible::Client;
 
206
    return role;
 
207
}
 
208
 
 
209
bool QAccessibleQuickItem::isAccessible() const
 
210
{
 
211
    return item()->d_func()->isAccessible;
 
212
}
 
213
 
 
214
QStringList QAccessibleQuickItem::actionNames() const
 
215
{
 
216
    QStringList actions = QQmlAccessible::actionNames();
 
217
    if (state().focusable)
 
218
        actions.append(QAccessibleActionInterface::setFocusAction());
 
219
 
 
220
    // ### The following can lead to duplicate action names. We'll fix that when we kill QQmlAccessible
 
221
    if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
 
222
        attached->availableActions(&actions);
 
223
    return actions;
 
224
}
 
225
 
 
226
void QAccessibleQuickItem::doAction(const QString &actionName)
 
227
{
 
228
    bool accepted = false;
 
229
    if (actionName == QAccessibleActionInterface::setFocusAction()) {
 
230
        item()->forceActiveFocus();
 
231
        accepted = true;
 
232
    }
 
233
    if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
 
234
        accepted = attached->doAction(actionName);
 
235
    if (!accepted)
 
236
        QQmlAccessible::doAction(actionName);
 
237
}
 
238
 
 
239
QStringList QAccessibleQuickItem::keyBindingsForAction(const QString &actionName) const
 
240
{
 
241
    return QQmlAccessible::keyBindingsForAction(actionName);
 
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::fromLatin1(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 block handles item-specific behavior
 
274
    if (role() == QAccessible::EditableText) {
 
275
        if (textType == QAccessible::Value) {
 
276
            if (QTextDocument *doc = textDocument()) {
 
277
                return doc->toPlainText();
 
278
            }
 
279
            QVariant text = object()->property("text");
 
280
            return text.toString();
 
281
        }
 
282
    }
 
283
 
 
284
    return QString();
 
285
}
 
286
 
 
287
void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t)
 
288
{
 
289
    QAccessible::Role r = role();
 
290
    if (t == QAccessible::ValueInterface &&
 
291
           (r == QAccessible::Slider ||
 
292
            r == QAccessible::SpinBox ||
 
293
            r == QAccessible::Dial ||
 
294
            r == QAccessible::ScrollBar))
 
295
       return static_cast<QAccessibleValueInterface*>(this);
 
296
 
 
297
    if (t == QAccessible::TextInterface &&
 
298
            (r == QAccessible::EditableText))
 
299
        return static_cast<QAccessibleTextInterface*>(this);
 
300
 
 
301
    return QQmlAccessible::interface_cast(t);
 
302
}
 
303
 
 
304
QVariant QAccessibleQuickItem::currentValue() const
 
305
{
 
306
    return item()->property("value");
 
307
}
 
308
 
 
309
void QAccessibleQuickItem::setCurrentValue(const QVariant &value)
 
310
{
 
311
    item()->setProperty("value", value);
 
312
}
 
313
 
 
314
QVariant QAccessibleQuickItem::maximumValue() const
 
315
{
 
316
    return item()->property("maximumValue");
 
317
}
 
318
 
 
319
QVariant QAccessibleQuickItem::minimumValue() const
 
320
{
 
321
    return item()->property("minimumValue");
 
322
}
 
323
 
 
324
QVariant QAccessibleQuickItem::minimumStepSize() const
 
325
{
 
326
    return item()->property("stepSize");
 
327
}
 
328
 
 
329
/*!
 
330
  \internal
 
331
  Shared between QAccessibleQuickItem and QAccessibleQuickView
 
332
*/
 
333
QRect itemScreenRect(QQuickItem *item)
 
334
{
 
335
    // ### no window in some cases.
 
336
    // ### Should we really check for 0 opacity?
 
337
    if (!item->window() ||!item->isVisible() || qFuzzyIsNull(item->opacity())) {
 
338
        return QRect();
 
339
    }
 
340
 
 
341
    QSize itemSize((int)item->width(), (int)item->height());
 
342
    // ### If the bounding rect fails, we first try the implicit size, then we go for the
 
343
    // parent size. WE MIGHT HAVE TO REVISIT THESE FALLBACKS.
 
344
    if (itemSize.isEmpty()) {
 
345
        itemSize = QSize((int)item->implicitWidth(), (int)item->implicitHeight());
 
346
        if (itemSize.isEmpty() && item->parentItem())
 
347
            // ### Seems that the above fallback is not enough, fallback to use the parent size...
 
348
            itemSize = QSize((int)item->parentItem()->width(), (int)item->parentItem()->height());
 
349
    }
 
350
 
 
351
    QPointF scenePoint = item->mapToScene(QPointF(0, 0));
 
352
    QPoint screenPos = item->window()->mapToGlobal(scenePoint.toPoint());
 
353
    return QRect(screenPos, itemSize);
 
354
}
 
355
 
 
356
QTextDocument *QAccessibleQuickItem::textDocument() const
 
357
{
 
358
    QVariant docVariant = item()->property("textDocument");
 
359
    if (docVariant.canConvert<QQuickTextDocument*>()) {
 
360
        QQuickTextDocument *qqdoc = docVariant.value<QQuickTextDocument*>();
 
361
        return qqdoc->textDocument();
 
362
    }
 
363
    return 0;
 
364
}
 
365
 
 
366
int QAccessibleQuickItem::characterCount() const
 
367
{
 
368
    if (m_doc) {
 
369
        QTextCursor cursor = QTextCursor(m_doc);
 
370
        cursor.movePosition(QTextCursor::End);
 
371
        return cursor.position();
 
372
    }
 
373
    return text(QAccessible::Value).size();
 
374
}
 
375
 
 
376
int QAccessibleQuickItem::cursorPosition() const
 
377
{
 
378
    QVariant pos = item()->property("cursorPosition");
 
379
    return pos.toInt();
 
380
}
 
381
 
 
382
void QAccessibleQuickItem::setCursorPosition(int position)
 
383
{
 
384
    item()->setProperty("cursorPosition", position);
 
385
}
 
386
 
 
387
QString QAccessibleQuickItem::text(int startOffset, int endOffset) const
 
388
{
 
389
    if (m_doc) {
 
390
        QTextCursor cursor = QTextCursor(m_doc);
 
391
        cursor.setPosition(startOffset);
 
392
        cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
 
393
        return cursor.selectedText();
 
394
    }
 
395
    return text(QAccessible::Value).mid(startOffset, endOffset - startOffset);
 
396
}
 
397
 
 
398
QString QAccessibleQuickItem::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
 
399
                                 int *startOffset, int *endOffset) const
 
400
{
 
401
    Q_ASSERT(startOffset);
 
402
    Q_ASSERT(endOffset);
 
403
 
 
404
    if (m_doc) {
 
405
        QTextCursor cursor = QTextCursor(m_doc);
 
406
        cursor.setPosition(offset);
 
407
        QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
 
408
        cursor.setPosition(boundaries.first - 1);
 
409
        boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
 
410
 
 
411
        *startOffset = boundaries.first;
 
412
        *endOffset = boundaries.second;
 
413
 
 
414
        return text(boundaries.first, boundaries.second);
 
415
    } else {
 
416
        return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
 
417
    }
 
418
}
 
419
 
 
420
QString QAccessibleQuickItem::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
 
421
                                int *startOffset, int *endOffset) const
 
422
{
 
423
    Q_ASSERT(startOffset);
 
424
    Q_ASSERT(endOffset);
 
425
 
 
426
    if (m_doc) {
 
427
        QTextCursor cursor = QTextCursor(m_doc);
 
428
        cursor.setPosition(offset);
 
429
        QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
 
430
        cursor.setPosition(boundaries.second);
 
431
        boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
 
432
 
 
433
        *startOffset = boundaries.first;
 
434
        *endOffset = boundaries.second;
 
435
 
 
436
        return text(boundaries.first, boundaries.second);
 
437
    } else {
 
438
        return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
 
439
    }
 
440
}
 
441
 
 
442
QString QAccessibleQuickItem::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
 
443
                             int *startOffset, int *endOffset) const
 
444
{
 
445
    Q_ASSERT(startOffset);
 
446
    Q_ASSERT(endOffset);
 
447
 
 
448
    if (m_doc) {
 
449
        QTextCursor cursor = QTextCursor(m_doc);
 
450
        cursor.setPosition(offset);
 
451
        QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
 
452
 
 
453
        *startOffset = boundaries.first;
 
454
        *endOffset = boundaries.second;
 
455
        return text(boundaries.first, boundaries.second);
 
456
    } else {
 
457
        return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
 
458
    }
 
459
}
 
460
 
 
461
void QAccessibleQuickItem::selection(int selectionIndex, int *startOffset, int *endOffset) const
 
462
{
 
463
    if (selectionIndex == 0) {
 
464
        *startOffset = item()->property("selectionStart").toInt();
 
465
        *endOffset = item()->property("selectionEnd").toInt();
 
466
    } else {
 
467
        *startOffset = 0;
 
468
        *endOffset = 0;
 
469
    }
 
470
}
 
471
 
 
472
int QAccessibleQuickItem::selectionCount() const
 
473
{
 
474
    if (item()->property("selectionStart").toInt() != item()->property("selectionEnd").toInt())
 
475
        return 1;
 
476
    return 0;
 
477
}
 
478
 
 
479
void QAccessibleQuickItem::addSelection(int /* startOffset */, int /* endOffset */)
 
480
{
 
481
 
 
482
}
 
483
void QAccessibleQuickItem::removeSelection(int /* selectionIndex */)
 
484
{
 
485
 
 
486
}
 
487
void QAccessibleQuickItem::setSelection(int /* selectionIndex */, int /* startOffset */, int /* endOffset */)
 
488
{
 
489
 
 
490
}
 
491
 
 
492
 
 
493
#endif // QT_NO_ACCESSIBILITY
 
494
 
 
495
QT_END_NAMESPACE