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

Last change on this file since 100 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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