src/gui/accessible/qaccessiblewidget.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 static 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 
       
    78 static 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 
       
   103 QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
       
   104 {
       
   105     return QString(text).remove(QLatin1Char('&'));
       
   106 }
       
   107 
       
   108 QString 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 
       
   138 class QAccessibleWidgetPrivate : public QAccessible
       
   139 {
       
   140 public:
       
   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 */
       
   180 QAccessibleWidget::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 */
       
   193 QAccessibleWidget::~QAccessibleWidget()
       
   194 {
       
   195     delete d;
       
   196 }
       
   197 
       
   198 /*!
       
   199     Returns the associated widget.
       
   200 */
       
   201 QWidget *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 */
       
   210 QObject *QAccessibleWidget::parentObject() const
       
   211 {
       
   212     QObject *parent = object()->parent();
       
   213     if (!parent)
       
   214         parent = qApp;
       
   215     return parent;
       
   216 }
       
   217 
       
   218 /*! \reimp */
       
   219 int 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 */
       
   251 QRect 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 
       
   266 QT_BEGIN_INCLUDE_NAMESPACE
       
   267 #include <private/qobject_p.h>
       
   268 QT_END_INCLUDE_NAMESPACE
       
   269 
       
   270 class QACConnectionObject : public QObject
       
   271 {
       
   272     Q_DECLARE_PRIVATE(QObject)
       
   273 public:
       
   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 */
       
   288 void 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 */
       
   304 void 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 */
       
   317 void 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 */
       
   330 void 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 */
       
   343 void QAccessibleWidget::setAccelerator(const QString &accel)
       
   344 {
       
   345     d->accelerator = accel;
       
   346 }
       
   347 
       
   348 static 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 */
       
   360 QAccessible::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 */
       
   451 int 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 */
       
   773 int QAccessibleWidget::childCount() const
       
   774 {
       
   775     QWidgetList cl = childWidgets(widget());
       
   776     return cl.size();
       
   777 }
       
   778 
       
   779 /*! \reimp */
       
   780 int 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
       
   790 extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
       
   791 
       
   792 /*! \reimp */
       
   793 QString 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 */
       
   848 int QAccessibleWidget::userActionCount(int child) const
       
   849 {
       
   850     if (child)
       
   851         return 0;
       
   852     return widget()->actions().count();
       
   853 }
       
   854 
       
   855 /*! \reimp */
       
   856 QString 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 */
       
   883 bool 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 */
       
   907 QAccessible::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 */
       
   927 QAccessible::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
       
   954 QAccessibleWidgetEx::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 
       
   964 int QAccessibleWidgetEx::childCount() const
       
   965 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childCount(); }
       
   966 int QAccessibleWidgetEx::indexOfChild(const QAccessibleInterface *child) const
       
   967 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::indexOfChild(child); }
       
   968 QAccessible::Relation QAccessibleWidgetEx::relationTo(int child, const QAccessibleInterface *other, int otherChild) const
       
   969 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::relationTo(child, other, otherChild); }
       
   970 
       
   971 int QAccessibleWidgetEx::childAt(int x, int y) const
       
   972 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childAt(x, y); }
       
   973 QRect QAccessibleWidgetEx::rect(int child) const
       
   974 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::rect(child); }
       
   975 int QAccessibleWidgetEx::navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const
       
   976 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::navigate(rel, entry, target); }
       
   977 
       
   978 QString QAccessibleWidgetEx::text(Text t, int child) const
       
   979 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::text(t, child); }
       
   980 QAccessible::Role QAccessibleWidgetEx::role(int child) const
       
   981 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::role(child); }
       
   982 QAccessible::State QAccessibleWidgetEx::state(int child) const
       
   983 { return (reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::state(child))
       
   984     | HasInvokeExtension; }
       
   985 
       
   986 QString QAccessibleWidgetEx::actionText(int action, Text t, int child) const
       
   987 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::actionText(action, t, child); }
       
   988 bool QAccessibleWidgetEx::doAction(int action, int child, const QVariantList &params)
       
   989 { return reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::doAction(action, child, params); }
       
   990 
       
   991 QAccessibleWidgetEx::~QAccessibleWidgetEx()
       
   992 { delete d; }
       
   993 QWidget *QAccessibleWidgetEx::widget() const
       
   994 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::widget(); }
       
   995 QObject *QAccessibleWidgetEx::parentObject() const
       
   996 { return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::parentObject(); }
       
   997 
       
   998 void QAccessibleWidgetEx::addControllingSignal(const QString &signal)
       
   999 { reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::addControllingSignal(signal); }
       
  1000 void QAccessibleWidgetEx::setValue(const QString &value)
       
  1001 { reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setValue(value); }
       
  1002 void QAccessibleWidgetEx::setDescription(const QString &desc)
       
  1003 { reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setDescription(desc); }
       
  1004 void QAccessibleWidgetEx::setHelp(const QString &help)
       
  1005 { reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setHelp(help); }
       
  1006 void QAccessibleWidgetEx::setAccelerator(const QString &accel)
       
  1007 { reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setAccelerator(accel); }
       
  1008 
       
  1009 QVariant 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 
       
  1029 QT_END_NAMESPACE
       
  1030 
       
  1031 #endif //QT_NO_ACCESSIBILITY