src/gui/accessible/qaccessibleobject.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 "qaccessibleobject.h"
       
    43 
       
    44 #ifndef QT_NO_ACCESSIBILITY
       
    45 
       
    46 #include "qapplication.h"
       
    47 #include "qwidget.h"
       
    48 #include "qpointer.h"
       
    49 #include "qmetaobject.h"
       
    50 #include "qvarlengtharray.h"
       
    51 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 class QAccessibleObjectPrivate
       
    55 {
       
    56 public:
       
    57     QPointer<QObject> object;
       
    58 
       
    59     QList<QByteArray> actionList() const;
       
    60 };
       
    61 
       
    62 QList<QByteArray> QAccessibleObjectPrivate::actionList() const
       
    63 {
       
    64     QList<QByteArray> actionList;
       
    65 
       
    66     if (!object)
       
    67         return actionList;
       
    68 
       
    69     const QMetaObject *mo = object->metaObject();
       
    70     Q_ASSERT(mo);
       
    71 
       
    72     QByteArray defaultAction = QMetaObject::normalizedSignature(
       
    73         mo->classInfo(mo->indexOfClassInfo("DefaultSlot")).value());
       
    74 
       
    75     for (int i = 0; i < mo->methodCount(); ++i) {
       
    76         const QMetaMethod member = mo->method(i);
       
    77         if (member.methodType() != QMetaMethod::Slot && member.access() != QMetaMethod::Public)
       
    78             continue;
       
    79 
       
    80         if (!qstrcmp(member.tag(), "QACCESSIBLE_SLOT")) {
       
    81             if (member.signature() == defaultAction)
       
    82                 actionList.prepend(defaultAction);
       
    83             else
       
    84                 actionList << member.signature();
       
    85         }
       
    86     }
       
    87 
       
    88     return actionList;
       
    89 }
       
    90 
       
    91 /*!
       
    92     \class QAccessibleObject
       
    93     \brief The QAccessibleObject class implements parts of the
       
    94     QAccessibleInterface for QObjects.
       
    95 
       
    96     \ingroup accessibility
       
    97 
       
    98     This class is mainly provided for convenience. All subclasses of
       
    99     the QAccessibleInterface that provide implementations of non-widget objects
       
   100     should use this class as their base class.
       
   101 
       
   102     \sa QAccessible, QAccessibleWidget
       
   103 */
       
   104 
       
   105 /*!
       
   106     Creates a QAccessibleObject for \a object.
       
   107 */
       
   108 QAccessibleObject::QAccessibleObject(QObject *object)
       
   109 {
       
   110     d = new QAccessibleObjectPrivate;
       
   111     d->object = object;
       
   112 }
       
   113 
       
   114 /*!
       
   115     Destroys the QAccessibleObject.
       
   116 
       
   117     This only happens when a call to release() decrements the internal
       
   118     reference counter to zero.
       
   119 */
       
   120 QAccessibleObject::~QAccessibleObject()
       
   121 {
       
   122     delete d;
       
   123 }
       
   124 
       
   125 /*!
       
   126     \reimp
       
   127 */
       
   128 QObject *QAccessibleObject::object() const
       
   129 {
       
   130 #ifndef QT_NO_DEBUG
       
   131     if (!d->object)
       
   132         qWarning("QAccessibleInterface is invalid. Crash pending...");
       
   133 #endif
       
   134     return d->object;
       
   135 }
       
   136 
       
   137 /*!
       
   138     \reimp
       
   139 */
       
   140 bool QAccessibleObject::isValid() const
       
   141 {
       
   142     return !d->object.isNull();
       
   143 }
       
   144 
       
   145 /*! \reimp */
       
   146 QRect QAccessibleObject::rect(int) const
       
   147 {
       
   148     return QRect();
       
   149 }
       
   150 
       
   151 /*! \reimp */
       
   152 void QAccessibleObject::setText(Text, int, const QString &)
       
   153 {
       
   154 }
       
   155 
       
   156 /*! \reimp */
       
   157 int QAccessibleObject::userActionCount(int) const
       
   158 {
       
   159     return 0;
       
   160 }
       
   161 
       
   162 /*! \reimp */
       
   163 bool QAccessibleObject::doAction(int, int, const QVariantList &)
       
   164 {
       
   165     return false;
       
   166 }
       
   167 
       
   168 static const char * const action_text[][5] =
       
   169 {
       
   170     // Name, Description, Value, Help, Accelerator
       
   171     { "Press", "", "", "", "Space" },
       
   172     { "SetFocus", "Passes focus to this widget", "", "", "" },
       
   173     { "Increase", "", "", "", "" },
       
   174     { "Decrease", "", "", "", "" },
       
   175     { "Accept", "", "", "", "" },
       
   176     { "Cancel", "", "", "", "" },
       
   177     { "Select", "", "", "", "" },
       
   178     { "ClearSelection", "", "", "", "" },
       
   179     { "RemoveSelection", "", "", "", "" },
       
   180     { "ExtendSelection", "", "", "", "" },
       
   181     { "AddToSelection", "", "", "", "" }
       
   182 };
       
   183 
       
   184 /*! \reimp */
       
   185 QString QAccessibleObject::actionText(int action, Text t, int child) const
       
   186 {
       
   187     if (child || action > FirstStandardAction || action < LastStandardAction || t > Accelerator)
       
   188         return QString();
       
   189 
       
   190     return QString::fromLatin1(action_text[-(action - FirstStandardAction)][t]);
       
   191 }
       
   192 
       
   193 
       
   194 /*!
       
   195     \class QAccessibleApplication
       
   196     \brief The QAccessibleApplication class implements the QAccessibleInterface for QApplication.
       
   197 
       
   198     \internal
       
   199 
       
   200     \ingroup accessibility
       
   201 */
       
   202 
       
   203 /*!
       
   204     Creates a QAccessibleApplication for the QApplication object referenced by qApp.
       
   205 */
       
   206 QAccessibleApplication::QAccessibleApplication()
       
   207 : QAccessibleObject(qApp)
       
   208 {
       
   209 }
       
   210 
       
   211 // all toplevel widgets except popups and the desktop
       
   212 static QWidgetList topLevelWidgets()
       
   213 {
       
   214     QWidgetList list;
       
   215     const QWidgetList tlw(QApplication::topLevelWidgets());
       
   216     for (int i = 0; i < tlw.count(); ++i) {
       
   217         QWidget *w = tlw.at(i);
       
   218         if (!(w->windowType() == Qt::Popup) && !(w->windowType() == Qt::Desktop))
       
   219             list.append(w);
       
   220     }
       
   221 
       
   222     return list;
       
   223 }
       
   224 
       
   225 /*! \reimp */
       
   226 int QAccessibleApplication::childCount() const
       
   227 {
       
   228     return topLevelWidgets().count();
       
   229 }
       
   230 
       
   231 /*! \reimp */
       
   232 int QAccessibleApplication::indexOfChild(const QAccessibleInterface *child) const
       
   233 {
       
   234     if (!child->object()->isWidgetType())
       
   235         return -1;
       
   236 
       
   237     const QWidgetList tlw(topLevelWidgets());
       
   238     int index = tlw.indexOf(static_cast<QWidget*>(child->object()));
       
   239     if (index != -1)
       
   240         ++index;
       
   241     return index;
       
   242 }
       
   243 
       
   244 /*! \reimp */
       
   245 int QAccessibleApplication::childAt(int x, int y) const
       
   246 {
       
   247     const QWidgetList tlw(topLevelWidgets());
       
   248     for (int i = 0; i < tlw.count(); ++i) {
       
   249         QWidget *w = tlw.at(i);
       
   250         if (w->frameGeometry().contains(x,y))
       
   251             return i+1;
       
   252     }
       
   253     return -1;
       
   254 }
       
   255 
       
   256 /*! \reimp */
       
   257 QAccessible::Relation QAccessibleApplication::relationTo(int child, const
       
   258         QAccessibleInterface *other, int otherChild) const
       
   259 {
       
   260     QObject *o = other ? other->object() : 0;
       
   261     if (!o)
       
   262         return Unrelated;
       
   263 
       
   264     if(o == object()) {
       
   265         if (child && !otherChild)
       
   266             return Child;
       
   267         if (!child && otherChild)
       
   268             return Ancestor;
       
   269         if (!child && !otherChild)
       
   270             return Self;
       
   271     }
       
   272 
       
   273     QWidgetList tlw(topLevelWidgets());
       
   274     if (tlw.contains(qobject_cast<QWidget*>(o)))
       
   275         return Ancestor;
       
   276 
       
   277     for (int i = 0; i < tlw.count(); ++i) {
       
   278         QWidget *w = tlw.at(i);
       
   279         QObjectList cl = qFindChildren<QObject *>(w, QString());
       
   280         if (cl.contains(o))
       
   281             return Ancestor;
       
   282     }
       
   283 
       
   284     return Unrelated;
       
   285 }
       
   286 
       
   287 /*! \reimp */
       
   288 int QAccessibleApplication::navigate(RelationFlag relation, int entry,
       
   289                                      QAccessibleInterface **target) const
       
   290 {
       
   291     if (!target)
       
   292         return -1;
       
   293 
       
   294     *target = 0;
       
   295     QObject *targetObject = 0;
       
   296 
       
   297     switch (relation) {
       
   298     case Self:
       
   299         targetObject = object();
       
   300         break;
       
   301     case Child:
       
   302         if (entry > 0 && entry <= childCount()) {
       
   303             const QWidgetList tlw(topLevelWidgets());
       
   304             if (tlw.count() >= entry)
       
   305                 targetObject = tlw.at(entry-1);
       
   306         } else {
       
   307             return -1;
       
   308         }
       
   309         break;
       
   310     case FocusChild:
       
   311         targetObject = QApplication::activeWindow();
       
   312         break;
       
   313     default:
       
   314         break;
       
   315     }
       
   316     *target = QAccessible::queryAccessibleInterface(targetObject);
       
   317     return *target ? 0 : -1;
       
   318 }
       
   319 
       
   320 /*! \reimp */
       
   321 QString QAccessibleApplication::text(Text t, int) const
       
   322 {
       
   323     switch (t) {
       
   324     case Name:
       
   325         if (QApplication::activeWindow())
       
   326             return QApplication::activeWindow()->windowTitle();
       
   327         break;
       
   328     case Description:
       
   329         return QApplication::applicationFilePath();
       
   330     default:
       
   331         break;
       
   332     }
       
   333     return QString();
       
   334 }
       
   335 
       
   336 /*! \reimp */
       
   337 QAccessible::Role QAccessibleApplication::role(int) const
       
   338 {
       
   339     return Application;
       
   340 }
       
   341 
       
   342 /*! \reimp */
       
   343 QAccessible::State QAccessibleApplication::state(int) const
       
   344 {
       
   345     return QApplication::activeWindow() ? Focused : Normal;
       
   346 }
       
   347 
       
   348 /*! \reimp */
       
   349 int QAccessibleApplication::userActionCount(int) const
       
   350 {
       
   351     return 1;
       
   352 }
       
   353 
       
   354 /*! \reimp */
       
   355 bool QAccessibleApplication::doAction(int action, int child, const QVariantList &param)
       
   356 {
       
   357     if (action == 0 || action == 1) {
       
   358         QWidget *w = 0;
       
   359         w = QApplication::activeWindow();
       
   360         if (!w)
       
   361             w = topLevelWidgets().at(0);
       
   362         if (!w)
       
   363             return false;
       
   364         w->activateWindow();
       
   365         return true;
       
   366     }
       
   367     return QAccessibleObject::doAction(action, child, param);
       
   368 }
       
   369 
       
   370 /*! \reimp */
       
   371 QString QAccessibleApplication::actionText(int action, Text text, int child) const
       
   372 {
       
   373     QString str;
       
   374     if ((action == 0 || action == 1) && !child) switch (text) {
       
   375     case Name:
       
   376         return QApplication::tr("Activate");
       
   377     case Description:
       
   378         return QApplication::tr("Activates the program's main window");
       
   379     default:
       
   380         break;
       
   381     }
       
   382     return QAccessibleObject::actionText(action, text, child);
       
   383 }
       
   384 
       
   385 // ### Qt 5: remove me - binary compatibility hack
       
   386 QAccessibleObjectEx::QAccessibleObjectEx(QObject *object)
       
   387 {
       
   388     d = new QAccessibleObjectPrivate;
       
   389     d->object = object;
       
   390 }
       
   391 bool QAccessibleObjectEx::isValid() const
       
   392 { return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::isValid(); }
       
   393 QObject *QAccessibleObjectEx::object() const
       
   394 { return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::object(); }
       
   395 QRect QAccessibleObjectEx::rect(int child) const
       
   396 { return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::rect(child); }
       
   397 void QAccessibleObjectEx::setText(Text t, int child, const QString &text)
       
   398 { reinterpret_cast<QAccessibleObject *>(this)->QAccessibleObject::setText(t, child, text); }
       
   399 int QAccessibleObjectEx::userActionCount(int child) const
       
   400 { return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::userActionCount(child); }
       
   401 bool QAccessibleObjectEx::doAction(int action, int child, const QVariantList &params)
       
   402 { return reinterpret_cast<QAccessibleObject *>(this)->QAccessibleObject::doAction(action, child, params); }
       
   403 QString QAccessibleObjectEx::actionText(int action, Text t, int child) const
       
   404 { return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::actionText(action, t, child); }
       
   405 QAccessibleObjectEx::~QAccessibleObjectEx()
       
   406 { delete d; }
       
   407 
       
   408 QT_END_NAMESPACE
       
   409 
       
   410 #endif //QT_NO_ACCESSIBILITY