~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/accessible/qaccessiblewidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the accessibility module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qaccessiblewidget.h"
 
30
 
 
31
#ifndef QT_NO_ACCESSIBILITY
 
32
 
 
33
#include "qapplication.h"
 
34
#include "qgroupbox.h"
 
35
#include "qlabel.h"
 
36
#include "qtooltip.h"
 
37
#include "qwhatsthis.h"
 
38
#include "qwidget.h"
 
39
 
 
40
#include <math.h>
 
41
 
 
42
static QWidgetList childWidgets(const QWidget *widget)
 
43
{
 
44
    QObjectList list = widget->children();
 
45
    QWidgetList widgets;
 
46
    for (int i = 0; i < list.size(); ++i) {
 
47
        QWidget *w = qobject_cast<QWidget *>(list.at(i));
 
48
        if (w)
 
49
            widgets.append(w);
 
50
    }
 
51
    return widgets;
 
52
}
 
53
 
 
54
static QString buddyString(const QWidget *widget)
 
55
{
 
56
    if (!widget)
 
57
        return QString();
 
58
    QWidget *parent = widget->parentWidget();
 
59
    if (!parent)
 
60
        return QString();
 
61
    QObjectList ol = parent->children();
 
62
    for (int i = 0; i < ol.size(); ++i) {
 
63
        QLabel *label = qobject_cast<QLabel*>(ol.at(i));
 
64
        if (label && label->buddy() == widget)
 
65
            return label->text();
 
66
    }
 
67
 
 
68
    QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent);
 
69
    if (groupbox)
 
70
        return groupbox->title();
 
71
 
 
72
    return QString();
 
73
}
 
74
 
 
75
QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
 
76
{
 
77
    if (text.isEmpty())
 
78
        return text;
 
79
 
 
80
    const QChar *ch = text.unicode();
 
81
    int length = text.length();
 
82
    QString str;
 
83
    while (length > 0) {
 
84
        if (*ch == '&') {
 
85
            ++ch;
 
86
            --length;
 
87
            if (!ch)
 
88
                --ch;
 
89
        }
 
90
        str += *ch;
 
91
        ++ch;
 
92
        --length;
 
93
    }
 
94
    return str;
 
95
}
 
96
 
 
97
QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
 
98
{
 
99
    if (text.isEmpty())
 
100
        return text;
 
101
 
 
102
    int fa = 0;
 
103
    QChar ac;
 
104
    while ((fa = text.indexOf('&', fa)) != -1) {
 
105
        if (fa == text.length() - 1 || text.at(fa+1) != '&') {
 
106
            ac = text.at(fa+1);
 
107
            break;
 
108
        }
 
109
    }
 
110
    if (ac.isNull())
 
111
        return QString();
 
112
    return (QString)QKeySequence(Qt::ALT) + ac.toUpper();
 
113
}
 
114
 
 
115
class QAccessibleWidgetPrivate : public QAccessible
 
116
{
 
117
public:
 
118
    QAccessibleWidgetPrivate()
 
119
        :role(Client)
 
120
    {}
 
121
 
 
122
    Role role;
 
123
    QString name;
 
124
    QString description;
 
125
    QString value;
 
126
    QString help;
 
127
    QString accelerator;
 
128
    QStringList primarySignals;
 
129
    const QAccessibleInterface *asking;
 
130
};
 
131
 
 
132
/*!
 
133
    \class QAccessibleWidget
 
134
    \brief The QAccessibleWidget class implements the QAccessibleInterface for QWidgets.
 
135
 
 
136
    \ingroup accessibility
 
137
 
 
138
    This class is convenient to use as a base class for custom
 
139
    implementations of QAccessibleInterfaces that provide information
 
140
    about widget objects.
 
141
 
 
142
    The class provides functions to retrieve the parentObject() (the
 
143
    widget's parent widget), and the associated widget(). Controlling
 
144
    signals can be added with addControllingSignal(), and setters are
 
145
    provided for various aspects of the interface implementation, for
 
146
    example setValue(), setDescription(), setAccelerator(), and
 
147
    setHelp().
 
148
 
 
149
    \sa QAccessible, QAccessibleObject
 
150
*/
 
151
 
 
152
/*!
 
153
    Creates a QAccessibleWidget object for widget \a w.
 
154
    \a role and \a name are optional parameters that set the object's
 
155
    role and name properties.
 
156
*/
 
157
QAccessibleWidget::QAccessibleWidget(QWidget *w, Role role, const QString &name)
 
158
: QAccessibleObject(w)
 
159
{
 
160
    Q_ASSERT(widget());
 
161
    d = new QAccessibleWidgetPrivate();
 
162
    d->role = role;
 
163
    d->name = name;
 
164
    d->asking = 0;
 
165
}
 
166
 
 
167
/*!
 
168
    Destroys this object.
 
169
*/
 
170
QAccessibleWidget::~QAccessibleWidget()
 
171
{
 
172
    delete d;
 
173
}
 
174
 
 
175
/*!
 
176
    Returns the associated widget.
 
177
*/
 
178
QWidget *QAccessibleWidget::widget() const
 
179
{
 
180
    return qobject_cast<QWidget*>(object());
 
181
}
 
182
 
 
183
/*!
 
184
    Returns the associated widget's parent object, which is either the
 
185
    parent widget, or qApp for top-level widgets.
 
186
*/
 
187
QObject *QAccessibleWidget::parentObject() const
 
188
{
 
189
    QObject *parent = object()->parent();
 
190
    if (!parent)
 
191
        parent = qApp;
 
192
    return parent;
 
193
}
 
194
 
 
195
/*! \reimp */
 
196
int QAccessibleWidget::childAt(int x, int y) const
 
197
{
 
198
    QWidget *w = widget();
 
199
    QPoint gp = w->mapToGlobal(QPoint(0, 0));
 
200
    if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
 
201
        return -1;
 
202
 
 
203
    QWidgetList list = childWidgets(w);
 
204
    int ccount = childCount();
 
205
 
 
206
    // a complex child
 
207
    if (list.size() < ccount) {
 
208
        for (int i = 1; i <= ccount; ++i) {
 
209
            if (rect(i).contains(x, y))
 
210
                return i;
 
211
        }
 
212
        return 0;
 
213
    }
 
214
 
 
215
    QPoint rp = w->mapFromGlobal(QPoint(x, y));
 
216
    for (int i = 0; i<list.size(); ++i) {
 
217
        QWidget *child = list.at(i);
 
218
        if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
 
219
            return i + 1;
 
220
        }
 
221
    }
 
222
    return -1;
 
223
}
 
224
 
 
225
/*! \reimp */
 
226
QRect QAccessibleWidget::rect(int child) const
 
227
{
 
228
    if (child)
 
229
        qWarning("QAccessibleWidget::rect: This implementation does not support subelements! (ID %d unknown for %s)", child, widget()->metaObject()->className());
 
230
 
 
231
    QWidget *w = widget();
 
232
    QPoint wpos = w->mapToGlobal(QPoint(0, 0));
 
233
 
 
234
    return QRect(wpos.x(), wpos.y(), w->width(), w->height());
 
235
}
 
236
 
 
237
#include <private/qobject_p.h>
 
238
 
 
239
class ConnectionObject : public QObject
 
240
{
 
241
    Q_DECLARE_PRIVATE(QObject)
 
242
public:
 
243
    inline bool isSender(const QObject *receiver, const char *signal) const
 
244
    { return d_func()->isSender(receiver, signal); }
 
245
    inline QObjectList receiverList(const char *signal) const
 
246
    { return d_func()->receiverList(signal); }
 
247
    inline QObjectList senderList() const
 
248
    { return d_func()->senderList(); }
 
249
};
 
250
 
 
251
/*!
 
252
    Registers \a signal as a controlling signal.
 
253
 
 
254
    An object is a Controller to any other object connected to a
 
255
    controlling signal.
 
256
*/
 
257
void QAccessibleWidget::addControllingSignal(const QString &signal)
 
258
{
 
259
    QByteArray s = QMetaObject::normalizedSignature(signal.toAscii());
 
260
    if (object()->metaObject()->indexOfSignal(s) < 0)
 
261
        qWarning("Signal %s unknown in %s", (const char*)s, object()->metaObject()->className());
 
262
    d->primarySignals << s;
 
263
}
 
264
 
 
265
/*!
 
266
    Sets the value of this interface implementation to \a value.
 
267
 
 
268
    The default implementation of text() returns the set value for
 
269
    the Value text.
 
270
 
 
271
    Note that the object wrapped by this interface is not modified.
 
272
*/
 
273
void QAccessibleWidget::setValue(const QString &value)
 
274
{
 
275
    d->value = value;
 
276
}
 
277
 
 
278
/*!
 
279
    Sets the description of this interface implementation to \a desc.
 
280
 
 
281
    The default implementation of text() returns the set value for
 
282
    the Description text.
 
283
 
 
284
    Note that the object wrapped by this interface is not modified.
 
285
*/
 
286
void QAccessibleWidget::setDescription(const QString &desc)
 
287
{
 
288
    d->description = desc;
 
289
}
 
290
 
 
291
/*!
 
292
    Sets the help of this interface implementation to \a help.
 
293
 
 
294
    The default implementation of text() returns the set value for
 
295
    the Help text.
 
296
 
 
297
    Note that the object wrapped by this interface is not modified.
 
298
*/
 
299
void QAccessibleWidget::setHelp(const QString &help)
 
300
{
 
301
    d->help = help;
 
302
}
 
303
 
 
304
/*!
 
305
    Sets the accelerator of this interface implementation to \a accel.
 
306
 
 
307
    The default implementation of text() returns the set value for
 
308
    the Accelerator text.
 
309
 
 
310
    Note that the object wrapped by this interface is not modified.
 
311
*/
 
312
void QAccessibleWidget::setAccelerator(const QString &accel)
 
313
{
 
314
    d->accelerator = accel;
 
315
}
 
316
 
 
317
static inline bool isAncestor(const QObject *obj, const QObject *child)
 
318
{
 
319
    while (child) {
 
320
        if (child == obj)
 
321
            return true;
 
322
        child = child->parent();
 
323
    }
 
324
    return false;
 
325
}
 
326
 
 
327
 
 
328
/*! \reimp */
 
329
QAccessible::Relation QAccessibleWidget::relationTo(int child,
 
330
            const QAccessibleInterface *other, int otherChild) const
 
331
{
 
332
    Relation relation = Unrelated;
 
333
    if (d->asking == this) // recursive call
 
334
        return relation;
 
335
 
 
336
    QObject *o = other ? other->object() : 0;
 
337
    if (!o)
 
338
        return relation;
 
339
 
 
340
    QWidget *focus = widget()->focusWidget();
 
341
    if (object() == focus && isAncestor(o, focus))
 
342
        relation |= FocusChild;
 
343
 
 
344
    ConnectionObject *connectionObject = (ConnectionObject*)object();
 
345
    for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
 
346
        if (connectionObject->isSender(o, d->primarySignals.at(sig).toAscii())) {
 
347
            relation |= Controller;
 
348
            break;
 
349
        }
 
350
    }
 
351
    // test for passive relationships.
 
352
    // d->asking protects from endless recursion.
 
353
    d->asking = this;
 
354
    int inverse = other->relationTo(otherChild, this, child);
 
355
    d->asking = 0;
 
356
 
 
357
    if (inverse & Controller)
 
358
        relation |= Controlled;
 
359
    if (inverse & Label)
 
360
        relation |= Labelled;
 
361
 
 
362
    if(o == object()) {
 
363
        if (child && !otherChild)
 
364
            return relation | Child;
 
365
        if (!child && otherChild)
 
366
            return relation | Ancestor;
 
367
        if (!child && !otherChild)
 
368
            return relation | Self;
 
369
    }
 
370
 
 
371
    QObject *parent = object()->parent();
 
372
    if (o == parent)
 
373
        return relation | Child;
 
374
 
 
375
    if (o->parent() == parent) {
 
376
        relation |= Sibling;
 
377
        QAccessibleInterface *sibIface = QAccessible::queryAccessibleInterface(o);
 
378
        Q_ASSERT(sibIface);
 
379
        QRect wg = rect(0);
 
380
        QRect sg = sibIface->rect(0);
 
381
        if (wg.intersects(sg)) {
 
382
            QAccessibleInterface *pIface = 0;
 
383
            sibIface->navigate(Ancestor, 1, &pIface);
 
384
            if (pIface && !((sibIface->state(0) | state(0)) & Invisible)) {
 
385
                int wi = pIface->indexOfChild(this);
 
386
                int si = pIface->indexOfChild(sibIface);
 
387
 
 
388
                if (wi > si)
 
389
                    relation |= QAccessible::Covers;
 
390
                else
 
391
                    relation |= QAccessible::Covered;
 
392
            }
 
393
            delete pIface;
 
394
        } else {
 
395
            QPoint wc = wg.center();
 
396
            QPoint sc = sg.center();
 
397
            if (wc.x() < sc.x())
 
398
                relation |= QAccessible::Left;
 
399
            else if(wc.x() > sc.x())
 
400
                relation |= QAccessible::Right;
 
401
            if (wc.y() < sc.y())
 
402
                relation |= QAccessible::Up;
 
403
            else if (wc.y() > sc.y())
 
404
                relation |= QAccessible::Down;
 
405
        }
 
406
        delete sibIface;
 
407
 
 
408
        return relation;
 
409
    }
 
410
 
 
411
    if (isAncestor(o, object()))
 
412
        return relation | Descendent;
 
413
    if (isAncestor(object(), o))
 
414
        return relation | Ancestor;
 
415
 
 
416
    return relation;
 
417
}
 
418
 
 
419
/*! \reimp */
 
420
int QAccessibleWidget::navigate(RelationFlag relation, int entry,
 
421
                                QAccessibleInterface **target) const
 
422
{
 
423
    if (!target)
 
424
        return -1;
 
425
 
 
426
    *target = 0;
 
427
    QObject *targetObject = 0;
 
428
 
 
429
    QWidgetList childList = childWidgets(widget());
 
430
    bool complexWidget = childList.size() < childCount();
 
431
 
 
432
    switch (relation) {
 
433
    // Hierarchical
 
434
    case Self:
 
435
        targetObject = object();
 
436
        break;
 
437
    case Child:
 
438
        if (complexWidget) {
 
439
            if (entry > 0 && entry <= childCount())
 
440
                return entry;
 
441
            return -1;
 
442
        }else {
 
443
            if (entry > 0 && childList.size() >= entry)
 
444
                targetObject = childList.at(entry - 1);
 
445
        }
 
446
        break;
 
447
    case Ancestor:
 
448
        {
 
449
            if (entry <= 0)
 
450
                return -1;
 
451
            targetObject = widget()->parentWidget();
 
452
            int i;
 
453
            for (i = entry; i > 1 && targetObject; --i)
 
454
                targetObject = targetObject->parent();
 
455
            if (!targetObject && i == 1)
 
456
                targetObject = qApp;
 
457
        }
 
458
        break;
 
459
    case Sibling:
 
460
        {
 
461
            QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parentObject());
 
462
            if (!iface)
 
463
                return -1;
 
464
 
 
465
            iface->navigate(Child, entry, target);
 
466
            delete iface;
 
467
            if (*target)
 
468
                return 0;
 
469
        }
 
470
        break;
 
471
 
 
472
    // Geometrical
 
473
    case QAccessible::Left:
 
474
        if (complexWidget && entry) {
 
475
            if (entry < 2 || widget()->height() > widget()->width() + 20) // looks vertical
 
476
                return -1;
 
477
            return entry - 1;
 
478
        }
 
479
        // fall through
 
480
    case QAccessible::Right:
 
481
        if (complexWidget && entry) {
 
482
            if (entry >= childCount() || widget()->height() > widget()->width() + 20) // looks vertical
 
483
                return -1;
 
484
            return entry + 1;
 
485
        }
 
486
        // fall through
 
487
    case QAccessible::Up:
 
488
        if (complexWidget && entry) {
 
489
            if (entry < 2 || widget()->width() > widget()->height() + 20) // looks horizontal
 
490
                return - 1;
 
491
            return entry - 1;
 
492
        }
 
493
        // fall through
 
494
    case QAccessible::Down:
 
495
        if (complexWidget && entry) {
 
496
            if (entry >= childCount() || widget()->width() > widget()->height()  + 20) // looks horizontal
 
497
                return - 1;
 
498
            return entry + 1;
 
499
        } else {
 
500
            QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
 
501
            if (!pIface)
 
502
                return -1;
 
503
 
 
504
            QRect startg = rect(0);
 
505
            QPoint startc = startg.center();
 
506
            QAccessibleInterface *candidate = 0;
 
507
            int mindist = 100000;
 
508
            int sibCount = pIface->childCount();
 
509
            for (int i = 0; i < sibCount; ++i) {
 
510
                QAccessibleInterface *sibling = 0;
 
511
                pIface->navigate(Child, i+1, &sibling);
 
512
                Q_ASSERT(sibling);
 
513
                if ((relationTo(0, sibling, 0) & Self) || (sibling->state(0) & QAccessible::Invisible)) {
 
514
                    //ignore ourself and invisible siblings
 
515
                    delete sibling;
 
516
                    continue;
 
517
                }
 
518
 
 
519
                QRect sibg = sibling->rect(0);
 
520
                QPoint sibc = sibg.center();
 
521
                QPoint sibp;
 
522
                QPoint startp;
 
523
                QPoint distp;
 
524
                switch (relation) {
 
525
                case QAccessible::Left:
 
526
                    startp = QPoint(startg.left(), startg.top() + startg.height() / 2);
 
527
                    sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2);
 
528
                    if (QPoint(sibc - startc).x() >= 0) {
 
529
                        delete sibling;
 
530
                        continue;
 
531
                    }
 
532
                    distp = sibp - startp;
 
533
                    break;
 
534
                case QAccessible::Right:
 
535
                    startp = QPoint(startg.right(), startg.top() + startg.height() / 2);
 
536
                    sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2);
 
537
                    if (QPoint(sibc - startc).x() <= 0) {
 
538
                        delete sibling;
 
539
                        continue;
 
540
                    }
 
541
                    distp = sibp - startp;
 
542
                    break;
 
543
                case QAccessible::Up:
 
544
                    startp = QPoint(startg.left() + startg.width() / 2, startg.top());
 
545
                    sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom());
 
546
                    if (QPoint(sibc - startc).y() >= 0) {
 
547
                        delete sibling;
 
548
                        continue;
 
549
                    }
 
550
                    distp = sibp - startp;
 
551
                    break;
 
552
                case QAccessible::Down:
 
553
                    startp = QPoint(startg.left() + startg.width() / 2, startg.bottom());
 
554
                    sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top());
 
555
                    if (QPoint(sibc - startc).y() <= 0) {
 
556
                        delete sibling;
 
557
                        continue;
 
558
                    }
 
559
                    distp = sibp - startp;
 
560
                    break;
 
561
                default:
 
562
                    break;
 
563
                }
 
564
 
 
565
                int dist = (int)sqrt((double)distp.x() * distp.x() + distp.y() * distp.y());
 
566
                if (dist < mindist) {
 
567
                    delete candidate;
 
568
                    candidate = sibling;
 
569
                    mindist = dist;
 
570
                } else {
 
571
                    delete sibling;
 
572
                }
 
573
            }
 
574
            delete pIface;
 
575
            *target = candidate;
 
576
            if (*target)
 
577
                return 0;
 
578
        }
 
579
        break;
 
580
    case Covers:
 
581
        if (entry > 0) {
 
582
            QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
 
583
            if (!pIface)
 
584
                return -1;
 
585
 
 
586
            QRect r = rect(0);
 
587
            int sibCount = pIface->childCount();
 
588
            QAccessibleInterface *sibling = 0;
 
589
            for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) {
 
590
                pIface->navigate(Child, i, &sibling);
 
591
                Q_ASSERT(sibling);
 
592
                if (!sibling || (sibling->state(0) & Invisible)) {
 
593
                    delete sibling;
 
594
                    sibling = 0;
 
595
                    continue;
 
596
                }
 
597
                if (sibling->rect(0).intersects(r))
 
598
                    --entry;
 
599
                if (!entry)
 
600
                    break;
 
601
                delete sibling;
 
602
                sibling = 0;
 
603
            }
 
604
            delete pIface;
 
605
            *target = sibling;
 
606
            if (*target)
 
607
                return 0;
 
608
        }
 
609
        break;
 
610
    case Covered:
 
611
        if (entry > 0) {
 
612
            QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
 
613
            if (!pIface)
 
614
                return -1;
 
615
 
 
616
            QRect r = rect(0);
 
617
            int index = pIface->indexOfChild(this);
 
618
            QAccessibleInterface *sibling = 0;
 
619
            for (int i = 1; i < index && entry; ++i) {
 
620
                pIface->navigate(Child, i, &sibling);
 
621
                Q_ASSERT(sibling);
 
622
                if (!sibling || (sibling->state(0) & Invisible)) {
 
623
                    delete sibling;
 
624
                    sibling = 0;
 
625
                    continue;
 
626
                }
 
627
                if (sibling->rect(0).intersects(r))
 
628
                    --entry;
 
629
                if (!entry)
 
630
                    break;
 
631
                delete sibling;
 
632
                sibling = 0;
 
633
            }
 
634
            delete pIface;
 
635
            *target = sibling;
 
636
            if (*target)
 
637
                return 0;
 
638
        }
 
639
        break;
 
640
 
 
641
    // Logical
 
642
    case FocusChild:
 
643
        {
 
644
            if (widget()->hasFocus())
 
645
                return 0;
 
646
 
 
647
            QWidget *fw = widget()->focusWidget();
 
648
            if (!fw)
 
649
                return -1;
 
650
 
 
651
            if (isAncestor(widget(), fw))
 
652
                targetObject = fw;
 
653
            /* ###
 
654
            QWidget *parent = fw;
 
655
            while (parent && !targetObject) {
 
656
                parent = parent->parentWidget();
 
657
                if (parent == widget())
 
658
                    targetObject = fw;
 
659
            }
 
660
            */
 
661
        }
 
662
        break;
 
663
    case Label:
 
664
        if (entry > 0) {
 
665
            QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
 
666
            if (!pIface)
 
667
                return -1;
 
668
 
 
669
            // first check for all siblings that are labels to us
 
670
            // ideally we would go through all objects and check, but that
 
671
            // will be too expensive
 
672
            int sibCount = pIface->childCount();
 
673
            QAccessibleInterface *candidate = 0;
 
674
            for (int i = 0; i < sibCount && entry; ++i) {
 
675
                pIface->navigate(Child, i+1, &candidate);
 
676
                Q_ASSERT(candidate);
 
677
                if (candidate->relationTo(0, this, 0) & Label)
 
678
                    --entry;
 
679
                if (!entry)
 
680
                    break;
 
681
                delete candidate;
 
682
                candidate = 0;
 
683
            }
 
684
            if (!candidate) {
 
685
                if (pIface->relationTo(0, this, 0) & Label)
 
686
                    --entry;
 
687
                if (!entry)
 
688
                    candidate = pIface;
 
689
            }
 
690
            if (pIface != candidate)
 
691
                delete pIface;
 
692
 
 
693
            *target = candidate;
 
694
            if (*target)
 
695
                return 0;
 
696
        }
 
697
        break;
 
698
    case Labelled: // only implemented in subclasses
 
699
        break;
 
700
    case Controller:
 
701
        if (entry > 0) {
 
702
            // check all senders we are connected to,
 
703
            // and figure out which one are controllers to us
 
704
            ConnectionObject *connectionObject = (ConnectionObject*)object();
 
705
            QObjectList allSenders = connectionObject->senderList();
 
706
            QObjectList senders;
 
707
            for (int s = 0; s < allSenders.size(); ++s) {
 
708
                QObject *sender = allSenders.at(s);
 
709
                QAccessibleInterface *candidate = QAccessible::queryAccessibleInterface(sender);
 
710
                if (!candidate)
 
711
                    continue;
 
712
                if (candidate->relationTo(0, this, 0)&Controller)
 
713
                    senders << sender;
 
714
                delete candidate;
 
715
            }
 
716
            if (entry <= senders.size())
 
717
                targetObject = senders.at(entry-1);
 
718
        }
 
719
        break;
 
720
    case Controlled:
 
721
        if (entry > 0) {
 
722
            QObjectList allReceivers;
 
723
            ConnectionObject *connectionObject = (ConnectionObject*)object();
 
724
            for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
 
725
                QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toAscii());
 
726
                allReceivers += receivers;
 
727
            }
 
728
            if (entry <= allReceivers.size())
 
729
                targetObject = allReceivers.at(entry-1);
 
730
        }
 
731
        break;
 
732
    default:
 
733
        break;
 
734
    }
 
735
    *target = QAccessible::queryAccessibleInterface(targetObject);
 
736
    return *target ? 0 : -1;
 
737
}
 
738
 
 
739
/*! \reimp */
 
740
int QAccessibleWidget::childCount() const
 
741
{
 
742
    QWidgetList cl = childWidgets(widget());
 
743
    return cl.size();
 
744
}
 
745
 
 
746
/*! \reimp */
 
747
int QAccessibleWidget::indexOfChild(const QAccessibleInterface *child) const
 
748
{
 
749
    QWidgetList cl = childWidgets(widget());
 
750
    int index = cl.indexOf(qobject_cast<QWidget *>(child->object()));
 
751
    if (index != -1)
 
752
        ++index;
 
753
    return index;
 
754
}
 
755
 
 
756
/*! \reimp */
 
757
QString QAccessibleWidget::text(Text t, int child) const
 
758
{
 
759
    QString str;
 
760
 
 
761
    switch (t) {
 
762
    case Name:
 
763
        if (!d->name.isEmpty())
 
764
            str = d->name;
 
765
        else if (!widget()->accessibleName().isEmpty())
 
766
            str = widget()->accessibleName();
 
767
        else if (!child && widget()->isWindow())
 
768
            str = widget()->windowTitle();
 
769
        else
 
770
            str = qt_accStripAmp(buddyString(widget()));
 
771
        break;
 
772
    case Description:
 
773
        if (!d->description.isEmpty())
 
774
            str = d->description;
 
775
        else if (!widget()->accessibleDescription().isEmpty())
 
776
            str = widget()->accessibleDescription();
 
777
        else
 
778
            str = widget()->toolTip();
 
779
        break;
 
780
    case Help:
 
781
        if (!d->help.isEmpty())
 
782
            str = d->help;
 
783
        else
 
784
            str = widget()->whatsThis();
 
785
        break;
 
786
    case Accelerator:
 
787
        if (!d->accelerator.isEmpty())
 
788
            str = d->accelerator;
 
789
        else
 
790
            str = qt_accHotKey(buddyString(widget()));
 
791
        break;
 
792
    case Value:
 
793
        str = d->value;
 
794
        break;
 
795
    default:
 
796
        break;
 
797
    }
 
798
    return str;
 
799
}
 
800
 
 
801
/*! \reimp */
 
802
QString QAccessibleWidget::actionText(int action, Text t, int child) const
 
803
{
 
804
    if (action == DefaultAction)
 
805
        action = SetFocus;
 
806
 
 
807
    return QAccessibleObject::actionText(action, t, child);
 
808
}
 
809
 
 
810
/*! \reimp */
 
811
bool QAccessibleWidget::doAction(int action, int child, const QVariantList &params)
 
812
{
 
813
    if (action == SetFocus || action == DefaultAction) {
 
814
        if (child || !widget()->isEnabled())
 
815
            return false;
 
816
        if (widget()->focusPolicy() != Qt::NoFocus)
 
817
            widget()->setFocus();
 
818
        else if (widget()->isWindow())
 
819
            widget()->activateWindow();
 
820
        else
 
821
            return false;
 
822
        return true;
 
823
    }
 
824
    return QAccessibleObject::doAction(action, child, params);
 
825
}
 
826
 
 
827
/*! \reimp */
 
828
QAccessible::Role QAccessibleWidget::role(int child) const
 
829
{
 
830
    if (!child)
 
831
        return d->role;
 
832
    return NoRole;
 
833
}
 
834
 
 
835
/*! \reimp */
 
836
QAccessible::State QAccessibleWidget::state(int child) const
 
837
{
 
838
    if (child)
 
839
        return Normal;
 
840
 
 
841
    int state = Normal;
 
842
 
 
843
    QWidget *w = widget();
 
844
    if (w->testAttribute(Qt::WA_WState_Hidden))
 
845
        state |= Invisible;
 
846
    if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
 
847
        state |= Focusable;
 
848
    if (w->hasFocus())
 
849
        state |= Focused;
 
850
    if (!w->isEnabled())
 
851
        state |= Unavailable;
 
852
    if (w->isWindow()) {
 
853
        if (w->windowFlags() & Qt::WindowSystemMenuHint)
 
854
            state |= Movable;
 
855
        if (w->minimumSize() != w->maximumSize())
 
856
            state |= Sizeable;
 
857
    }
 
858
 
 
859
    return (State)state;
 
860
}
 
861
 
 
862
#endif //QT_NO_ACCESSIBILITY