src/plugins/accessible/widgets/qaccessiblewidgets.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 plugins 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 "qaccessiblewidgets.h"
       
    43 #include "qabstracttextdocumentlayout.h"
       
    44 #include "qapplication.h"
       
    45 #include "qclipboard.h"
       
    46 #include "qtextedit.h"
       
    47 #include "private/qtextedit_p.h"
       
    48 #include "qtextdocument.h"
       
    49 #include "qtextobject.h"
       
    50 #include "qscrollbar.h"
       
    51 #include "qdebug.h"
       
    52 #include <QApplication>
       
    53 #include <QStackedWidget>
       
    54 #include <QToolBox>
       
    55 #include <QMdiArea>
       
    56 #include <QMdiSubWindow>
       
    57 #include <QWorkspace>
       
    58 #include <QDialogButtonBox>
       
    59 #include <limits.h>
       
    60 #include <QRubberBand>
       
    61 #include <QTextBrowser>
       
    62 #include <QCalendarWidget>
       
    63 #include <QAbstractItemView>
       
    64 #include <QDockWidget>
       
    65 #include <QMainWindow>
       
    66 #include <QAbstractButton>
       
    67 #include <private/qdockwidget_p.h>
       
    68 #include <QtGui/QFocusFrame>
       
    69 
       
    70 #ifndef QT_NO_ACCESSIBILITY
       
    71 
       
    72 QT_BEGIN_NAMESPACE
       
    73 
       
    74 using namespace QAccessible2;
       
    75 
       
    76 QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel)
       
    77 {
       
    78     if (widget == 0)
       
    79         return QList<QWidget*>();
       
    80     QList<QObject*> list = widget->children();
       
    81     QList<QWidget*> widgets;
       
    82     for (int i = 0; i < list.size(); ++i) {
       
    83         QWidget *w = qobject_cast<QWidget *>(list.at(i));
       
    84         if (!w)
       
    85             continue;
       
    86         QString objectName = w->objectName();
       
    87         if ((includeTopLevel || !w->isWindow()) 
       
    88               && !qobject_cast<QFocusFrame*>(w)
       
    89               && !qobject_cast<QMenu*>(w)
       
    90               && objectName != QLatin1String("qt_rubberband")
       
    91               && objectName != QLatin1String("qt_qmainwindow_extended_splitter")) {
       
    92             widgets.append(w);
       
    93         }
       
    94     }
       
    95     return widgets;
       
    96 }
       
    97 
       
    98 static inline int distance(QWidget *source, QWidget *target,
       
    99                            QAccessible::RelationFlag relation)
       
   100 {
       
   101     if (!source || !target)
       
   102         return -1;
       
   103 
       
   104     int returnValue = -1;
       
   105     switch (relation) {
       
   106     case QAccessible::Up:
       
   107         if (target->y() <= source->y())
       
   108             returnValue = source->y() - target->y();
       
   109         break;
       
   110     case QAccessible::Down:
       
   111         if (target->y() >= source->y() + source->height())
       
   112             returnValue = target->y() - (source->y() + source->height());
       
   113         break;
       
   114     case QAccessible::Right:
       
   115         if (target->x() >= source->x() + source->width())
       
   116             returnValue = target->x() - (source->x() + source->width());
       
   117         break;
       
   118     case QAccessible::Left:
       
   119         if (target->x() <= source->x())
       
   120             returnValue = source->x() - target->x();
       
   121         break;
       
   122     default:
       
   123         break;
       
   124     }
       
   125     return returnValue;
       
   126 }
       
   127 
       
   128 static inline QWidget *mdiAreaNavigate(QWidget *area,
       
   129                                        QAccessible::RelationFlag relation, int entry)
       
   130 {
       
   131 #if defined(QT_NO_MDIAREA) && defined(QT_NO_WORKSPACE)
       
   132     Q_UNUSED(area);
       
   133 #endif
       
   134 #ifndef QT_NO_MDIAREA
       
   135     const QMdiArea *mdiArea = qobject_cast<QMdiArea *>(area);
       
   136 #endif
       
   137 #ifndef QT_NO_WORKSPACE
       
   138     const QWorkspace *workspace = qobject_cast<QWorkspace *>(area);
       
   139 #endif
       
   140     if (true
       
   141 #ifndef QT_NO_MDIAREA
       
   142         && !mdiArea
       
   143 #endif
       
   144 #ifndef QT_NO_WORKSPACE
       
   145     && !workspace
       
   146 #endif
       
   147     )
       
   148         return 0;
       
   149 
       
   150     QWidgetList windows;
       
   151 #ifndef QT_NO_MDIAREA
       
   152     if (mdiArea) {
       
   153         foreach (QMdiSubWindow *window, mdiArea->subWindowList())
       
   154             windows.append(window);
       
   155     } else
       
   156 #endif
       
   157     {
       
   158 #ifndef QT_NO_WORKSPACE
       
   159         foreach (QWidget *window, workspace->windowList())
       
   160             windows.append(window->parentWidget());
       
   161 #endif
       
   162     }
       
   163 
       
   164     if (windows.isEmpty() || entry < 1 || entry > windows.count())
       
   165         return 0;
       
   166 
       
   167     QWidget *source = windows.at(entry - 1);
       
   168     QMap<int, QWidget *> candidates;
       
   169     foreach (QWidget *window, windows) {
       
   170         if (source == window)
       
   171             continue;
       
   172         int candidateDistance = distance(source, window, relation);
       
   173         if (candidateDistance >= 0)
       
   174             candidates.insert(candidateDistance, window);
       
   175     }
       
   176 
       
   177     int minimumDistance = INT_MAX;
       
   178     QWidget *target = 0;
       
   179     foreach (QWidget *candidate, candidates.values()) {
       
   180         switch (relation) {
       
   181         case QAccessible::Up:
       
   182         case QAccessible::Down:
       
   183             if (qAbs(candidate->x() - source->x()) < minimumDistance) {
       
   184                 target = candidate;
       
   185                 minimumDistance = qAbs(candidate->x() - source->x());
       
   186             }
       
   187             break;
       
   188         case QAccessible::Left:
       
   189         case QAccessible::Right:
       
   190             if (qAbs(candidate->y() - source->y()) < minimumDistance) {
       
   191                 target = candidate;
       
   192                 minimumDistance = qAbs(candidate->y() - source->y());
       
   193             }
       
   194             break;
       
   195         default:
       
   196             break;
       
   197         }
       
   198         if (minimumDistance == 0)
       
   199             break;
       
   200     }
       
   201 
       
   202 #ifndef QT_NO_WORKSPACE
       
   203     if (workspace) {
       
   204         foreach (QWidget *widget, workspace->windowList()) {
       
   205             if (widget->parentWidget() == target)
       
   206                 target = widget;
       
   207         }
       
   208     }
       
   209 #endif
       
   210     return target;
       
   211 }
       
   212 
       
   213 #ifndef QT_NO_TEXTEDIT
       
   214 
       
   215 /*!
       
   216   \class QAccessibleTextEdit
       
   217   \brief The QAccessibleTextEdit class implements the QAccessibleInterface for richtext editors.
       
   218   \internal
       
   219 */
       
   220 
       
   221 static QTextBlock qTextBlockAt(const QTextDocument *doc, int pos)
       
   222 {
       
   223     Q_ASSERT(pos >= 0);
       
   224 
       
   225     QTextBlock block = doc->begin();
       
   226     int i = 0;
       
   227     while (block.isValid() && i < pos) {
       
   228         block = block.next();
       
   229         ++i;
       
   230     }
       
   231     return block;
       
   232 }
       
   233 
       
   234 static int qTextBlockPosition(QTextBlock block)
       
   235 {
       
   236     int child = 0;
       
   237     while (block.isValid()) {
       
   238         block = block.previous();
       
   239         ++child;
       
   240     }
       
   241 
       
   242     return child;
       
   243 }
       
   244 
       
   245 /*!
       
   246   \fn QAccessibleTextEdit::QAccessibleTextEdit(QWidget* widget)
       
   247 
       
   248   Constructs a QAccessibleTextEdit object for a \a widget.
       
   249 */
       
   250 QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
       
   251 : QAccessibleWidgetEx(o, EditableText)
       
   252 {
       
   253     Q_ASSERT(widget()->inherits("QTextEdit"));
       
   254     childOffset = QAccessibleWidgetEx::childCount();
       
   255 }
       
   256 
       
   257 /*! Returns the text edit. */
       
   258 QTextEdit *QAccessibleTextEdit::textEdit() const
       
   259 {
       
   260     return static_cast<QTextEdit *>(widget());
       
   261 }
       
   262 
       
   263 QRect QAccessibleTextEdit::rect(int child) const
       
   264 {
       
   265     if (child <= childOffset)
       
   266         return QAccessibleWidgetEx::rect(child);
       
   267 
       
   268      QTextEdit *edit = textEdit();
       
   269      QTextBlock block = qTextBlockAt(edit->document(), child - childOffset - 1);
       
   270      if (!block.isValid())
       
   271          return QRect();
       
   272 
       
   273      QRect rect = edit->document()->documentLayout()->blockBoundingRect(block).toRect();
       
   274      rect.translate(-edit->horizontalScrollBar()->value(), -edit->verticalScrollBar()->value());
       
   275 
       
   276      rect = edit->viewport()->rect().intersect(rect);
       
   277      if (rect.isEmpty())
       
   278          return QRect();
       
   279 
       
   280      return rect.translated(edit->viewport()->mapToGlobal(QPoint(0, 0)));
       
   281 }
       
   282 
       
   283 int QAccessibleTextEdit::childAt(int x, int y) const
       
   284 {
       
   285     QTextEdit *edit = textEdit();
       
   286     if (!edit->isVisible())
       
   287         return -1;
       
   288 
       
   289     QPoint point = edit->viewport()->mapFromGlobal(QPoint(x, y));
       
   290     QTextBlock block = edit->cursorForPosition(point).block();
       
   291     if (block.isValid())
       
   292         return qTextBlockPosition(block) + childOffset;
       
   293 
       
   294     return QAccessibleWidgetEx::childAt(x, y);
       
   295 }
       
   296 
       
   297 /*! \reimp */
       
   298 QString QAccessibleTextEdit::text(Text t, int child) const
       
   299 {
       
   300     if (t == Value) {
       
   301         if (child > childOffset)
       
   302             return qTextBlockAt(textEdit()->document(), child - childOffset - 1).text();
       
   303         if (!child)
       
   304             return textEdit()->toPlainText();
       
   305     }
       
   306 
       
   307     return QAccessibleWidgetEx::text(t, child);
       
   308 }
       
   309 
       
   310 /*! \reimp */
       
   311 void QAccessibleTextEdit::setText(Text t, int child, const QString &text)
       
   312 {
       
   313     if (t != Value || (child > 0 && child <= childOffset)) {
       
   314         QAccessibleWidgetEx::setText(t, child, text);
       
   315         return;
       
   316     }
       
   317     if (textEdit()->isReadOnly())
       
   318         return;
       
   319 
       
   320     if (!child) {
       
   321         textEdit()->setText(text);
       
   322         return;
       
   323     }
       
   324     QTextBlock block = qTextBlockAt(textEdit()->document(), child - childOffset - 1);
       
   325     if (!block.isValid())
       
   326         return;
       
   327 
       
   328     QTextCursor cursor(block);
       
   329     cursor.select(QTextCursor::BlockUnderCursor);
       
   330     cursor.insertText(text);
       
   331 }
       
   332 
       
   333 /*! \reimp */
       
   334 QAccessible::Role QAccessibleTextEdit::role(int child) const
       
   335 {
       
   336     if (child > childOffset)
       
   337         return EditableText;
       
   338     return QAccessibleWidgetEx::role(child);
       
   339 }
       
   340 
       
   341 QVariant QAccessibleTextEdit::invokeMethodEx(QAccessible::Method method, int child,
       
   342                                                      const QVariantList &params)
       
   343 {
       
   344     if (child)
       
   345         return QVariant();
       
   346 
       
   347     switch (method) {
       
   348     case ListSupportedMethods: {
       
   349         QSet<QAccessible::Method> set;
       
   350         set << ListSupportedMethods << SetCursorPosition << GetCursorPosition;
       
   351         return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >(
       
   352                     QAccessibleWidgetEx::invokeMethodEx(method, child, params)));
       
   353     }
       
   354     case SetCursorPosition:
       
   355         setCursorPosition(params.value(0).toInt());
       
   356         return true;
       
   357     case GetCursorPosition:
       
   358         return textEdit()->textCursor().position();
       
   359     default:
       
   360         return QAccessibleWidgetEx::invokeMethodEx(method, child, params);
       
   361     }
       
   362 }
       
   363 
       
   364 int QAccessibleTextEdit::childCount() const
       
   365 {
       
   366     return childOffset + textEdit()->document()->blockCount();
       
   367 }
       
   368 #endif // QT_NO_TEXTEDIT
       
   369 
       
   370 #ifndef QT_NO_STACKEDWIDGET
       
   371 // ======================= QAccessibleStackedWidget ======================
       
   372 QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
       
   373     : QAccessibleWidgetEx(widget, LayeredPane)
       
   374 {
       
   375     Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
       
   376 }
       
   377 
       
   378 QVariant QAccessibleStackedWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   379 {
       
   380     return QVariant();
       
   381 }
       
   382 
       
   383 
       
   384 int QAccessibleStackedWidget::childAt(int x, int y) const
       
   385 {
       
   386     if (!stackedWidget()->isVisible())
       
   387         return -1;
       
   388     QWidget *currentWidget = stackedWidget()->currentWidget();
       
   389     if (!currentWidget)
       
   390         return -1;
       
   391     QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
       
   392     if (currentWidget->rect().contains(position))
       
   393         return 1;
       
   394     return -1;
       
   395 }
       
   396 
       
   397 int QAccessibleStackedWidget::childCount() const
       
   398 {
       
   399     return stackedWidget()->count();
       
   400 }
       
   401 
       
   402 int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
       
   403 {
       
   404     if (!child || (stackedWidget()->currentWidget() != child->object()))
       
   405         return -1;
       
   406     return 1;
       
   407 }
       
   408 
       
   409 int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   410 {
       
   411     *target = 0;
       
   412 
       
   413     QObject *targetObject = 0;
       
   414     switch (relation) {
       
   415     case Child:
       
   416         if (entry != 1)
       
   417             return -1;
       
   418         targetObject = stackedWidget()->currentWidget();
       
   419         break;
       
   420     default:
       
   421         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   422     }
       
   423     *target = QAccessible::queryAccessibleInterface(targetObject);
       
   424     return *target ? 0 : -1;
       
   425 }
       
   426 
       
   427 QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
       
   428 {
       
   429     return static_cast<QStackedWidget *>(object());
       
   430 }
       
   431 #endif // QT_NO_STACKEDWIDGET
       
   432 
       
   433 #ifndef QT_NO_TOOLBOX
       
   434 // ======================= QAccessibleToolBox ======================
       
   435 QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
       
   436     : QAccessibleWidgetEx(widget, LayeredPane)
       
   437 {
       
   438     Q_ASSERT(qobject_cast<QToolBox *>(widget));
       
   439 }
       
   440 
       
   441 QString QAccessibleToolBox::text(Text textType, int child) const
       
   442 {
       
   443     if (textType != Value || child <= 0 || child > toolBox()->count())
       
   444         return QAccessibleWidgetEx::text(textType, child);
       
   445     return toolBox()->itemText(child - 1);
       
   446 }
       
   447 
       
   448 void QAccessibleToolBox::setText(Text textType, int child, const QString &text)
       
   449 {
       
   450     if (textType != Value || child <= 0 || child > toolBox()->count()) {
       
   451         QAccessibleWidgetEx::setText(textType, child, text);
       
   452         return;
       
   453     }
       
   454     toolBox()->setItemText(child - 1, text);
       
   455 }
       
   456 
       
   457 QAccessible::State QAccessibleToolBox::state(int child) const
       
   458 {
       
   459     QWidget *childWidget = toolBox()->widget(child - 1);
       
   460     if (!childWidget)
       
   461         return QAccessibleWidgetEx::state(child);
       
   462     QAccessible::State childState = QAccessible::Normal;
       
   463     if (toolBox()->currentWidget() == childWidget)
       
   464         childState |= QAccessible::Expanded;
       
   465     else
       
   466         childState |= QAccessible::Collapsed;
       
   467     return childState;
       
   468 }
       
   469 
       
   470 QVariant QAccessibleToolBox::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   471 {
       
   472     return QVariant();
       
   473 }
       
   474 
       
   475 int QAccessibleToolBox::childCount() const
       
   476 {
       
   477     return toolBox()->count();
       
   478 }
       
   479 
       
   480 int QAccessibleToolBox::indexOfChild(const QAccessibleInterface *child) const
       
   481 {
       
   482     if (!child)
       
   483         return -1;
       
   484     QWidget *childWidget = qobject_cast<QWidget *>(child->object());
       
   485     if (!childWidget)
       
   486         return -1;
       
   487     int index = toolBox()->indexOf(childWidget);
       
   488     if (index != -1)
       
   489         ++index;
       
   490     return index;
       
   491 }
       
   492 
       
   493 int QAccessibleToolBox::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   494 {
       
   495     *target = 0;
       
   496     if (entry <= 0 || entry > toolBox()->count())
       
   497         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   498     int index = -1;
       
   499     if (relation == QAccessible::Up)
       
   500         index = entry - 2;
       
   501     else if (relation == QAccessible::Down)
       
   502         index = entry;
       
   503     *target = QAccessible::queryAccessibleInterface(toolBox()->widget(index));
       
   504     return *target ? 0: -1;
       
   505 }
       
   506 
       
   507 QToolBox * QAccessibleToolBox::toolBox() const
       
   508 {
       
   509     return static_cast<QToolBox *>(object());
       
   510 }
       
   511 #endif // QT_NO_TOOLBOX
       
   512 
       
   513 // ======================= QAccessibleMdiArea ======================
       
   514 #ifndef QT_NO_MDIAREA
       
   515 QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
       
   516     : QAccessibleWidgetEx(widget, LayeredPane)
       
   517 {
       
   518     Q_ASSERT(qobject_cast<QMdiArea *>(widget));
       
   519 }
       
   520 
       
   521 QAccessible::State QAccessibleMdiArea::state(int child) const
       
   522 {
       
   523     if (child < 0)
       
   524         return QAccessibleWidgetEx::state(child);
       
   525     if (child == 0)
       
   526         return QAccessible::Normal;
       
   527     QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
       
   528     if (subWindows.isEmpty() || child > subWindows.count())
       
   529         return QAccessibleWidgetEx::state(child);
       
   530     if (subWindows.at(child - 1) == mdiArea()->activeSubWindow())
       
   531         return QAccessible::Focused;
       
   532     return QAccessible::Normal;
       
   533 }
       
   534 
       
   535 QVariant QAccessibleMdiArea::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   536 {
       
   537     return QVariant();
       
   538 }
       
   539 
       
   540 int QAccessibleMdiArea::childCount() const
       
   541 {
       
   542     return mdiArea()->subWindowList().count();
       
   543 }
       
   544 
       
   545 int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
       
   546 {
       
   547     if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
       
   548         return -1;
       
   549     if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
       
   550         int index = mdiArea()->subWindowList().indexOf(window);
       
   551         if (index != -1)
       
   552             return ++index;
       
   553     }
       
   554     return -1;
       
   555 }
       
   556 
       
   557 int QAccessibleMdiArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   558 {
       
   559     *target = 0;
       
   560     QWidget *targetObject = 0;
       
   561     QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
       
   562     switch (relation) {
       
   563     case Child:
       
   564         if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
       
   565             return -1;
       
   566         targetObject = subWindows.at(entry - 1);
       
   567         break;
       
   568     case Up:
       
   569     case Down:
       
   570     case Left:
       
   571     case Right:
       
   572         targetObject = mdiAreaNavigate(mdiArea(), relation, entry);
       
   573         break;
       
   574     default:
       
   575         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   576     }
       
   577     *target = QAccessible::queryAccessibleInterface(targetObject);
       
   578     return *target ? 0: -1;
       
   579 }
       
   580 
       
   581 QMdiArea *QAccessibleMdiArea::mdiArea() const
       
   582 {
       
   583     return static_cast<QMdiArea *>(object());
       
   584 }
       
   585 
       
   586 // ======================= QAccessibleMdiSubWindow ======================
       
   587 QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
       
   588     : QAccessibleWidgetEx(widget, QAccessible::Window)
       
   589 {
       
   590     Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
       
   591 }
       
   592 
       
   593 QString QAccessibleMdiSubWindow::text(Text textType, int child) const
       
   594 {
       
   595     if (textType == QAccessible::Name && (child == 0 || child == 1)) {
       
   596         QString title = mdiSubWindow()->windowTitle();
       
   597         title.replace(QLatin1String("[*]"), QLatin1String(""));
       
   598         return title;
       
   599     }
       
   600     return QAccessibleWidgetEx::text(textType, child);
       
   601 }
       
   602 
       
   603 void QAccessibleMdiSubWindow::setText(Text textType, int child, const QString &text)
       
   604 {
       
   605     if (textType == QAccessible::Name && (child == 0 || child == 1))
       
   606         mdiSubWindow()->setWindowTitle(text);
       
   607     else
       
   608         QAccessibleWidgetEx::setText(textType, child, text);
       
   609 }
       
   610 
       
   611 QAccessible::State QAccessibleMdiSubWindow::state(int child) const
       
   612 {
       
   613     if (child != 0 || !mdiSubWindow()->parent())
       
   614         return QAccessibleWidgetEx::state(child);
       
   615     QAccessible::State state = QAccessible::Normal | QAccessible::Focusable;
       
   616     if (!mdiSubWindow()->isMaximized())
       
   617         state |= (QAccessible::Movable | QAccessible::Sizeable);
       
   618     if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
       
   619             || QApplication::focusWidget() == mdiSubWindow())
       
   620         state |= QAccessible::Focused;
       
   621     if (!mdiSubWindow()->isVisible())
       
   622         state |= QAccessible::Invisible;
       
   623     if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
       
   624         state |= QAccessible::Offscreen;
       
   625     if (!mdiSubWindow()->isEnabled())
       
   626         state |= QAccessible::Unavailable;
       
   627     return state;
       
   628 }
       
   629 
       
   630 QVariant QAccessibleMdiSubWindow::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   631 {
       
   632     return QVariant();
       
   633 }
       
   634 
       
   635 int QAccessibleMdiSubWindow::childCount() const
       
   636 {
       
   637     if (mdiSubWindow()->widget())
       
   638         return 1;
       
   639     return 0;
       
   640 }
       
   641 
       
   642 int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
       
   643 {
       
   644     if (child && child->object() && child->object() == mdiSubWindow()->widget())
       
   645         return 1;
       
   646     return -1;
       
   647 }
       
   648 
       
   649 int QAccessibleMdiSubWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   650 {
       
   651     *target = 0;
       
   652 
       
   653     if (!mdiSubWindow()->parent())
       
   654         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   655 
       
   656     QWidget *targetObject = 0;
       
   657     QMdiSubWindow *source = mdiSubWindow();
       
   658     switch (relation) {
       
   659     case Child:
       
   660         if (entry != 1 || !source->widget())
       
   661             return -1;
       
   662         targetObject = source->widget();
       
   663         break;
       
   664     case Up:
       
   665     case Down:
       
   666     case Left:
       
   667     case Right: {
       
   668         if (entry != 0)
       
   669             break;
       
   670         QWidget *parent = source->parentWidget();
       
   671         while (parent && !parent->inherits("QMdiArea"))
       
   672             parent = parent->parentWidget();
       
   673         QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parent);
       
   674         if (!mdiArea)
       
   675             break;
       
   676         int index = mdiArea->subWindowList().indexOf(source);
       
   677         if (index == -1)
       
   678             break;
       
   679         if (QWidget *dest = mdiAreaNavigate(mdiArea, relation, index + 1)) {
       
   680             *target = QAccessible::queryAccessibleInterface(dest);
       
   681             return *target ? 0 : -1;
       
   682         }
       
   683         break;
       
   684     }
       
   685     default:
       
   686         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   687     }
       
   688     *target = QAccessible::queryAccessibleInterface(targetObject);
       
   689     return *target ? 0: -1;
       
   690 }
       
   691 
       
   692 QRect QAccessibleMdiSubWindow::rect(int child) const
       
   693 {
       
   694     if (mdiSubWindow()->isHidden())
       
   695         return QRect();
       
   696     if (!mdiSubWindow()->parent())
       
   697         return QAccessibleWidgetEx::rect(child);
       
   698     const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
       
   699     if (child == 0)
       
   700         return QRect(pos, mdiSubWindow()->size());
       
   701     if (child == 1 && mdiSubWindow()->widget()) {
       
   702         if (mdiSubWindow()->widget()->isHidden())
       
   703             return QRect();
       
   704         const QRect contentsRect = mdiSubWindow()->contentsRect();
       
   705         return QRect(pos.x() + contentsRect.x(), pos.y() + contentsRect.y(),
       
   706                      contentsRect.width(), contentsRect.height());
       
   707     }
       
   708     return QRect();
       
   709 }
       
   710 
       
   711 int QAccessibleMdiSubWindow::childAt(int x, int y) const
       
   712 {
       
   713     if (!mdiSubWindow()->isVisible())
       
   714         return -1;
       
   715     if (!mdiSubWindow()->parent())
       
   716         return QAccessibleWidgetEx::childAt(x, y);
       
   717     const QRect globalGeometry = rect(0);
       
   718     if (!globalGeometry.isValid())
       
   719         return -1;
       
   720     const QRect globalChildGeometry = rect(1);
       
   721     if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
       
   722         return 1;
       
   723     if (globalGeometry.contains(QPoint(x, y)))
       
   724         return 0;
       
   725     return -1;
       
   726 }
       
   727 
       
   728 QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
       
   729 {
       
   730     return static_cast<QMdiSubWindow *>(object());
       
   731 }
       
   732 #endif // QT_NO_MDIAREA
       
   733 
       
   734 // ======================= QAccessibleWorkspace ======================
       
   735 #ifndef QT_NO_WORKSPACE
       
   736 QAccessibleWorkspace::QAccessibleWorkspace(QWidget *widget)
       
   737     : QAccessibleWidgetEx(widget, LayeredPane)
       
   738 {
       
   739     Q_ASSERT(qobject_cast<QWorkspace *>(widget));
       
   740 }
       
   741 
       
   742 QAccessible::State QAccessibleWorkspace::state(int child) const
       
   743 {
       
   744     if (child < 0)
       
   745         return QAccessibleWidgetEx::state(child);
       
   746     if (child == 0)
       
   747         return QAccessible::Normal;
       
   748     QWidgetList subWindows = workspace()->windowList();
       
   749     if (subWindows.isEmpty() || child > subWindows.count())
       
   750         return QAccessibleWidgetEx::state(child);
       
   751     if (subWindows.at(child - 1) == workspace()->activeWindow())
       
   752         return QAccessible::Focused;
       
   753     return QAccessible::Normal;
       
   754 }
       
   755 
       
   756 QVariant QAccessibleWorkspace::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   757 {
       
   758     return QVariant();
       
   759 }
       
   760 
       
   761 int QAccessibleWorkspace::childCount() const
       
   762 {
       
   763     return workspace()->windowList().count();
       
   764 }
       
   765 
       
   766 int QAccessibleWorkspace::indexOfChild(const QAccessibleInterface *child) const
       
   767 {
       
   768     if (!child || !child->object() || workspace()->windowList().isEmpty())
       
   769         return -1;
       
   770     if (QWidget *window = qobject_cast<QWidget *>(child->object())) {
       
   771         int index = workspace()->windowList().indexOf(window);
       
   772         if (index != -1)
       
   773             return ++index;
       
   774     }
       
   775     return -1;
       
   776 }
       
   777 
       
   778 int QAccessibleWorkspace::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   779 {
       
   780     *target = 0;
       
   781     QWidget *targetObject = 0;
       
   782     QWidgetList subWindows = workspace()->windowList();
       
   783     switch (relation) {
       
   784     case Child:
       
   785         if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
       
   786             return -1;
       
   787         targetObject = subWindows.at(entry - 1);
       
   788         break;
       
   789     case Up:
       
   790     case Down:
       
   791     case Left:
       
   792     case Right:
       
   793         targetObject = mdiAreaNavigate(workspace(), relation, entry);
       
   794         break;
       
   795     default:
       
   796         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   797     }
       
   798     *target = QAccessible::queryAccessibleInterface(targetObject);
       
   799     return *target ? 0: -1;
       
   800 }
       
   801 
       
   802 QWorkspace *QAccessibleWorkspace::workspace() const
       
   803 {
       
   804     return static_cast<QWorkspace *>(object());
       
   805 }
       
   806 #endif
       
   807 
       
   808 #ifndef QT_NO_DIALOGBUTTONBOX
       
   809 // ======================= QAccessibleDialogButtonBox ======================
       
   810 QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
       
   811     : QAccessibleWidgetEx(widget, Grouping)
       
   812 {
       
   813     Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
       
   814 }
       
   815 
       
   816 QVariant QAccessibleDialogButtonBox::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   817 {
       
   818     return QVariant();
       
   819 }
       
   820 #endif // QT_NO_DIALOGBUTTONBOX
       
   821 
       
   822 #ifndef QT_NO_TEXTBROWSER
       
   823 QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
       
   824     : QAccessibleTextEdit(widget)
       
   825 {
       
   826     Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
       
   827 }
       
   828 
       
   829 QAccessible::Role QAccessibleTextBrowser::role(int child) const
       
   830 {
       
   831     if (child != 0)
       
   832         return QAccessibleTextEdit::role(child);
       
   833     return QAccessible::StaticText;
       
   834 }
       
   835 #endif // QT_NO_TEXTBROWSER
       
   836 
       
   837 #ifndef QT_NO_CALENDARWIDGET
       
   838 // ===================== QAccessibleCalendarWidget ========================
       
   839 QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
       
   840     : QAccessibleWidgetEx(widget, Table)
       
   841 {
       
   842     Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
       
   843 }
       
   844 
       
   845 QVariant QAccessibleCalendarWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
   846 {
       
   847     return QVariant();
       
   848 }
       
   849 
       
   850 int QAccessibleCalendarWidget::childCount() const
       
   851 {
       
   852    return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
       
   853 }
       
   854 
       
   855 int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
       
   856 {
       
   857     if (!child || !child->object() || childCount() <= 0)
       
   858         return -1;
       
   859     if (qobject_cast<QAbstractItemView *>(child->object()))
       
   860         return childCount();
       
   861     return 1;
       
   862 }
       
   863 
       
   864 int QAccessibleCalendarWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
   865 {
       
   866     *target = 0;
       
   867     if (entry <= 0 || entry > childCount())
       
   868         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   869     QWidget *targetWidget = 0;
       
   870     switch (relation) {
       
   871     case Child:
       
   872         if (childCount() == 1) {
       
   873             targetWidget = calendarView();
       
   874         } else {
       
   875             if (entry == 1)
       
   876                 targetWidget = navigationBar();
       
   877             else
       
   878                 targetWidget = calendarView();
       
   879         }
       
   880         break;
       
   881     case Up:
       
   882         if (entry == 2)
       
   883             targetWidget = navigationBar();
       
   884         break;
       
   885     case Down:
       
   886         if (entry == 1 && childCount() == 2)
       
   887             targetWidget = calendarView();
       
   888         break;
       
   889     default:
       
   890         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
   891     }
       
   892     *target = queryAccessibleInterface(targetWidget);
       
   893     return *target ? 0: -1;
       
   894 }
       
   895 
       
   896 QRect QAccessibleCalendarWidget::rect(int child) const
       
   897 {
       
   898     if (!calendarWidget()->isVisible() || child > childCount())
       
   899         return QRect();
       
   900     if (child == 0)
       
   901         return QAccessibleWidgetEx::rect(child);
       
   902     QWidget *childWidget = 0;
       
   903     if (childCount() == 2)
       
   904         childWidget = child == 1 ? navigationBar() : calendarView();
       
   905     else
       
   906         childWidget = calendarView();
       
   907     return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
       
   908 }
       
   909 
       
   910 int QAccessibleCalendarWidget::childAt(int x, int y) const
       
   911 {
       
   912     const QPoint globalTargetPos = QPoint(x, y);
       
   913     if (!rect(0).contains(globalTargetPos))
       
   914         return -1;
       
   915     if (rect(1).contains(globalTargetPos))
       
   916         return 1;
       
   917     if (rect(2).contains(globalTargetPos))
       
   918         return 2;
       
   919     return 0;
       
   920 }
       
   921 
       
   922 QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
       
   923 {
       
   924     return static_cast<QCalendarWidget *>(object());
       
   925 }
       
   926 
       
   927 QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
       
   928 {
       
   929     foreach (QObject *child, calendarWidget()->children()) {
       
   930         if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
       
   931             return static_cast<QAbstractItemView *>(child);
       
   932     }
       
   933     return 0;
       
   934 }
       
   935 
       
   936 QWidget *QAccessibleCalendarWidget::navigationBar() const
       
   937 {
       
   938     foreach (QObject *child, calendarWidget()->children()) {
       
   939         if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
       
   940             return static_cast<QWidget *>(child);
       
   941     }
       
   942     return 0;
       
   943 }
       
   944 #endif // QT_NO_CALENDARWIDGET
       
   945 
       
   946 #ifndef QT_NO_DOCKWIDGET
       
   947 QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
       
   948     : QAccessibleWidgetEx(widget, Window)
       
   949 {
       
   950 
       
   951 }
       
   952 
       
   953 int QAccessibleDockWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
       
   954 {
       
   955     if (relation == Child) {
       
   956         if (entry == 1) {
       
   957             *iface = new QAccessibleTitleBar(dockWidget());
       
   958             return 0;
       
   959         } else if (entry == 2) {
       
   960             if (dockWidget()->widget())
       
   961                 *iface = QAccessible::queryAccessibleInterface(dockWidget()->widget());
       
   962             return 0;
       
   963         }
       
   964         *iface = 0;
       
   965         return -1;
       
   966     }
       
   967     return QAccessibleWidgetEx::navigate(relation, entry, iface);
       
   968 }
       
   969 
       
   970 int QAccessibleDockWidget::childAt(int x, int y) const
       
   971 {
       
   972     for (int i = childCount(); i >= 0; --i) {
       
   973         if (rect(i).contains(x,y))
       
   974             return i;
       
   975     }
       
   976     return -1;
       
   977 }
       
   978 
       
   979 int QAccessibleDockWidget::childCount() const
       
   980 {
       
   981     return dockWidget()->widget() ? 2 : 1;
       
   982 }
       
   983 
       
   984 int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
       
   985 {
       
   986     if (child) {
       
   987         if (qobject_cast<QDockWidget *>(child->object()) == dockWidget() && child->role(0) == TitleBar) {
       
   988             return 1;
       
   989         } else {
       
   990             return 2;   //###
       
   991         }
       
   992     }
       
   993     return -1;
       
   994 }
       
   995 
       
   996 QAccessible::Role QAccessibleDockWidget::role(int child) const
       
   997 {
       
   998     switch (child) {
       
   999         case 0:
       
  1000             return Window;
       
  1001         case 1:
       
  1002             return TitleBar;
       
  1003         case 2:
       
  1004             //###
       
  1005             break;
       
  1006         default:
       
  1007             break;
       
  1008     }
       
  1009     return NoRole;
       
  1010 }
       
  1011 
       
  1012 QAccessible::State QAccessibleDockWidget::state(int child) const
       
  1013 {
       
  1014     //### mark tabified widgets as invisible
       
  1015     return QAccessibleWidgetEx::state(child);
       
  1016 }
       
  1017 
       
  1018 QRect QAccessibleDockWidget::rect (int child ) const
       
  1019 {
       
  1020     QRect rect;
       
  1021     bool mapToGlobal = true;
       
  1022     if (child == 0) {
       
  1023         if (dockWidget()->isFloating()) {
       
  1024             rect = dockWidget()->frameGeometry();
       
  1025             mapToGlobal = false;
       
  1026         } else {
       
  1027             rect = dockWidget()->rect();
       
  1028         }
       
  1029     }else if (child == 1) {
       
  1030         QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
       
  1031         rect = layout->titleArea();
       
  1032     }else if (child == 2) {
       
  1033         if (dockWidget()->widget())
       
  1034             rect = dockWidget()->widget()->geometry();
       
  1035     }
       
  1036     if (rect.isNull())
       
  1037         return rect;
       
  1038 
       
  1039     if (mapToGlobal)
       
  1040         rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
       
  1041 
       
  1042     return rect;
       
  1043 }
       
  1044 
       
  1045 QVariant QAccessibleDockWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
  1046 {
       
  1047     return QVariant();
       
  1048 }
       
  1049 
       
  1050 QDockWidget *QAccessibleDockWidget::dockWidget() const
       
  1051 {
       
  1052     return static_cast<QDockWidget *>(object());
       
  1053 }
       
  1054 
       
  1055 ////
       
  1056 //      QAccessibleTitleBar
       
  1057 ////
       
  1058 QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget)
       
  1059     : m_dockWidget(widget)
       
  1060 {
       
  1061 
       
  1062 }
       
  1063 
       
  1064 int QAccessibleTitleBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
       
  1065 {
       
  1066     if (entry == 0 || relation == Self) {
       
  1067         *iface = new QAccessibleTitleBar(dockWidget());
       
  1068         return 0;
       
  1069     }
       
  1070     switch (relation) {
       
  1071     case Child:
       
  1072     case FocusChild:
       
  1073         if (entry >= 1) {
       
  1074             QDockWidgetLayout *layout = dockWidgetLayout();
       
  1075             int index = 1;
       
  1076             int role;
       
  1077             for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
       
  1078                 QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
       
  1079                 if (!w->isVisible())
       
  1080                     continue;
       
  1081                 if (index == entry)
       
  1082                     break;
       
  1083                 ++index;
       
  1084             }
       
  1085             *iface = 0;
       
  1086             return role > QDockWidgetLayout::FloatButton ? -1 : index;
       
  1087         }
       
  1088         break;
       
  1089     case Ancestor:
       
  1090         {
       
  1091         QAccessibleDockWidget *target = new QAccessibleDockWidget(dockWidget());
       
  1092         int index;
       
  1093         if (entry == 1) {
       
  1094             *iface = target;
       
  1095             return 0;
       
  1096         }
       
  1097         index = target->navigate(Ancestor, entry - 1, iface);
       
  1098         delete target;
       
  1099         return index;
       
  1100 
       
  1101         break;}
       
  1102     case Sibling:
       
  1103         return navigate(Child, entry, iface);
       
  1104         break;
       
  1105     default:
       
  1106         break;
       
  1107     }
       
  1108     *iface = 0;
       
  1109     return -1;
       
  1110 }
       
  1111 
       
  1112 QAccessible::Relation QAccessibleTitleBar::relationTo(int /*child*/,  const QAccessibleInterface * /*other*/, int /*otherChild*/) const
       
  1113 {
       
  1114     return Unrelated;   //###
       
  1115 }
       
  1116 
       
  1117 int QAccessibleTitleBar::indexOfChild(const QAccessibleInterface * /*child*/) const
       
  1118 {
       
  1119     return -1;
       
  1120 }
       
  1121 
       
  1122 int QAccessibleTitleBar::childCount() const
       
  1123 {
       
  1124     QDockWidgetLayout *layout = dockWidgetLayout();
       
  1125     int count = 0;
       
  1126     for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
       
  1127         QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
       
  1128         if (w && w->isVisible())
       
  1129             ++count;
       
  1130     }
       
  1131     return count;
       
  1132 }
       
  1133 
       
  1134 QString QAccessibleTitleBar::text(Text t, int child) const
       
  1135 {
       
  1136     if (!child) {
       
  1137         if (t == Value) {
       
  1138             return dockWidget()->windowTitle();
       
  1139         }
       
  1140     }
       
  1141     return QString();
       
  1142 }
       
  1143 
       
  1144 QAccessible::State QAccessibleTitleBar::state(int child) const
       
  1145 {
       
  1146     QAccessible::State state = Normal;
       
  1147     if (child) {
       
  1148         QDockWidgetLayout *layout = dockWidgetLayout();
       
  1149         QAbstractButton *b = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
       
  1150         if (b) {
       
  1151             if (b->isDown())
       
  1152                 state |= Pressed;
       
  1153         }
       
  1154     } else {
       
  1155         QDockWidget *w = dockWidget();
       
  1156         if (w->testAttribute(Qt::WA_WState_Visible) == false)
       
  1157             state |= Invisible;
       
  1158         if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
       
  1159             state |= Focusable;
       
  1160         if (w->hasFocus())
       
  1161             state |= Focused;
       
  1162         if (!w->isEnabled())
       
  1163             state |= Unavailable;
       
  1164     }
       
  1165 
       
  1166     return state;
       
  1167 }
       
  1168 
       
  1169 QRect QAccessibleTitleBar::rect (int child ) const
       
  1170 {
       
  1171     bool mapToGlobal = true;
       
  1172     QRect rect;
       
  1173     if (child == 0) {
       
  1174         if (dockWidget()->isFloating()) {
       
  1175             rect = dockWidget()->frameGeometry();
       
  1176             QPoint globalPos = dockWidget()->mapToGlobal( dockWidget()->widget()->rect().topLeft() );
       
  1177             globalPos.ry()--;
       
  1178             rect.setBottom(globalPos.y());
       
  1179             mapToGlobal = false;
       
  1180         } else {
       
  1181             QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
       
  1182             rect = layout->titleArea();
       
  1183         }
       
  1184     }else if (child >= 1 && child <= childCount()) {
       
  1185         QDockWidgetLayout *layout = dockWidgetLayout();
       
  1186         int index = 1;
       
  1187         for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
       
  1188             QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
       
  1189             if (!w || !w->isVisible())
       
  1190                 continue;
       
  1191             if (index == child) {
       
  1192                 rect = w->geometry();
       
  1193                 break;
       
  1194             }
       
  1195             ++index;
       
  1196         }
       
  1197     }
       
  1198     if (rect.isNull())
       
  1199         return rect;
       
  1200 
       
  1201     if (mapToGlobal)
       
  1202         rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
       
  1203     return rect;
       
  1204 }
       
  1205 
       
  1206 int QAccessibleTitleBar::childAt(int x, int y) const
       
  1207 {
       
  1208     for (int i = childCount(); i >= 0; --i) {
       
  1209         if (rect(i).contains(x,y))
       
  1210             return i;
       
  1211     }
       
  1212     return -1;
       
  1213 }
       
  1214 
       
  1215 QObject *QAccessibleTitleBar::object() const
       
  1216 {
       
  1217     return m_dockWidget;
       
  1218 }
       
  1219 
       
  1220 QDockWidgetLayout *QAccessibleTitleBar::dockWidgetLayout() const
       
  1221 {
       
  1222     return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
       
  1223 }
       
  1224 
       
  1225 QDockWidget *QAccessibleTitleBar::dockWidget() const
       
  1226 {
       
  1227     return m_dockWidget;
       
  1228 }
       
  1229 
       
  1230 QString QAccessibleTitleBar::actionText(int action, Text t, int child) const
       
  1231 {
       
  1232     QString str;
       
  1233     if (child >= 1 && child <= childCount()) {
       
  1234         if (t == Name) {
       
  1235             switch (action) {
       
  1236             case Press:
       
  1237             case DefaultAction:
       
  1238                 if (child == QDockWidgetLayout::CloseButton) {
       
  1239                     str = QDockWidget::tr("Close");
       
  1240                 } else if (child == QDockWidgetLayout::FloatButton) {
       
  1241                     str = dockWidget()->isFloating() ? QDockWidget::tr("Dock")
       
  1242                                                      : QDockWidget::tr("Float");
       
  1243                 }
       
  1244                 break;
       
  1245             default:
       
  1246                 break;
       
  1247             }
       
  1248         }
       
  1249     }
       
  1250     return str;
       
  1251 }
       
  1252 
       
  1253 bool QAccessibleTitleBar::doAction(int action, int child, const QVariantList& /*params*/)
       
  1254 {
       
  1255     if (!child || !dockWidget()->isEnabled())
       
  1256         return false;
       
  1257 
       
  1258     switch (action) {
       
  1259     case DefaultAction:
       
  1260     case Press: {
       
  1261         QDockWidgetLayout *layout = dockWidgetLayout();
       
  1262         QAbstractButton *btn = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
       
  1263         if (btn)
       
  1264             btn->animateClick();
       
  1265         return true;
       
  1266         break;}
       
  1267     default:
       
  1268         break;
       
  1269     }
       
  1270 
       
  1271     return false;
       
  1272 }
       
  1273 
       
  1274 int QAccessibleTitleBar::userActionCount (int /*child*/) const
       
  1275 {
       
  1276     return 0;
       
  1277 }
       
  1278 
       
  1279 QAccessible::Role QAccessibleTitleBar::role(int child) const
       
  1280 {
       
  1281     switch (child) {
       
  1282         case 0:
       
  1283             return TitleBar;
       
  1284             break;
       
  1285         default:
       
  1286             if (child >= 1 && child <= childCount())
       
  1287                 return PushButton;
       
  1288             break;
       
  1289     }
       
  1290 
       
  1291     return NoRole;
       
  1292 }
       
  1293 
       
  1294 void QAccessibleTitleBar::setText(Text /*t*/, int /*child*/, const QString &/*text*/)
       
  1295 {
       
  1296 
       
  1297 }
       
  1298 
       
  1299 bool QAccessibleTitleBar::isValid() const
       
  1300 {
       
  1301     return dockWidget();
       
  1302 }
       
  1303 
       
  1304 #endif // QT_NO_DOCKWIDGET
       
  1305 
       
  1306 #ifndef QT_NO_TEXTEDIT
       
  1307 void QAccessibleTextEdit::addSelection(int startOffset, int endOffset)
       
  1308 {
       
  1309     setSelection(0, startOffset, endOffset);
       
  1310 }
       
  1311 
       
  1312 QString QAccessibleTextEdit::attributes(int offset, int *startOffset, int *endOffset)
       
  1313 {
       
  1314     // TODO - wait for a definition of attributes
       
  1315     Q_UNUSED(offset);
       
  1316     Q_UNUSED(startOffset);
       
  1317     Q_UNUSED(endOffset);
       
  1318     return QString();
       
  1319 }
       
  1320 
       
  1321 int QAccessibleTextEdit::cursorPosition()
       
  1322 {
       
  1323     return textEdit()->textCursor().position();
       
  1324 }
       
  1325 
       
  1326 QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
       
  1327 {
       
  1328     QTextEdit *edit = textEdit();
       
  1329     QTextCursor cursor(edit->document());
       
  1330     cursor.setPosition(offset);
       
  1331 
       
  1332     if (cursor.position() != offset)
       
  1333         return QRect();
       
  1334 
       
  1335     QRect r = edit->cursorRect(cursor);
       
  1336     if (cursor.movePosition(QTextCursor::NextCharacter)) {
       
  1337         r.setWidth(edit->cursorRect(cursor).y() - r.y());
       
  1338     } else {
       
  1339         // we don't know the width of the character - maybe because we're at document end
       
  1340         // in that case, IAccessible2 tells us to return the width of a default character
       
  1341         int averageCharWidth = QFontMetrics(cursor.charFormat().font()).averageCharWidth();
       
  1342         if (edit->layoutDirection() == Qt::RightToLeft)
       
  1343             averageCharWidth *= -1;
       
  1344         r.setWidth(averageCharWidth);
       
  1345     }
       
  1346 
       
  1347     switch (coordType) {
       
  1348     case RelativeToScreen:
       
  1349         r.moveTo(edit->viewport()->mapToGlobal(r.topLeft()));
       
  1350         break;
       
  1351     case RelativeToParent:
       
  1352         break;
       
  1353     }
       
  1354 
       
  1355     return r;
       
  1356 }
       
  1357 
       
  1358 int QAccessibleTextEdit::selectionCount()
       
  1359 {
       
  1360     return textEdit()->textCursor().hasSelection() ? 1 : 0;
       
  1361 }
       
  1362 
       
  1363 int QAccessibleTextEdit::offsetAtPoint(const QPoint &point, CoordinateType coordType)
       
  1364 {
       
  1365     QTextEdit *edit = textEdit();
       
  1366 
       
  1367     QPoint p = point;
       
  1368     if (coordType == RelativeToScreen)
       
  1369         p = edit->viewport()->mapFromGlobal(p);
       
  1370     // convert to document coordinates
       
  1371     p += QPoint(edit->horizontalScrollBar()->value(), edit->verticalScrollBar()->value());
       
  1372 
       
  1373     return edit->document()->documentLayout()->hitTest(p, Qt::ExactHit);
       
  1374 }
       
  1375 
       
  1376 void QAccessibleTextEdit::selection(int selectionIndex, int *startOffset, int *endOffset)
       
  1377 {
       
  1378     *startOffset = *endOffset = 0;
       
  1379     QTextCursor cursor = textEdit()->textCursor();
       
  1380 
       
  1381     if (selectionIndex != 0 || !cursor.hasSelection())
       
  1382         return;
       
  1383 
       
  1384     *startOffset = cursor.selectionStart();
       
  1385     *endOffset = cursor.selectionEnd();
       
  1386 }
       
  1387 
       
  1388 QString QAccessibleTextEdit::text(int startOffset, int endOffset)
       
  1389 {
       
  1390     QTextCursor cursor(textEdit()->document());
       
  1391 
       
  1392     cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
       
  1393     cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
       
  1394 
       
  1395     return cursor.selectedText();
       
  1396 }
       
  1397 
       
  1398 QString QAccessibleTextEdit::textBeforeOffset (int offset, BoundaryType boundaryType,
       
  1399         int *startOffset, int *endOffset)
       
  1400 {
       
  1401     // TODO - what exactly is before?
       
  1402     Q_UNUSED(offset);
       
  1403     Q_UNUSED(boundaryType);
       
  1404     Q_UNUSED(startOffset);
       
  1405     Q_UNUSED(endOffset);
       
  1406     return QString();
       
  1407 }
       
  1408 
       
  1409 QString QAccessibleTextEdit::textAfterOffset(int offset, BoundaryType boundaryType,
       
  1410         int *startOffset, int *endOffset)
       
  1411 {
       
  1412     // TODO - what exactly is after?
       
  1413     Q_UNUSED(offset);
       
  1414     Q_UNUSED(boundaryType);
       
  1415     Q_UNUSED(startOffset);
       
  1416     Q_UNUSED(endOffset);
       
  1417     return QString();
       
  1418 }
       
  1419 
       
  1420 QString QAccessibleTextEdit::textAtOffset(int offset, BoundaryType boundaryType,
       
  1421                                           int *startOffset, int *endOffset)
       
  1422 {
       
  1423     Q_ASSERT(startOffset);
       
  1424     Q_ASSERT(endOffset);
       
  1425 
       
  1426     *startOffset = *endOffset = -1;
       
  1427     QTextEdit *edit = textEdit();
       
  1428 
       
  1429     QTextCursor cursor(edit->document());
       
  1430     if (offset >= characterCount())
       
  1431         return QString();
       
  1432 
       
  1433     switch (boundaryType) {
       
  1434     case CharBoundary:
       
  1435         cursor.setPosition(offset);
       
  1436         *startOffset = cursor.position();
       
  1437         cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
       
  1438         *endOffset = cursor.position();
       
  1439         break;
       
  1440     case WordBoundary:
       
  1441         cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
       
  1442         *startOffset = cursor.position();
       
  1443         cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
       
  1444         *endOffset = cursor.position();
       
  1445         break;
       
  1446     case SentenceBoundary:
       
  1447         // TODO - what's a sentence?
       
  1448         return QString();
       
  1449     case LineBoundary:
       
  1450         cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
       
  1451         *startOffset = cursor.position();
       
  1452         cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
       
  1453         *endOffset = cursor.position();
       
  1454         break;
       
  1455     case ParagraphBoundary:
       
  1456         cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
       
  1457         *startOffset = cursor.position();
       
  1458         cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
       
  1459         *endOffset = cursor.position();
       
  1460         break;
       
  1461     case NoBoundary: {
       
  1462         *startOffset = 0;
       
  1463         const QString txt = edit->toPlainText();
       
  1464         *endOffset = txt.count();
       
  1465         return txt; }
       
  1466     default:
       
  1467         qDebug("AccessibleTextAdaptor::textAtOffset: Unknown boundary type %d", boundaryType);
       
  1468         return QString();
       
  1469     }
       
  1470 
       
  1471     return cursor.selectedText();
       
  1472 }
       
  1473 
       
  1474 void QAccessibleTextEdit::removeSelection(int selectionIndex)
       
  1475 {
       
  1476     if (selectionIndex != 0)
       
  1477         return;
       
  1478 
       
  1479     QTextCursor cursor = textEdit()->textCursor();
       
  1480     cursor.clearSelection();
       
  1481     textEdit()->setTextCursor(cursor);
       
  1482 }
       
  1483 
       
  1484 void QAccessibleTextEdit::setCursorPosition(int position)
       
  1485 {
       
  1486     QTextCursor cursor = textEdit()->textCursor();
       
  1487     cursor.setPosition(position);
       
  1488     textEdit()->setTextCursor(cursor);
       
  1489 }
       
  1490 
       
  1491 void QAccessibleTextEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
       
  1492 {
       
  1493     if (selectionIndex != 0)
       
  1494         return;
       
  1495 
       
  1496     QTextCursor cursor = textEdit()->textCursor();
       
  1497     cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
       
  1498     cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
       
  1499     textEdit()->setTextCursor(cursor);
       
  1500 }
       
  1501 
       
  1502 int QAccessibleTextEdit::characterCount()
       
  1503 {
       
  1504     return textEdit()->toPlainText().count();
       
  1505 }
       
  1506 
       
  1507 void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
       
  1508 {
       
  1509     QTextEdit *edit = textEdit();
       
  1510 
       
  1511     QTextCursor cursor(edit->document());
       
  1512     cursor.setPosition(startIndex);
       
  1513     QRect r = edit->cursorRect(cursor);
       
  1514 
       
  1515     cursor.setPosition(endIndex);
       
  1516     r.setBottomRight(edit->cursorRect(cursor).bottomRight());
       
  1517 
       
  1518     r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
       
  1519              r.y() + edit->verticalScrollBar()->value());
       
  1520 
       
  1521     // E V I L, but ensureVisible is not public
       
  1522     if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
       
  1523         qWarning("AccessibleTextEdit::scrollToSubstring failed!");
       
  1524 }
       
  1525 
       
  1526 static QTextCursor cursorForRange(QTextEdit *textEdit, int startOffset, int endOffset)
       
  1527 {
       
  1528     QTextCursor cursor(textEdit->document());
       
  1529     cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
       
  1530     cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
       
  1531 
       
  1532     return cursor;
       
  1533 }
       
  1534 
       
  1535 void QAccessibleTextEdit::copyText(int startOffset, int endOffset)
       
  1536 {
       
  1537     QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
       
  1538 
       
  1539     if (!cursor.hasSelection())
       
  1540         return;
       
  1541 
       
  1542 //     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
       
  1543 }
       
  1544 
       
  1545 void QAccessibleTextEdit::deleteText(int startOffset, int endOffset)
       
  1546 {
       
  1547     QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
       
  1548 
       
  1549     cursor.removeSelectedText();
       
  1550 }
       
  1551 
       
  1552 void QAccessibleTextEdit::insertText(int offset, const QString &text)
       
  1553 {
       
  1554     QTextCursor cursor(textEdit()->document());
       
  1555     cursor.setPosition(offset);
       
  1556 
       
  1557     cursor.insertText(text);
       
  1558 }
       
  1559 
       
  1560 void QAccessibleTextEdit::cutText(int startOffset, int endOffset)
       
  1561 {
       
  1562     QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
       
  1563 
       
  1564     if (!cursor.hasSelection())
       
  1565         return;
       
  1566 
       
  1567 //     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
       
  1568     cursor.removeSelectedText();
       
  1569 }
       
  1570 
       
  1571 void QAccessibleTextEdit::pasteText(int offset)
       
  1572 {
       
  1573     QTextEdit *edit = textEdit();
       
  1574 
       
  1575     QTextCursor oldCursor = edit->textCursor();
       
  1576     QTextCursor newCursor = oldCursor;
       
  1577     newCursor.setPosition(offset);
       
  1578 
       
  1579     edit->setTextCursor(newCursor);
       
  1580 #ifndef QT_NO_CLIPBOARD
       
  1581     edit->paste();
       
  1582 #endif
       
  1583     edit->setTextCursor(oldCursor);
       
  1584 }
       
  1585 
       
  1586 void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QString &text)
       
  1587 {
       
  1588     QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
       
  1589 
       
  1590     cursor.removeSelectedText();
       
  1591     cursor.insertText(text);
       
  1592 }
       
  1593 
       
  1594 void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes)
       
  1595 {
       
  1596     // TODO
       
  1597     Q_UNUSED(startOffset);
       
  1598     Q_UNUSED(endOffset);
       
  1599     Q_UNUSED(attributes);
       
  1600 }
       
  1601 
       
  1602 #endif // QT_NO_TEXTEDIT
       
  1603 
       
  1604 #ifndef QT_NO_MAINWINDOW
       
  1605 QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
       
  1606     : QAccessibleWidgetEx(widget, Application) { }
       
  1607 
       
  1608 QVariant QAccessibleMainWindow::invokeMethodEx(QAccessible::Method /*method*/, int /*child*/, const QVariantList & /*params*/)
       
  1609 {
       
  1610     return QVariant();
       
  1611 }
       
  1612 
       
  1613 int QAccessibleMainWindow::childCount() const
       
  1614 {
       
  1615     QList<QWidget*> kids = childWidgets(mainWindow(), true);
       
  1616     return kids.count();
       
  1617 }
       
  1618 
       
  1619 int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const
       
  1620 {
       
  1621     QList<QWidget*> kids = childWidgets(mainWindow(), true);
       
  1622     int childIndex = kids.indexOf(static_cast<QWidget*>(iface->object()));
       
  1623     return childIndex == -1 ? -1 : ++childIndex;
       
  1624 }
       
  1625 
       
  1626 int QAccessibleMainWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
       
  1627 {
       
  1628     if (relation == Child && entry >= 1) {
       
  1629         QList<QWidget*> kids = childWidgets(mainWindow(), true);
       
  1630         if (entry <= kids.count()) {
       
  1631             *iface = QAccessible::queryAccessibleInterface(kids.at(entry - 1));
       
  1632             return *iface ? 0 : -1;
       
  1633         }
       
  1634     }
       
  1635     return QAccessibleWidgetEx::navigate(relation, entry, iface);
       
  1636 }
       
  1637 
       
  1638 int QAccessibleMainWindow::childAt(int x, int y) const
       
  1639 {
       
  1640     QWidget *w = widget();
       
  1641     if (!w->isVisible())
       
  1642         return -1;
       
  1643     QPoint gp = w->mapToGlobal(QPoint(0, 0));
       
  1644     if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
       
  1645         return -1;
       
  1646 
       
  1647     QWidgetList kids = childWidgets(mainWindow(), true);
       
  1648     QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y));
       
  1649     for (int i = 0; i < kids.size(); ++i) {
       
  1650         QWidget *child = kids.at(i);
       
  1651         if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
       
  1652             return i + 1;
       
  1653         }
       
  1654     }
       
  1655     return 0;
       
  1656 }
       
  1657 
       
  1658 QMainWindow *QAccessibleMainWindow::mainWindow() const
       
  1659 {
       
  1660     return qobject_cast<QMainWindow *>(object());
       
  1661 }
       
  1662 
       
  1663 #endif //QT_NO_MAINWINDOW
       
  1664 
       
  1665 QT_END_NAMESPACE
       
  1666 
       
  1667 #endif // QT_NO_ACCESSIBILITY