source: trunk/src/gui/accessible/qaccessiblewidget.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 31.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qaccessiblewidget.h"
43
44#ifndef QT_NO_ACCESSIBILITY
45
46#include "qaction.h"
47#include "qapplication.h"
48#include "qgroupbox.h"
49#include "qlabel.h"
50#include "qtooltip.h"
51#include "qwhatsthis.h"
52#include "qwidget.h"
53#include "qdebug.h"
54#include <qmath.h>
55#include <QRubberBand>
56#include <QtGui/QFocusFrame>
57#include <QtGui/QMenu>
58
59QT_BEGIN_NAMESPACE
60
61static QList<QWidget*> childWidgets(const QWidget *widget)
62{
63 QList<QObject*> list = widget->children();
64 QList<QWidget*> widgets;
65 for (int i = 0; i < list.size(); ++i) {
66 QWidget *w = qobject_cast<QWidget *>(list.at(i));
67 if (w && !w->isWindow()
68 && !qobject_cast<QFocusFrame*>(w)
69#if !defined(QT_NO_MENU)
70 && !qobject_cast<QMenu*>(w)
71#endif
72 && w->objectName() != QLatin1String("qt_rubberband"))
73 widgets.append(w);
74 }
75 return widgets;
76}
77
78static QString buddyString(const QWidget *widget)
79{
80 if (!widget)
81 return QString();
82 QWidget *parent = widget->parentWidget();
83 if (!parent)
84 return QString();
85#ifndef QT_NO_SHORTCUT
86 QObjectList ol = parent->children();
87 for (int i = 0; i < ol.size(); ++i) {
88 QLabel *label = qobject_cast<QLabel*>(ol.at(i));
89 if (label && label->buddy() == widget)
90 return label->text();
91 }
92#endif
93
94#ifndef QT_NO_GROUPBOX
95 QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent);
96 if (groupbox)
97 return groupbox->title();
98#endif
99
100 return QString();
101}
102
103QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
104{
105 return QString(text).remove(QLatin1Char('&'));
106}
107
108QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
109{
110#ifndef QT_NO_SHORTCUT
111 if (text.isEmpty())
112 return text;
113
114 int fa = 0;
115 QChar ac;
116 while ((fa = text.indexOf(QLatin1Char('&'), fa)) != -1) {
117 ++fa;
118 if (fa < text.length()) {
119 // ignore "&&"
120 if (text.at(fa) == QLatin1Char('&')) {
121 ++fa;
122 continue;
123 } else {
124 ac = text.at(fa);
125 break;
126 }
127 }
128 }
129 if (ac.isNull())
130 return QString();
131 return (QString)QKeySequence(Qt::ALT) + ac.toUpper();
132#else
133 Q_UNUSED(text);
134 return QString();
135#endif
136}
137
138class QAccessibleWidgetPrivate : public QAccessible
139{
140public:
141 QAccessibleWidgetPrivate()
142 :role(Client)
143 {}
144
145 Role role;
146 QString name;
147 QString description;
148 QString value;
149 QString help;
150 QString accelerator;
151 QStringList primarySignals;
152 const QAccessibleInterface *asking;
153};
154
155/*!
156 \class QAccessibleWidget
157 \brief The QAccessibleWidget class implements the QAccessibleInterface for QWidgets.
158
159 \ingroup accessibility
160
161 This class is convenient to use as a base class for custom
162 implementations of QAccessibleInterfaces that provide information
163 about widget objects.
164
165 The class provides functions to retrieve the parentObject() (the
166 widget's parent widget), and the associated widget(). Controlling
167 signals can be added with addControllingSignal(), and setters are
168 provided for various aspects of the interface implementation, for
169 example setValue(), setDescription(), setAccelerator(), and
170 setHelp().
171
172 \sa QAccessible, QAccessibleObject
173*/
174
175/*!
176 Creates a QAccessibleWidget object for widget \a w.
177 \a role and \a name are optional parameters that set the object's
178 role and name properties.
179*/
180QAccessibleWidget::QAccessibleWidget(QWidget *w, Role role, const QString &name)
181: QAccessibleObject(w)
182{
183 Q_ASSERT(widget());
184 d = new QAccessibleWidgetPrivate();
185 d->role = role;
186 d->name = name;
187 d->asking = 0;
188}
189
190/*!
191 Destroys this object.
192*/
193QAccessibleWidget::~QAccessibleWidget()
194{
195 delete d;
196}
197
198/*!
199 Returns the associated widget.
200*/
201QWidget *QAccessibleWidget::widget() const
202{
203 return qobject_cast<QWidget*>(object());
204}
205
206/*!
207 Returns the associated widget's parent object, which is either the
208 parent widget, or qApp for top-level widgets.
209*/
210QObject *QAccessibleWidget::parentObject() const
211{
212 QObject *parent = object()->parent();
213 if (!parent)
214 parent = qApp;
215 return parent;
216}
217
218/*! \reimp */
219int QAccessibleWidget::childAt(int x, int y) const
220{
221 QWidget *w = widget();
222 if (!w->isVisible())
223 return -1;
224 QPoint gp = w->mapToGlobal(QPoint(0, 0));
225 if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
226 return -1;
227
228 QWidgetList list = childWidgets(w);
229 int ccount = childCount();
230
231 // a complex child
232 if (list.size() < ccount) {
233 for (int i = 1; i <= ccount; ++i) {
234 if (rect(i).contains(x, y))
235 return i;
236 }
237 return 0;
238 }
239
240 QPoint rp = w->mapFromGlobal(QPoint(x, y));
241 for (int i = 0; i<list.size(); ++i) {
242 QWidget *child = list.at(i);
243 if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
244 return i + 1;
245 }
246 }
247 return 0;
248}
249
250/*! \reimp */
251QRect QAccessibleWidget::rect(int child) const
252{
253 if (child) {
254 qWarning("QAccessibleWidget::rect: This implementation does not support subelements! "
255 "(ID %d unknown for %s)", child, widget()->metaObject()->className());
256 }
257
258 QWidget *w = widget();
259 if (!w->isVisible())
260 return QRect();
261 QPoint wpos = w->mapToGlobal(QPoint(0, 0));
262
263 return QRect(wpos.x(), wpos.y(), w->width(), w->height());
264}
265
266QT_BEGIN_INCLUDE_NAMESPACE
267#include <private/qobject_p.h>
268QT_END_INCLUDE_NAMESPACE
269
270class QACConnectionObject : public QObject
271{
272 Q_DECLARE_PRIVATE(QObject)
273public:
274 inline bool isSender(const QObject *receiver, const char *signal) const
275 { return d_func()->isSender(receiver, signal); }
276 inline QObjectList receiverList(const char *signal) const
277 { return d_func()->receiverList(signal); }
278 inline QObjectList senderList() const
279 { return d_func()->senderList(); }
280};
281
282/*!
283 Registers \a signal as a controlling signal.
284
285 An object is a Controller to any other object connected to a
286 controlling signal.
287*/
288void QAccessibleWidget::addControllingSignal(const QString &signal)
289{
290 QByteArray s = QMetaObject::normalizedSignature(signal.toAscii());
291 if (object()->metaObject()->indexOfSignal(s) < 0)
292 qWarning("Signal %s unknown in %s", s.constData(), object()->metaObject()->className());
293 d->primarySignals << QLatin1String(s);
294}
295
296/*!
297 Sets the value of this interface implementation to \a value.
298
299 The default implementation of text() returns the set value for
300 the Value text.
301
302 Note that the object wrapped by this interface is not modified.
303*/
304void QAccessibleWidget::setValue(const QString &value)
305{
306 d->value = value;
307}
308
309/*!
310 Sets the description of this interface implementation to \a desc.
311
312 The default implementation of text() returns the set value for
313 the Description text.
314
315 Note that the object wrapped by this interface is not modified.
316*/
317void QAccessibleWidget::setDescription(const QString &desc)
318{
319 d->description = desc;
320}
321
322/*!
323 Sets the help of this interface implementation to \a help.
324
325 The default implementation of text() returns the set value for
326 the Help text.
327
328 Note that the object wrapped by this interface is not modified.
329*/
330void QAccessibleWidget::setHelp(const QString &help)
331{
332 d->help = help;
333}
334
335/*!
336 Sets the accelerator of this interface implementation to \a accel.
337
338 The default implementation of text() returns the set value for
339 the Accelerator text.
340
341 Note that the object wrapped by this interface is not modified.
342*/
343void QAccessibleWidget::setAccelerator(const QString &accel)
344{
345 d->accelerator = accel;
346}
347
348static inline bool isAncestor(const QObject *obj, const QObject *child)
349{
350 while (child) {
351 if (child == obj)
352 return true;
353 child = child->parent();
354 }
355 return false;
356}
357
358
359/*! \reimp */
360QAccessible::Relation QAccessibleWidget::relationTo(int child,
361 const QAccessibleInterface *other, int otherChild) const
362{
363 Relation relation = Unrelated;
364 if (d->asking == this) // recursive call
365 return relation;
366
367 QObject *o = other ? other->object() : 0;
368 if (!o)
369 return relation;
370
371 QWidget *focus = widget()->focusWidget();
372 if (object() == focus && isAncestor(o, focus))
373 relation |= FocusChild;
374
375 QACConnectionObject *connectionObject = (QACConnectionObject*)object();
376 for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
377 if (connectionObject->isSender(o, d->primarySignals.at(sig).toAscii())) {
378 relation |= Controller;
379 break;
380 }
381 }
382 // test for passive relationships.
383 // d->asking protects from endless recursion.
384 d->asking = this;
385 int inverse = other->relationTo(otherChild, this, child);
386 d->asking = 0;
387
388 if (inverse & Controller)
389 relation |= Controlled;
390 if (inverse & Label)
391 relation |= Labelled;
392
393 if(o == object()) {
394 if (child && !otherChild)
395 return relation | Child;
396 if (!child && otherChild)
397 return relation | Ancestor;
398 if (!child && !otherChild)
399 return relation | Self;
400 }
401
402 QObject *parent = object()->parent();
403 if (o == parent)
404 return relation | Child;
405
406 if (o->parent() == parent) {
407 relation |= Sibling;
408 QAccessibleInterface *sibIface = QAccessible::queryAccessibleInterface(o);
409 Q_ASSERT(sibIface);
410 QRect wg = rect(0);
411 QRect sg = sibIface->rect(0);
412 if (wg.intersects(sg)) {
413 QAccessibleInterface *pIface = 0;
414 sibIface->navigate(Ancestor, 1, &pIface);
415 if (pIface && !((sibIface->state(0) | state(0)) & Invisible)) {
416 int wi = pIface->indexOfChild(this);
417 int si = pIface->indexOfChild(sibIface);
418
419 if (wi > si)
420 relation |= QAccessible::Covers;
421 else
422 relation |= QAccessible::Covered;
423 }
424 delete pIface;
425 } else {
426 QPoint wc = wg.center();
427 QPoint sc = sg.center();
428 if (wc.x() < sc.x())
429 relation |= QAccessible::Left;
430 else if(wc.x() > sc.x())
431 relation |= QAccessible::Right;
432 if (wc.y() < sc.y())
433 relation |= QAccessible::Up;
434 else if (wc.y() > sc.y())
435 relation |= QAccessible::Down;
436 }
437 delete sibIface;
438
439 return relation;
440 }
441
442 if (isAncestor(o, object()))
443 return relation | Descendent;
444 if (isAncestor(object(), o))
445 return relation | Ancestor;
446
447 return relation;
448}
449
450/*! \reimp */
451int QAccessibleWidget::navigate(RelationFlag relation, int entry,
452 QAccessibleInterface **target) const
453{
454 if (!target)
455 return -1;
456
457 *target = 0;
458 QObject *targetObject = 0;
459
460 QWidgetList childList = childWidgets(widget());
461 bool complexWidget = childList.size() < childCount();
462
463 switch (relation) {
464 // Hierarchical
465 case Self:
466 targetObject = object();
467 break;
468 case Child:
469 if (complexWidget) {
470 if (entry > 0 && entry <= childCount())
471 return entry;
472 return -1;
473 }else {
474 if (entry > 0 && childList.size() >= entry)
475 targetObject = childList.at(entry - 1);
476 }
477 break;
478 case Ancestor:
479 {
480 if (entry <= 0)
481 return -1;
482 targetObject = widget()->parentWidget();
483 int i;
484 for (i = entry; i > 1 && targetObject; --i)
485 targetObject = targetObject->parent();
486 if (!targetObject && i == 1)
487 targetObject = qApp;
488 }
489 break;
490 case Sibling:
491 {
492 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parentObject());
493 if (!iface)
494 return -1;
495
496 iface->navigate(Child, entry, target);
497 delete iface;
498 if (*target)
499 return 0;
500 }
501 break;
502
503 // Geometrical
504 case QAccessible::Left:
505 if (complexWidget && entry) {
506 if (entry < 2 || widget()->height() > widget()->width() + 20) // looks vertical
507 return -1;
508 return entry - 1;
509 }
510 // fall through
511 case QAccessible::Right:
512 if (complexWidget && entry) {
513 if (entry >= childCount() || widget()->height() > widget()->width() + 20) // looks vertical
514 return -1;
515 return entry + 1;
516 }
517 // fall through
518 case QAccessible::Up:
519 if (complexWidget && entry) {
520 if (entry < 2 || widget()->width() > widget()->height() + 20) // looks horizontal
521 return - 1;
522 return entry - 1;
523 }
524 // fall through
525 case QAccessible::Down:
526 if (complexWidget && entry) {
527 if (entry >= childCount() || widget()->width() > widget()->height() + 20) // looks horizontal
528 return - 1;
529 return entry + 1;
530 } else {
531 QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
532 if (!pIface)
533 return -1;
534
535 QRect startg = rect(0);
536 QPoint startc = startg.center();
537 QAccessibleInterface *candidate = 0;
538 int mindist = 100000;
539 int sibCount = pIface->childCount();
540 for (int i = 0; i < sibCount; ++i) {
541 QAccessibleInterface *sibling = 0;
542 pIface->navigate(Child, i+1, &sibling);
543 Q_ASSERT(sibling);
544 if ((relationTo(0, sibling, 0) & Self) || (sibling->state(0) & QAccessible::Invisible)) {
545 //ignore ourself and invisible siblings
546 delete sibling;
547 continue;
548 }
549
550 QRect sibg = sibling->rect(0);
551 QPoint sibc = sibg.center();
552 QPoint sibp;
553 QPoint startp;
554 QPoint distp;
555 switch (relation) {
556 case QAccessible::Left:
557 startp = QPoint(startg.left(), startg.top() + startg.height() / 2);
558 sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2);
559 if (QPoint(sibc - startc).x() >= 0) {
560 delete sibling;
561 continue;
562 }
563 distp = sibp - startp;
564 break;
565 case QAccessible::Right:
566 startp = QPoint(startg.right(), startg.top() + startg.height() / 2);
567 sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2);
568 if (QPoint(sibc - startc).x() <= 0) {
569 delete sibling;
570 continue;
571 }
572 distp = sibp - startp;
573 break;
574 case QAccessible::Up:
575 startp = QPoint(startg.left() + startg.width() / 2, startg.top());
576 sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom());
577 if (QPoint(sibc - startc).y() >= 0) {
578 delete sibling;
579 continue;
580 }
581 distp = sibp - startp;
582 break;
583 case QAccessible::Down:
584 startp = QPoint(startg.left() + startg.width() / 2, startg.bottom());
585 sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top());
586 if (QPoint(sibc - startc).y() <= 0) {
587 delete sibling;
588 continue;
589 }
590 distp = sibp - startp;
591 break;
592 default:
593 break;
594 }
595
596 int dist = (int)qSqrt((qreal)distp.x() * distp.x() + distp.y() * distp.y());
597 if (dist < mindist) {
598 delete candidate;
599 candidate = sibling;
600 mindist = dist;
601 } else {
602 delete sibling;
603 }
604 }
605 delete pIface;
606 *target = candidate;
607 if (*target)
608 return 0;
609 }
610 break;
611 case Covers:
612 if (entry > 0) {
613 QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
614 if (!pIface)
615 return -1;
616
617 QRect r = rect(0);
618 int sibCount = pIface->childCount();
619 QAccessibleInterface *sibling = 0;
620 for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) {
621 pIface->navigate(Child, i, &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 case Covered:
641 if (entry > 0) {
642 QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
643 if (!pIface)
644 return -1;
645
646 QRect r = rect(0);
647 int index = pIface->indexOfChild(this);
648 QAccessibleInterface *sibling = 0;
649 for (int i = 1; i < index && entry; ++i) {
650 pIface->navigate(Child, i, &sibling);
651 Q_ASSERT(sibling);
652 if (!sibling || (sibling->state(0) & Invisible)) {
653 delete sibling;
654 sibling = 0;
655 continue;
656 }
657 if (sibling->rect(0).intersects(r))
658 --entry;
659 if (!entry)
660 break;
661 delete sibling;
662 sibling = 0;
663 }
664 delete pIface;
665 *target = sibling;
666 if (*target)
667 return 0;
668 }
669 break;
670
671 // Logical
672 case FocusChild:
673 {
674 if (widget()->hasFocus()) {
675 targetObject = object();
676 break;
677 }
678
679 QWidget *fw = widget()->focusWidget();
680 if (!fw)
681 return -1;
682
683 if (isAncestor(widget(), fw) || fw == widget())
684 targetObject = fw;
685 /* ###
686 QWidget *parent = fw;
687 while (parent && !targetObject) {
688 parent = parent->parentWidget();
689 if (parent == widget())
690 targetObject = fw;
691 }
692 */
693 }
694 break;
695 case Label:
696 if (entry > 0) {
697 QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
698 if (!pIface)
699 return -1;
700
701 // first check for all siblings that are labels to us
702 // ideally we would go through all objects and check, but that
703 // will be too expensive
704 int sibCount = pIface->childCount();
705 QAccessibleInterface *candidate = 0;
706 for (int i = 0; i < sibCount && entry; ++i) {
707 pIface->navigate(Child, i+1, &candidate);
708 Q_ASSERT(candidate);
709 if (candidate->relationTo(0, this, 0) & Label)
710 --entry;
711 if (!entry)
712 break;
713 delete candidate;
714 candidate = 0;
715 }
716 if (!candidate) {
717 if (pIface->relationTo(0, this, 0) & Label)
718 --entry;
719 if (!entry)
720 candidate = pIface;
721 }
722 if (pIface != candidate)
723 delete pIface;
724
725 *target = candidate;
726 if (*target)
727 return 0;
728 }
729 break;
730 case Labelled: // only implemented in subclasses
731 break;
732 case Controller:
733 if (entry > 0) {
734 // check all senders we are connected to,
735 // and figure out which one are controllers to us
736 QACConnectionObject *connectionObject = (QACConnectionObject*)object();
737 QObjectList allSenders = connectionObject->senderList();
738 QObjectList senders;
739 for (int s = 0; s < allSenders.size(); ++s) {
740 QObject *sender = allSenders.at(s);
741 QAccessibleInterface *candidate = QAccessible::queryAccessibleInterface(sender);
742 if (!candidate)
743 continue;
744 if (candidate->relationTo(0, this, 0)&Controller)
745 senders << sender;
746 delete candidate;
747 }
748 if (entry <= senders.size())
749 targetObject = senders.at(entry-1);
750 }
751 break;
752 case Controlled:
753 if (entry > 0) {
754 QObjectList allReceivers;
755 QACConnectionObject *connectionObject = (QACConnectionObject*)object();
756 for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
757 QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toAscii());
758 allReceivers += receivers;
759 }
760 if (entry <= allReceivers.size())
761 targetObject = allReceivers.at(entry-1);
762 }
763 break;
764 default:
765 break;
766 }
767
768 *target = QAccessible::queryAccessibleInterface(targetObject);
769 return *target ? 0 : -1;
770}
771
772/*! \reimp */
773int QAccessibleWidget::childCount() const
774{
775 QWidgetList cl = childWidgets(widget());
776 return cl.size();
777}
778
779/*! \reimp */
780int QAccessibleWidget::indexOfChild(const QAccessibleInterface *child) const
781{
782 QWidgetList cl = childWidgets(widget());
783 int index = cl.indexOf(qobject_cast<QWidget *>(child->object()));
784 if (index != -1)
785 ++index;
786 return index;
787}
788
789// from qwidget.cpp
790extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
791
792/*! \reimp */
793QString QAccessibleWidget::text(Text t, int child) const
794{
795 QString str;
796
797 switch (t) {
798 case Name:
799 if (!d->name.isEmpty()) {
800 str = d->name;
801 } else if (!widget()->accessibleName().isEmpty()) {
802 str = widget()->accessibleName();
803 } else if (!child && widget()->isWindow()) {
804 if (widget()->isMinimized())
805 str = qt_setWindowTitle_helperHelper(widget()->windowIconText(), widget());
806 else
807 str = qt_setWindowTitle_helperHelper(widget()->windowTitle(), widget());
808 } else {
809 str = qt_accStripAmp(buddyString(widget()));
810 }
811 break;
812 case Description:
813 if (!d->description.isEmpty())
814 str = d->description;
815 else if (!widget()->accessibleDescription().isEmpty())
816 str = widget()->accessibleDescription();
817#ifndef QT_NO_TOOLTIP
818 else
819 str = widget()->toolTip();
820#endif
821 break;
822 case Help:
823 if (!d->help.isEmpty())
824 str = d->help;
825#ifndef QT_NO_WHATSTHIS
826 else
827 str = widget()->whatsThis();
828#endif
829 break;
830 case Accelerator:
831 if (!d->accelerator.isEmpty())
832 str = d->accelerator;
833 else
834 str = qt_accHotKey(buddyString(widget()));
835 break;
836 case Value:
837 str = d->value;
838 break;
839 default:
840 break;
841 }
842 return str;
843}
844
845#ifndef QT_NO_ACTION
846
847/*! \reimp */
848int QAccessibleWidget::userActionCount(int child) const
849{
850 if (child)
851 return 0;
852 return widget()->actions().count();
853}
854
855/*! \reimp */
856QString QAccessibleWidget::actionText(int action, Text t, int child) const
857{
858 if (action == DefaultAction)
859 action = SetFocus;
860
861 if (action > 0 && !child) {
862 QAction *act = widget()->actions().value(action - 1);
863 if (act) {
864 switch (t) {
865 case Name:
866 return act->text();
867 case Description:
868 return act->toolTip();
869#ifndef QT_NO_SHORTCUT
870 case Accelerator:
871 return act->shortcut().toString();
872#endif
873 default:
874 break;
875 }
876 }
877 }
878
879 return QAccessibleObject::actionText(action, t, child);
880}
881
882/*! \reimp */
883bool QAccessibleWidget::doAction(int action, int child, const QVariantList &params)
884{
885 if (action == SetFocus || action == DefaultAction) {
886 if (child || !widget()->isEnabled())
887 return false;
888 if (widget()->focusPolicy() != Qt::NoFocus)
889 widget()->setFocus();
890 else if (widget()->isWindow())
891 widget()->activateWindow();
892 else
893 return false;
894 return true;
895 } else if (action > 0) {
896 if (QAction *act = widget()->actions().value(action - 1)) {
897 act->trigger();
898 return true;
899 }
900 }
901 return QAccessibleObject::doAction(action, child, params);
902}
903
904#endif // QT_NO_ACTION
905
906/*! \reimp */
907QAccessible::Role QAccessibleWidget::role(int child) const
908{
909 if (!child)
910 return d->role;
911
912 QWidgetList childList = childWidgets(widget());
913 if (childList.count() > 0 && child <= childList.count()) {
914 QWidget *targetWidget = childList.at(child - 1);
915 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(targetWidget);
916 if (iface) {
917 QAccessible::Role role = iface->role(0);
918 delete iface;
919 return role;
920 }
921 }
922
923 return NoRole;
924}
925
926/*! \reimp */
927QAccessible::State QAccessibleWidget::state(int child) const
928{
929 if (child)
930 return Normal;
931
932 QAccessible::State state = Normal;
933
934 QWidget *w = widget();
935 if (w->testAttribute(Qt::WA_WState_Visible) == false)
936 state |= Invisible;
937 if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
938 state |= Focusable;
939 if (w->hasFocus())
940 state |= Focused;
941 if (!w->isEnabled())
942 state |= Unavailable;
943 if (w->isWindow()) {
944 if (w->windowFlags() & Qt::WindowSystemMenuHint)
945 state |= Movable;
946 if (w->minimumSize() != w->maximumSize())
947 state |= Sizeable;
948 }
949
950 return state;
951}
952
953// ### Qt 5: remove me - binary compatibility hack
954QAccessibleWidgetEx::QAccessibleWidgetEx(QWidget *o, Role role, const QString& name)
955 : QAccessibleObjectEx(o)
956{
957 Q_ASSERT(widget());
958 d = new QAccessibleWidgetPrivate();
959 d->role = role;
960 d->name = name;
961 d->asking = 0;
962}
963
964int QAccessibleWidgetEx::childCount() const
965{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childCount(); }
966int QAccessibleWidgetEx::indexOfChild(const QAccessibleInterface *child) const
967{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::indexOfChild(child); }
968QAccessible::Relation QAccessibleWidgetEx::relationTo(int child, const QAccessibleInterface *other, int otherChild) const
969{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::relationTo(child, other, otherChild); }
970
971int QAccessibleWidgetEx::childAt(int x, int y) const
972{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childAt(x, y); }
973QRect QAccessibleWidgetEx::rect(int child) const
974{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::rect(child); }
975int QAccessibleWidgetEx::navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const
976{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::navigate(rel, entry, target); }
977
978QString QAccessibleWidgetEx::text(Text t, int child) const
979{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::text(t, child); }
980QAccessible::Role QAccessibleWidgetEx::role(int child) const
981{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::role(child); }
982QAccessible::State QAccessibleWidgetEx::state(int child) const
983{ return (reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::state(child))
984 | HasInvokeExtension; }
985
986QString QAccessibleWidgetEx::actionText(int action, Text t, int child) const
987{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::actionText(action, t, child); }
988bool QAccessibleWidgetEx::doAction(int action, int child, const QVariantList &params)
989{ return reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::doAction(action, child, params); }
990
991QAccessibleWidgetEx::~QAccessibleWidgetEx()
992{ delete d; }
993QWidget *QAccessibleWidgetEx::widget() const
994{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::widget(); }
995QObject *QAccessibleWidgetEx::parentObject() const
996{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::parentObject(); }
997
998void QAccessibleWidgetEx::addControllingSignal(const QString &signal)
999{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::addControllingSignal(signal); }
1000void QAccessibleWidgetEx::setValue(const QString &value)
1001{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setValue(value); }
1002void QAccessibleWidgetEx::setDescription(const QString &desc)
1003{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setDescription(desc); }
1004void QAccessibleWidgetEx::setHelp(const QString &help)
1005{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setHelp(help); }
1006void QAccessibleWidgetEx::setAccelerator(const QString &accel)
1007{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setAccelerator(accel); }
1008
1009QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVariantList & /*params*/)
1010{
1011 if (child)
1012 return QVariant();
1013
1014 switch (method) {
1015 case ListSupportedMethods: {
1016 QSet<QAccessible::Method> set;
1017 set << ListSupportedMethods << ForegroundColor << BackgroundColor;
1018 return qVariantFromValue(set);
1019 }
1020 case ForegroundColor:
1021 return widget()->palette().color(widget()->foregroundRole());
1022 case BackgroundColor:
1023 return widget()->palette().color(widget()->backgroundRole());
1024 default:
1025 return QVariant();
1026 }
1027}
1028
1029QT_END_NAMESPACE
1030
1031#endif //QT_NO_ACCESSIBILITY
Note: See TracBrowser for help on using the repository browser.