summaryrefslogtreecommitdiffstats
path: root/src/gui/accessible/qaccessiblewidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/accessible/qaccessiblewidget.cpp')
-rw-r--r--src/gui/accessible/qaccessiblewidget.cpp1031
1 files changed, 1031 insertions, 0 deletions
diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp
new file mode 100644
index 0000000000..2b2cec0f02
--- /dev/null
+++ b/src/gui/accessible/qaccessiblewidget.cpp
@@ -0,0 +1,1031 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidget.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qaction.h"
+#include "qapplication.h"
+#include "qgroupbox.h"
+#include "qlabel.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#include "qwidget.h"
+#include "qdebug.h"
+#include <qmath.h>
+#include <QRubberBand>
+#include <QtGui/QFocusFrame>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+static QList<QWidget*> childWidgets(const QWidget *widget)
+{
+ QList<QObject*> list = widget->children();
+ QList<QWidget*> widgets;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(list.at(i));
+ if (w && !w->isWindow()
+ && !qobject_cast<QFocusFrame*>(w)
+#if !defined(QT_NO_MENU)
+ && !qobject_cast<QMenu*>(w)
+#endif
+ && w->objectName() != QLatin1String("qt_rubberband"))
+ widgets.append(w);
+ }
+ return widgets;
+}
+
+static QString buddyString(const QWidget *widget)
+{
+ if (!widget)
+ return QString();
+ QWidget *parent = widget->parentWidget();
+ if (!parent)
+ return QString();
+#ifndef QT_NO_SHORTCUT
+ QObjectList ol = parent->children();
+ for (int i = 0; i < ol.size(); ++i) {
+ QLabel *label = qobject_cast<QLabel*>(ol.at(i));
+ if (label && label->buddy() == widget)
+ return label->text();
+ }
+#endif
+
+#ifndef QT_NO_GROUPBOX
+ QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent);
+ if (groupbox)
+ return groupbox->title();
+#endif
+
+ return QString();
+}
+
+QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
+{
+ return QString(text).remove(QLatin1Char('&'));
+}
+
+QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
+{
+#ifndef QT_NO_SHORTCUT
+ if (text.isEmpty())
+ return text;
+
+ int fa = 0;
+ QChar ac;
+ while ((fa = text.indexOf(QLatin1Char('&'), fa)) != -1) {
+ ++fa;
+ if (fa < text.length()) {
+ // ignore "&&"
+ if (text.at(fa) == QLatin1Char('&')) {
+ ++fa;
+ continue;
+ } else {
+ ac = text.at(fa);
+ break;
+ }
+ }
+ }
+ if (ac.isNull())
+ return QString();
+ return (QString)QKeySequence(Qt::ALT) + ac.toUpper();
+#else
+ Q_UNUSED(text);
+ return QString();
+#endif
+}
+
+class QAccessibleWidgetPrivate : public QAccessible
+{
+public:
+ QAccessibleWidgetPrivate()
+ :role(Client)
+ {}
+
+ Role role;
+ QString name;
+ QString description;
+ QString value;
+ QString help;
+ QString accelerator;
+ QStringList primarySignals;
+ const QAccessibleInterface *asking;
+};
+
+/*!
+ \class QAccessibleWidget
+ \brief The QAccessibleWidget class implements the QAccessibleInterface for QWidgets.
+
+ \ingroup accessibility
+
+ This class is convenient to use as a base class for custom
+ implementations of QAccessibleInterfaces that provide information
+ about widget objects.
+
+ The class provides functions to retrieve the parentObject() (the
+ widget's parent widget), and the associated widget(). Controlling
+ signals can be added with addControllingSignal(), and setters are
+ provided for various aspects of the interface implementation, for
+ example setValue(), setDescription(), setAccelerator(), and
+ setHelp().
+
+ \sa QAccessible, QAccessibleObject
+*/
+
+/*!
+ Creates a QAccessibleWidget object for widget \a w.
+ \a role and \a name are optional parameters that set the object's
+ role and name properties.
+*/
+QAccessibleWidget::QAccessibleWidget(QWidget *w, Role role, const QString &name)
+: QAccessibleObject(w)
+{
+ Q_ASSERT(widget());
+ d = new QAccessibleWidgetPrivate();
+ d->role = role;
+ d->name = name;
+ d->asking = 0;
+}
+
+/*!
+ Destroys this object.
+*/
+QAccessibleWidget::~QAccessibleWidget()
+{
+ delete d;
+}
+
+/*!
+ Returns the associated widget.
+*/
+QWidget *QAccessibleWidget::widget() const
+{
+ return qobject_cast<QWidget*>(object());
+}
+
+/*!
+ Returns the associated widget's parent object, which is either the
+ parent widget, or qApp for top-level widgets.
+*/
+QObject *QAccessibleWidget::parentObject() const
+{
+ QObject *parent = object()->parent();
+ if (!parent)
+ parent = qApp;
+ return parent;
+}
+
+/*! \reimp */
+int QAccessibleWidget::childAt(int x, int y) const
+{
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return -1;
+ QPoint gp = w->mapToGlobal(QPoint(0, 0));
+ if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
+ return -1;
+
+ QWidgetList list = childWidgets(w);
+ int ccount = childCount();
+
+ // a complex child
+ if (list.size() < ccount) {
+ for (int i = 1; i <= ccount; ++i) {
+ if (rect(i).contains(x, y))
+ return i;
+ }
+ return 0;
+ }
+
+ QPoint rp = w->mapFromGlobal(QPoint(x, y));
+ for (int i = 0; i<list.size(); ++i) {
+ QWidget *child = list.at(i);
+ if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
+ return i + 1;
+ }
+ }
+ return 0;
+}
+
+/*! \reimp */
+QRect QAccessibleWidget::rect(int child) const
+{
+ if (child) {
+ qWarning("QAccessibleWidget::rect: This implementation does not support subelements! "
+ "(ID %d unknown for %s)", child, widget()->metaObject()->className());
+ }
+
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return QRect();
+ QPoint wpos = w->mapToGlobal(QPoint(0, 0));
+
+ return QRect(wpos.x(), wpos.y(), w->width(), w->height());
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <private/qobject_p.h>
+QT_END_INCLUDE_NAMESPACE
+
+class QACConnectionObject : public QObject
+{
+ Q_DECLARE_PRIVATE(QObject)
+public:
+ inline bool isSender(const QObject *receiver, const char *signal) const
+ { return d_func()->isSender(receiver, signal); }
+ inline QObjectList receiverList(const char *signal) const
+ { return d_func()->receiverList(signal); }
+ inline QObjectList senderList() const
+ { return d_func()->senderList(); }
+};
+
+/*!
+ Registers \a signal as a controlling signal.
+
+ An object is a Controller to any other object connected to a
+ controlling signal.
+*/
+void QAccessibleWidget::addControllingSignal(const QString &signal)
+{
+ QByteArray s = QMetaObject::normalizedSignature(signal.toAscii());
+ if (object()->metaObject()->indexOfSignal(s) < 0)
+ qWarning("Signal %s unknown in %s", s.constData(), object()->metaObject()->className());
+ d->primarySignals << QLatin1String(s);
+}
+
+/*!
+ Sets the value of this interface implementation to \a value.
+
+ The default implementation of text() returns the set value for
+ the Value text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setValue(const QString &value)
+{
+ d->value = value;
+}
+
+/*!
+ Sets the description of this interface implementation to \a desc.
+
+ The default implementation of text() returns the set value for
+ the Description text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setDescription(const QString &desc)
+{
+ d->description = desc;
+}
+
+/*!
+ Sets the help of this interface implementation to \a help.
+
+ The default implementation of text() returns the set value for
+ the Help text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setHelp(const QString &help)
+{
+ d->help = help;
+}
+
+/*!
+ Sets the accelerator of this interface implementation to \a accel.
+
+ The default implementation of text() returns the set value for
+ the Accelerator text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setAccelerator(const QString &accel)
+{
+ d->accelerator = accel;
+}
+
+static inline bool isAncestor(const QObject *obj, const QObject *child)
+{
+ while (child) {
+ if (child == obj)
+ return true;
+ child = child->parent();
+ }
+ return false;
+}
+
+
+/*! \reimp */
+QAccessible::Relation QAccessibleWidget::relationTo(int child,
+ const QAccessibleInterface *other, int otherChild) const
+{
+ Relation relation = Unrelated;
+ if (d->asking == this) // recursive call
+ return relation;
+
+ QObject *o = other ? other->object() : 0;
+ if (!o)
+ return relation;
+
+ QWidget *focus = widget()->focusWidget();
+ if (object() == focus && isAncestor(o, focus))
+ relation |= FocusChild;
+
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
+ if (connectionObject->isSender(o, d->primarySignals.at(sig).toAscii())) {
+ relation |= Controller;
+ break;
+ }
+ }
+ // test for passive relationships.
+ // d->asking protects from endless recursion.
+ d->asking = this;
+ int inverse = other->relationTo(otherChild, this, child);
+ d->asking = 0;
+
+ if (inverse & Controller)
+ relation |= Controlled;
+ if (inverse & Label)
+ relation |= Labelled;
+
+ if(o == object()) {
+ if (child && !otherChild)
+ return relation | Child;
+ if (!child && otherChild)
+ return relation | Ancestor;
+ if (!child && !otherChild)
+ return relation | Self;
+ }
+
+ QObject *parent = object()->parent();
+ if (o == parent)
+ return relation | Child;
+
+ if (o->parent() == parent) {
+ relation |= Sibling;
+ QAccessibleInterface *sibIface = QAccessible::queryAccessibleInterface(o);
+ Q_ASSERT(sibIface);
+ QRect wg = rect(0);
+ QRect sg = sibIface->rect(0);
+ if (wg.intersects(sg)) {
+ QAccessibleInterface *pIface = 0;
+ sibIface->navigate(Ancestor, 1, &pIface);
+ if (pIface && !((sibIface->state(0) | state(0)) & Invisible)) {
+ int wi = pIface->indexOfChild(this);
+ int si = pIface->indexOfChild(sibIface);
+
+ if (wi > si)
+ relation |= QAccessible::Covers;
+ else
+ relation |= QAccessible::Covered;
+ }
+ delete pIface;
+ } else {
+ QPoint wc = wg.center();
+ QPoint sc = sg.center();
+ if (wc.x() < sc.x())
+ relation |= QAccessible::Left;
+ else if(wc.x() > sc.x())
+ relation |= QAccessible::Right;
+ if (wc.y() < sc.y())
+ relation |= QAccessible::Up;
+ else if (wc.y() > sc.y())
+ relation |= QAccessible::Down;
+ }
+ delete sibIface;
+
+ return relation;
+ }
+
+ if (isAncestor(o, object()))
+ return relation | Descendent;
+ if (isAncestor(object(), o))
+ return relation | Ancestor;
+
+ return relation;
+}
+
+/*! \reimp */
+int QAccessibleWidget::navigate(RelationFlag relation, int entry,
+ QAccessibleInterface **target) const
+{
+ if (!target)
+ return -1;
+
+ *target = 0;
+ QObject *targetObject = 0;
+
+ QWidgetList childList = childWidgets(widget());
+ bool complexWidget = childList.size() < childCount();
+
+ switch (relation) {
+ // Hierarchical
+ case Self:
+ targetObject = object();
+ break;
+ case Child:
+ if (complexWidget) {
+ if (entry > 0 && entry <= childCount())
+ return entry;
+ return -1;
+ }else {
+ if (entry > 0 && childList.size() >= entry)
+ targetObject = childList.at(entry - 1);
+ }
+ break;
+ case Ancestor:
+ {
+ if (entry <= 0)
+ return -1;
+ targetObject = widget()->parentWidget();
+ int i;
+ for (i = entry; i > 1 && targetObject; --i)
+ targetObject = targetObject->parent();
+ if (!targetObject && i == 1)
+ targetObject = qApp;
+ }
+ break;
+ case Sibling:
+ {
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!iface)
+ return -1;
+
+ iface->navigate(Child, entry, target);
+ delete iface;
+ if (*target)
+ return 0;
+ }
+ break;
+
+ // Geometrical
+ case QAccessible::Left:
+ if (complexWidget && entry) {
+ if (entry < 2 || widget()->height() > widget()->width() + 20) // looks vertical
+ return -1;
+ return entry - 1;
+ }
+ // fall through
+ case QAccessible::Right:
+ if (complexWidget && entry) {
+ if (entry >= childCount() || widget()->height() > widget()->width() + 20) // looks vertical
+ return -1;
+ return entry + 1;
+ }
+ // fall through
+ case QAccessible::Up:
+ if (complexWidget && entry) {
+ if (entry < 2 || widget()->width() > widget()->height() + 20) // looks horizontal
+ return - 1;
+ return entry - 1;
+ }
+ // fall through
+ case QAccessible::Down:
+ if (complexWidget && entry) {
+ if (entry >= childCount() || widget()->width() > widget()->height() + 20) // looks horizontal
+ return - 1;
+ return entry + 1;
+ } else {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect startg = rect(0);
+ QPoint startc = startg.center();
+ QAccessibleInterface *candidate = 0;
+ int mindist = 100000;
+ int sibCount = pIface->childCount();
+ for (int i = 0; i < sibCount; ++i) {
+ QAccessibleInterface *sibling = 0;
+ pIface->navigate(Child, i+1, &sibling);
+ Q_ASSERT(sibling);
+ if ((relationTo(0, sibling, 0) & Self) || (sibling->state(0) & QAccessible::Invisible)) {
+ //ignore ourself and invisible siblings
+ delete sibling;
+ continue;
+ }
+
+ QRect sibg = sibling->rect(0);
+ QPoint sibc = sibg.center();
+ QPoint sibp;
+ QPoint startp;
+ QPoint distp;
+ switch (relation) {
+ case QAccessible::Left:
+ startp = QPoint(startg.left(), startg.top() + startg.height() / 2);
+ sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2);
+ if (QPoint(sibc - startc).x() >= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Right:
+ startp = QPoint(startg.right(), startg.top() + startg.height() / 2);
+ sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2);
+ if (QPoint(sibc - startc).x() <= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Up:
+ startp = QPoint(startg.left() + startg.width() / 2, startg.top());
+ sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom());
+ if (QPoint(sibc - startc).y() >= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Down:
+ startp = QPoint(startg.left() + startg.width() / 2, startg.bottom());
+ sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top());
+ if (QPoint(sibc - startc).y() <= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ default:
+ break;
+ }
+
+ int dist = (int)qSqrt((qreal)distp.x() * distp.x() + distp.y() * distp.y());
+ if (dist < mindist) {
+ delete candidate;
+ candidate = sibling;
+ mindist = dist;
+ } else {
+ delete sibling;
+ }
+ }
+ delete pIface;
+ *target = candidate;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Covers:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect r = rect(0);
+ int sibCount = pIface->childCount();
+ QAccessibleInterface *sibling = 0;
+ for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) {
+ pIface->navigate(Child, i, &sibling);
+ if (!sibling || (sibling->state(0) & Invisible)) {
+ delete sibling;
+ sibling = 0;
+ continue;
+ }
+ if (sibling->rect(0).intersects(r))
+ --entry;
+ if (!entry)
+ break;
+ delete sibling;
+ sibling = 0;
+ }
+ delete pIface;
+ *target = sibling;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Covered:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect r = rect(0);
+ int index = pIface->indexOfChild(this);
+ QAccessibleInterface *sibling = 0;
+ for (int i = 1; i < index && entry; ++i) {
+ pIface->navigate(Child, i, &sibling);
+ Q_ASSERT(sibling);
+ if (!sibling || (sibling->state(0) & Invisible)) {
+ delete sibling;
+ sibling = 0;
+ continue;
+ }
+ if (sibling->rect(0).intersects(r))
+ --entry;
+ if (!entry)
+ break;
+ delete sibling;
+ sibling = 0;
+ }
+ delete pIface;
+ *target = sibling;
+ if (*target)
+ return 0;
+ }
+ break;
+
+ // Logical
+ case FocusChild:
+ {
+ if (widget()->hasFocus()) {
+ targetObject = object();
+ break;
+ }
+
+ QWidget *fw = widget()->focusWidget();
+ if (!fw)
+ return -1;
+
+ if (isAncestor(widget(), fw) || fw == widget())
+ targetObject = fw;
+ /* ###
+ QWidget *parent = fw;
+ while (parent && !targetObject) {
+ parent = parent->parentWidget();
+ if (parent == widget())
+ targetObject = fw;
+ }
+ */
+ }
+ break;
+ case Label:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ // first check for all siblings that are labels to us
+ // ideally we would go through all objects and check, but that
+ // will be too expensive
+ int sibCount = pIface->childCount();
+ QAccessibleInterface *candidate = 0;
+ for (int i = 0; i < sibCount && entry; ++i) {
+ pIface->navigate(Child, i+1, &candidate);
+ Q_ASSERT(candidate);
+ if (candidate->relationTo(0, this, 0) & Label)
+ --entry;
+ if (!entry)
+ break;
+ delete candidate;
+ candidate = 0;
+ }
+ if (!candidate) {
+ if (pIface->relationTo(0, this, 0) & Label)
+ --entry;
+ if (!entry)
+ candidate = pIface;
+ }
+ if (pIface != candidate)
+ delete pIface;
+
+ *target = candidate;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Labelled: // only implemented in subclasses
+ break;
+ case Controller:
+ if (entry > 0) {
+ // check all senders we are connected to,
+ // and figure out which one are controllers to us
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ QObjectList allSenders = connectionObject->senderList();
+ QObjectList senders;
+ for (int s = 0; s < allSenders.size(); ++s) {
+ QObject *sender = allSenders.at(s);
+ QAccessibleInterface *candidate = QAccessible::queryAccessibleInterface(sender);
+ if (!candidate)
+ continue;
+ if (candidate->relationTo(0, this, 0)&Controller)
+ senders << sender;
+ delete candidate;
+ }
+ if (entry <= senders.size())
+ targetObject = senders.at(entry-1);
+ }
+ break;
+ case Controlled:
+ if (entry > 0) {
+ QObjectList allReceivers;
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
+ QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toAscii());
+ allReceivers += receivers;
+ }
+ if (entry <= allReceivers.size())
+ targetObject = allReceivers.at(entry-1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ *target = QAccessible::queryAccessibleInterface(targetObject);
+ return *target ? 0 : -1;
+}
+
+/*! \reimp */
+int QAccessibleWidget::childCount() const
+{
+ QWidgetList cl = childWidgets(widget());
+ return cl.size();
+}
+
+/*! \reimp */
+int QAccessibleWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ QWidgetList cl = childWidgets(widget());
+ int index = cl.indexOf(qobject_cast<QWidget *>(child->object()));
+ if (index != -1)
+ ++index;
+ return index;
+}
+
+// from qwidget.cpp
+extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
+
+/*! \reimp */
+QString QAccessibleWidget::text(Text t, int child) const
+{
+ QString str;
+
+ switch (t) {
+ case Name:
+ if (!d->name.isEmpty()) {
+ str = d->name;
+ } else if (!widget()->accessibleName().isEmpty()) {
+ str = widget()->accessibleName();
+ } else if (!child && widget()->isWindow()) {
+ if (widget()->isMinimized())
+ str = qt_setWindowTitle_helperHelper(widget()->windowIconText(), widget());
+ else
+ str = qt_setWindowTitle_helperHelper(widget()->windowTitle(), widget());
+ } else {
+ str = qt_accStripAmp(buddyString(widget()));
+ }
+ break;
+ case Description:
+ if (!d->description.isEmpty())
+ str = d->description;
+ else if (!widget()->accessibleDescription().isEmpty())
+ str = widget()->accessibleDescription();
+#ifndef QT_NO_TOOLTIP
+ else
+ str = widget()->toolTip();
+#endif
+ break;
+ case Help:
+ if (!d->help.isEmpty())
+ str = d->help;
+#ifndef QT_NO_WHATSTHIS
+ else
+ str = widget()->whatsThis();
+#endif
+ break;
+ case Accelerator:
+ if (!d->accelerator.isEmpty())
+ str = d->accelerator;
+ else
+ str = qt_accHotKey(buddyString(widget()));
+ break;
+ case Value:
+ str = d->value;
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
+#ifndef QT_NO_ACTION
+
+/*! \reimp */
+int QAccessibleWidget::userActionCount(int child) const
+{
+ if (child)
+ return 0;
+ return widget()->actions().count();
+}
+
+/*! \reimp */
+QString QAccessibleWidget::actionText(int action, Text t, int child) const
+{
+ if (action == DefaultAction)
+ action = SetFocus;
+
+ if (action > 0 && !child) {
+ QAction *act = widget()->actions().value(action - 1);
+ if (act) {
+ switch (t) {
+ case Name:
+ return act->text();
+ case Description:
+ return act->toolTip();
+#ifndef QT_NO_SHORTCUT
+ case Accelerator:
+ return act->shortcut().toString();
+#endif
+ default:
+ break;
+ }
+ }
+ }
+
+ return QAccessibleObject::actionText(action, t, child);
+}
+
+/*! \reimp */
+bool QAccessibleWidget::doAction(int action, int child, const QVariantList &params)
+{
+ if (action == SetFocus || action == DefaultAction) {
+ if (child || !widget()->isEnabled())
+ return false;
+ if (widget()->focusPolicy() != Qt::NoFocus)
+ widget()->setFocus();
+ else if (widget()->isWindow())
+ widget()->activateWindow();
+ else
+ return false;
+ return true;
+ } else if (action > 0) {
+ if (QAction *act = widget()->actions().value(action - 1)) {
+ act->trigger();
+ return true;
+ }
+ }
+ return QAccessibleObject::doAction(action, child, params);
+}
+
+#endif // QT_NO_ACTION
+
+/*! \reimp */
+QAccessible::Role QAccessibleWidget::role(int child) const
+{
+ if (!child)
+ return d->role;
+
+ QWidgetList childList = childWidgets(widget());
+ if (childList.count() > 0 && child <= childList.count()) {
+ QWidget *targetWidget = childList.at(child - 1);
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(targetWidget);
+ if (iface) {
+ QAccessible::Role role = iface->role(0);
+ delete iface;
+ return role;
+ }
+ }
+
+ return NoRole;
+}
+
+/*! \reimp */
+QAccessible::State QAccessibleWidget::state(int child) const
+{
+ if (child)
+ return Normal;
+
+ QAccessible::State state = Normal;
+
+ QWidget *w = widget();
+ if (w->testAttribute(Qt::WA_WState_Visible) == false)
+ state |= Invisible;
+ if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
+ state |= Focusable;
+ if (w->hasFocus())
+ state |= Focused;
+ if (!w->isEnabled())
+ state |= Unavailable;
+ if (w->isWindow()) {
+ if (w->windowFlags() & Qt::WindowSystemMenuHint)
+ state |= Movable;
+ if (w->minimumSize() != w->maximumSize())
+ state |= Sizeable;
+ }
+
+ return state;
+}
+
+// ### Qt 5: remove me - binary compatibility hack
+QAccessibleWidgetEx::QAccessibleWidgetEx(QWidget *o, Role role, const QString& name)
+ : QAccessibleObjectEx(o)
+{
+ Q_ASSERT(widget());
+ d = new QAccessibleWidgetPrivate();
+ d->role = role;
+ d->name = name;
+ d->asking = 0;
+}
+
+int QAccessibleWidgetEx::childCount() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childCount(); }
+int QAccessibleWidgetEx::indexOfChild(const QAccessibleInterface *child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::indexOfChild(child); }
+QAccessible::Relation QAccessibleWidgetEx::relationTo(int child, const QAccessibleInterface *other, int otherChild) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::relationTo(child, other, otherChild); }
+
+int QAccessibleWidgetEx::childAt(int x, int y) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childAt(x, y); }
+QRect QAccessibleWidgetEx::rect(int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::rect(child); }
+int QAccessibleWidgetEx::navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::navigate(rel, entry, target); }
+
+QString QAccessibleWidgetEx::text(Text t, int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::text(t, child); }
+QAccessible::Role QAccessibleWidgetEx::role(int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::role(child); }
+QAccessible::State QAccessibleWidgetEx::state(int child) const
+{ return (reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::state(child))
+ | HasInvokeExtension; }
+
+QString QAccessibleWidgetEx::actionText(int action, Text t, int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::actionText(action, t, child); }
+bool QAccessibleWidgetEx::doAction(int action, int child, const QVariantList &params)
+{ return reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::doAction(action, child, params); }
+
+QAccessibleWidgetEx::~QAccessibleWidgetEx()
+{ delete d; }
+QWidget *QAccessibleWidgetEx::widget() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::widget(); }
+QObject *QAccessibleWidgetEx::parentObject() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::parentObject(); }
+
+void QAccessibleWidgetEx::addControllingSignal(const QString &signal)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::addControllingSignal(signal); }
+void QAccessibleWidgetEx::setValue(const QString &value)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setValue(value); }
+void QAccessibleWidgetEx::setDescription(const QString &desc)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setDescription(desc); }
+void QAccessibleWidgetEx::setHelp(const QString &help)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setHelp(help); }
+void QAccessibleWidgetEx::setAccelerator(const QString &accel)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setAccelerator(accel); }
+
+QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVariantList & /*params*/)
+{
+ if (child)
+ return QVariant();
+
+ switch (method) {
+ case ListSupportedMethods: {
+ QSet<QAccessible::Method> set;
+ set << ListSupportedMethods << ForegroundColor << BackgroundColor;
+ return QVariant::fromValue(set);
+ }
+ case ForegroundColor:
+ return widget()->palette().color(widget()->foregroundRole());
+ case BackgroundColor:
+ return widget()->palette().color(widget()->backgroundRole());
+ default:
+ return QVariant();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY