src/plugins/accessible/widgets/complexwidgets.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 "complexwidgets.h"
       
    43 
       
    44 #include <qapplication.h>
       
    45 #include <qabstractbutton.h>
       
    46 #include <qevent.h>
       
    47 #include <qheaderview.h>
       
    48 #include <qtabbar.h>
       
    49 #include <qcombobox.h>
       
    50 #include <qlistview.h>
       
    51 #include <qtableview.h>
       
    52 #include <qlineedit.h>
       
    53 #include <qstyle.h>
       
    54 #include <qstyleoption.h>
       
    55 #include <qtooltip.h>
       
    56 #include <qwhatsthis.h>
       
    57 #include <qtreeview.h>
       
    58 #include <private/qtabbar_p.h>
       
    59 #include <QAbstractScrollArea>
       
    60 #include <QScrollArea>
       
    61 #include <QScrollBar>
       
    62 #include <QDebug>
       
    63 
       
    64 #ifndef QT_NO_ACCESSIBILITY
       
    65 
       
    66 QT_BEGIN_NAMESPACE
       
    67 
       
    68 QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
       
    69 
       
    70 #ifndef QT_NO_ITEMVIEWS
       
    71 /*
       
    72 The MSDN article "Exposing Data Tables through Microsoft Active Accessibility" explains
       
    73 how data tables should be exposed. Url: http://msdn2.microsoft.com/en-us/library/ms971325.aspx
       
    74 Basically, the model is like this:
       
    75 
       
    76 ROLE_SYSTEM_TABLE
       
    77   |- ROLE_SYSTEM_ROW
       
    78   |  |- ROLE_SYSTEM_ROWHEADER
       
    79   |  |- ROLE_SYSTEM_COLUMNHEADER
       
    80   |  |- ROLE_SYSTEM_COLUMNHEADER
       
    81   |  |- ROLE_SYSTEM_COLUMNHEADER
       
    82   |     '- ..
       
    83   |- ROLE_SYSTEM_ROW
       
    84   |  |- ROLE_SYSTEM_ROWHEADER
       
    85   |  |- ROLE_SYSTEM_CELL
       
    86   |  |- ROLE_SYSTEM_CELL
       
    87   |  |- ROLE_SYSTEM_CELL
       
    88   |   '- ..
       
    89   |- ROLE_SYSTEM_ROW
       
    90   |  |- ROLE_SYSTEM_ROWHEADER
       
    91   |  |- ROLE_SYSTEM_CELL
       
    92   |  |- ROLE_SYSTEM_CELL
       
    93   |  |- ROLE_SYSTEM_CELL
       
    94   |   '- ..
       
    95    '- ..
       
    96 
       
    97 The headers of QTreeView is also represented like this.
       
    98 */
       
    99 QAccessibleItemRow::QAccessibleItemRow(QAbstractItemView *aView, const QModelIndex &index, bool isHeader)
       
   100     : row(index), view(aView), m_header(isHeader)
       
   101 {
       
   102 }
       
   103 
       
   104 QHeaderView *QAccessibleItemRow::horizontalHeader() const
       
   105 {
       
   106     QHeaderView *header = 0;
       
   107     if (m_header) {
       
   108         if (false) {
       
   109 #ifndef QT_NO_TABLEVIEW
       
   110         } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
       
   111             header = tv->horizontalHeader();
       
   112 #endif
       
   113 #ifndef QT_NO_TREEVIEW
       
   114         } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
       
   115             header = tv->header();
       
   116 #endif
       
   117         }
       
   118     }
       
   119     return header;
       
   120 }
       
   121 
       
   122 QHeaderView *QAccessibleItemRow::verticalHeader() const
       
   123 {
       
   124     QHeaderView *header = 0;
       
   125 #ifndef QT_NO_TABLEVIEW
       
   126     if (const QTableView *tv = qobject_cast<const QTableView*>(view))
       
   127         header = tv->verticalHeader();
       
   128 #endif
       
   129     return header;
       
   130 }
       
   131 
       
   132 int QAccessibleItemRow::logicalFromChild(QHeaderView *header, int child) const
       
   133 {
       
   134     int logical = -1;
       
   135     if (header->sectionsHidden()) {
       
   136         int kid = 0;
       
   137         for (int i = 0; i < header->count(); ++i) {
       
   138             if (!header->isSectionHidden(i))
       
   139                 ++kid;
       
   140             if (kid == child) {
       
   141                 logical = i;
       
   142                 break;
       
   143             }
       
   144         }
       
   145     } else {
       
   146         logical = child - 1;
       
   147     }
       
   148     return logical;
       
   149 }
       
   150 
       
   151 QRect QAccessibleItemRow::rect(int child) const
       
   152 {
       
   153     QRect r;
       
   154     if (view && view->isVisible()) {
       
   155         if (QHeaderView *header = horizontalHeader()) {
       
   156             if (!child) {
       
   157                 r = header->rect();
       
   158             } else {
       
   159                 if (QHeaderView *vheader = verticalHeader()) {
       
   160                     if (child == 1) {
       
   161                         int w = vheader->width();
       
   162                         int h = header->height();
       
   163                         r.setRect(0, 0, w, h);
       
   164                     }
       
   165                     --child;
       
   166                 }
       
   167                 if (child) {
       
   168                     int logical = logicalFromChild(header, child);
       
   169                     int w = header->sectionSize(logical);
       
   170                     r.setRect(header->sectionViewportPosition(logical), 0, w, header->height());
       
   171                     r.translate(header->mapTo(view, QPoint(0, 0)));
       
   172                 }
       
   173             }
       
   174         } else if (row.isValid()) {
       
   175             if (!child) {
       
   176                 QModelIndex parent = row.parent();
       
   177                 const int colCount = row.model()->columnCount(parent);
       
   178                 for (int i = 0; i < colCount; ++i)
       
   179                     r |= view->visualRect(row.model()->index(row.row(), i, parent));
       
   180                 r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
       
   181 
       
   182                 if (const QHeaderView *vheader = verticalHeader()) { // include the section of the vertical header
       
   183                     QRect re;
       
   184                     int logicalRow = row.row();
       
   185                     int h = vheader->sectionSize(logicalRow);
       
   186                     re.setRect(0, vheader->sectionViewportPosition(logicalRow), vheader->width(), h);
       
   187                     re.translate(vheader->mapTo(view, QPoint(0, 0)));
       
   188                     r |= re;
       
   189                 }
       
   190             } else {
       
   191                 if (QHeaderView *vheader = verticalHeader()) {
       
   192                     if (child == 1) {
       
   193                         int logicalRow = row.row();
       
   194                         int h = vheader->sectionSize(logicalRow);
       
   195                         r.setRect(0, vheader->sectionViewportPosition(logicalRow), vheader->width(), h);
       
   196                         r.translate(vheader->mapTo(view, QPoint(0, 0)));
       
   197                     }
       
   198                     --child;
       
   199                 }
       
   200                 if (child) {
       
   201                     r = view->visualRect(childIndex(child));
       
   202                     r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
       
   203                 }
       
   204             }
       
   205         }
       
   206     }
       
   207     if (!r.isNull())
       
   208         r.translate(view->mapToGlobal(QPoint(0, 0)));
       
   209 
       
   210     return r;
       
   211 }
       
   212 
       
   213 int QAccessibleItemRow::treeLevel() const
       
   214 {
       
   215     int level = 0;
       
   216     QModelIndex idx = row;
       
   217     while (idx.isValid()) {
       
   218         idx = idx.parent();
       
   219         ++level;
       
   220     }
       
   221     return level;
       
   222 }
       
   223 
       
   224 QString QAccessibleItemRow::text_helper(int child) const
       
   225 {
       
   226     QString value;
       
   227     if (m_header) {
       
   228         if (!child)
       
   229             return QString();
       
   230         if (verticalHeader()) {
       
   231             if (child == 1)
       
   232                 return QString();
       
   233             --child;
       
   234         }
       
   235         QHeaderView *header = horizontalHeader();
       
   236         int logical = logicalFromChild(header, child);
       
   237         value = view->model()->headerData(logical, Qt::Horizontal, Qt::AccessibleTextRole).toString();
       
   238         if (value.isEmpty())
       
   239             value = view->model()->headerData(logical, Qt::Horizontal).toString();
       
   240         return value;
       
   241     } else {
       
   242         if (!child) {   // for one-column views (i.e. QListView)
       
   243             if (children().count() >= 1)
       
   244                 child = 1;
       
   245             else
       
   246                 return QString();
       
   247         }
       
   248         if (verticalHeader()) {
       
   249             if (child == 1) {
       
   250                 int logical = row.row();
       
   251                 value = view->model()->headerData(logical, Qt::Vertical, Qt::AccessibleTextRole).toString();
       
   252                 if (value.isEmpty())
       
   253                     value = view->model()->headerData(logical, Qt::Vertical).toString();
       
   254                 return value;
       
   255             } else {
       
   256                 --child;
       
   257             }
       
   258         }
       
   259     }
       
   260     if (value.isEmpty()) {
       
   261         QModelIndex idx = childIndex(child);
       
   262         if (idx.isValid()) {
       
   263             value = idx.model()->data(idx, Qt::AccessibleTextRole).toString();
       
   264             if (value.isEmpty())
       
   265                 value = idx.model()->data(idx, Qt::DisplayRole).toString();
       
   266         }
       
   267     }
       
   268     return value;
       
   269 }
       
   270 
       
   271 QString QAccessibleItemRow::text(Text t, int child) const
       
   272 {
       
   273     QString value;
       
   274     if (t == Name) {
       
   275         value = text_helper(child);
       
   276     } else if (t == Value) {
       
   277 #ifndef QT_NO_TREEVIEW
       
   278         if (qobject_cast<const QTreeView*>(view)) {
       
   279             if (child == 0)
       
   280                 value = QString::number(treeLevel());
       
   281         } else
       
   282 #endif
       
   283         {
       
   284             value = text_helper(child);
       
   285         }
       
   286     } else if (t == Description) {
       
   287 #ifndef QT_NO_TREEVIEW
       
   288         if (child == 0 && qobject_cast<const QTreeView*>(view)) {
       
   289             // We store the tree coordinates of the current item in the description.
       
   290             // This enables some screen readers to report where the focus is
       
   291             // in a tree view. (works in JAWS). Also, Firefox does the same thing.
       
   292             // For instance the description "L2, 4 of 25 with 24" means
       
   293             // "L2": Tree Level 2
       
   294             // "4 of 25": We are item 4 out of in total 25 other siblings
       
   295             // "with 24": We have 24 children. (JAWS does not read this number)
       
   296 
       
   297             // level
       
   298             int level = treeLevel();
       
   299 
       
   300             QAbstractItemModel *m = view->model();
       
   301             // totalSiblings and itemIndex
       
   302             QModelIndex parent = row.parent();
       
   303             int rowCount = m->rowCount(parent);
       
   304             int itemIndex = -1;
       
   305             int totalSiblings = 0;
       
   306             for (int i = 0 ; i < rowCount; ++i) {
       
   307                 QModelIndex sibling = row.sibling(i, 0);
       
   308                 if (!view->isIndexHidden(sibling))
       
   309                     ++totalSiblings;
       
   310                 if (row == sibling)
       
   311                     itemIndex = totalSiblings;
       
   312             }
       
   313             int totalChildren = m->rowCount(row);   // JAWS does not report child count, so we do
       
   314                                                     // this simple and efficient.
       
   315                                                     // (don't check if they are all visible).
       
   316             value = QString::fromAscii("L%1, %2 of %3 with %4").arg(level).arg(itemIndex).arg(totalSiblings).arg(totalChildren);
       
   317         } else
       
   318 #endif // QT_NO_TREEVIEW
       
   319         {
       
   320             if (!m_header) {
       
   321                 if (child == 0 && children().count() >= 1)
       
   322                     child = 1;
       
   323                 if (verticalHeader()) {
       
   324                     if (child == 1) {
       
   325                         value = view->model()->headerData(row.row(), Qt::Vertical).toString();
       
   326                     }
       
   327                     --child;
       
   328                 }
       
   329                 if (child) {
       
   330                     QModelIndex idx = childIndex(child);
       
   331                     value = idx.model()->data(idx, Qt::AccessibleDescriptionRole).toString();
       
   332                 }
       
   333 
       
   334             }
       
   335         }
       
   336     }
       
   337     return value;
       
   338 }
       
   339 
       
   340 void QAccessibleItemRow::setText(Text t, int child, const QString &text)
       
   341 {
       
   342     if (m_header) {
       
   343         if (child)
       
   344             view->model()->setHeaderData(child - 1, Qt::Horizontal, text);
       
   345         // child == 0 means the cell to the left of the horizontal header, which is empty!?
       
   346     } else {
       
   347         if (!child) {
       
   348             if (children().count() == 1)
       
   349                 child = 1;
       
   350             else
       
   351                 return;
       
   352         }
       
   353 
       
   354         if (verticalHeader()) {
       
   355             if (child == 1) {
       
   356                 view->model()->setHeaderData(row.row(), Qt::Vertical, text);
       
   357                 return;
       
   358             }
       
   359             --child;
       
   360         }
       
   361         QModelIndex idx = childIndex(child);
       
   362         if (!idx.isValid())
       
   363             return;
       
   364 
       
   365         switch (t) {
       
   366         case Description:
       
   367             const_cast<QAbstractItemModel *>(idx.model())->setData(idx, text,
       
   368                                              Qt::AccessibleDescriptionRole);
       
   369             break;
       
   370         case Value:
       
   371             const_cast<QAbstractItemModel *>(idx.model())->setData(idx, text, Qt::EditRole);
       
   372             break;
       
   373         default:
       
   374             break;
       
   375         }
       
   376     }
       
   377 }
       
   378 
       
   379 QModelIndex QAccessibleItemRow::childIndex(int child) const
       
   380 {
       
   381     QList<QModelIndex> kids = children();
       
   382     Q_ASSERT(child >= 1 && child <= kids.count());
       
   383     return kids.at(child - 1);
       
   384 }
       
   385 
       
   386 QList<QModelIndex> QAccessibleItemRow::children() const
       
   387 {
       
   388     QList<QModelIndex> kids;
       
   389     for (int i = 0; i < row.model()->columnCount(row.parent()); ++i) {
       
   390         QModelIndex idx = row.model()->index(row.row(), i, row.parent());
       
   391         if (!view->isIndexHidden(idx)) {
       
   392             kids << idx;
       
   393         }
       
   394     }
       
   395     return kids;
       
   396 }
       
   397 
       
   398 bool QAccessibleItemRow::isValid() const
       
   399 {
       
   400     return m_header ? true : row.isValid();
       
   401 }
       
   402 
       
   403 QObject *QAccessibleItemRow::object() const
       
   404 {
       
   405     return 0;
       
   406 }
       
   407 
       
   408 int QAccessibleItemRow::childCount() const
       
   409 {
       
   410     int count = 0;
       
   411     if (QHeaderView *header = horizontalHeader()) {
       
   412         count = header->count() - header->hiddenSectionCount();
       
   413     } else {
       
   414         count = children().count();
       
   415     }
       
   416 #ifndef QT_NO_TABLEVIEW
       
   417     if (qobject_cast<const QTableView*>(view)) {
       
   418         if (verticalHeader())
       
   419             ++count;
       
   420     }
       
   421 #endif
       
   422     return count;
       
   423 }
       
   424 
       
   425 int QAccessibleItemRow::indexOfChild(const QAccessibleInterface *iface) const
       
   426 {
       
   427     if (!iface || iface->role(0) != Row)
       
   428         return -1;
       
   429 
       
   430     //### meaningless code?
       
   431     QList<QModelIndex> kids = children();
       
   432     QModelIndex idx = static_cast<const QAccessibleItemRow *>(iface)->row;
       
   433     if (!idx.isValid())
       
   434         return -1;
       
   435     return kids.indexOf(idx) + 1;
       
   436 }
       
   437 
       
   438 QAccessible::Relation QAccessibleItemRow::relationTo(int child, const QAccessibleInterface *other,
       
   439         int otherChild) const
       
   440 {
       
   441     if (!child && !otherChild && other->object() == view)
       
   442         return Child;
       
   443     if (!child && !otherChild && other == this)
       
   444         return Self;
       
   445     if (!child && otherChild && other == this)
       
   446         return Ancestor;
       
   447     if (child && otherChild && other == this)
       
   448         return Sibling;
       
   449     return Unrelated;
       
   450 }
       
   451 
       
   452 int QAccessibleItemRow::childAt(int x, int y) const
       
   453 {
       
   454     if (!view || !view->isVisible())
       
   455         return -1;
       
   456 
       
   457     for (int i = childCount(); i >= 0; --i) {
       
   458         if (rect(i).contains(x, y))
       
   459             return i;
       
   460     }
       
   461     return -1;
       
   462 }
       
   463 
       
   464 QAbstractItemView::CursorAction QAccessibleItemRow::toCursorAction(
       
   465                                            QAccessible::Relation rel)
       
   466 {
       
   467     switch (rel) {
       
   468     case QAccessible::Up:
       
   469         return QAbstractItemView::MoveUp;
       
   470     case QAccessible::Down:
       
   471         return QAbstractItemView::MoveDown;
       
   472     case QAccessible::Left:
       
   473         return QAbstractItemView::MoveLeft;
       
   474     case QAccessible::Right:
       
   475         return QAbstractItemView::MoveRight;
       
   476     default:
       
   477         Q_ASSERT(false);
       
   478     }
       
   479     // should never be reached.
       
   480     return QAbstractItemView::MoveRight;
       
   481 }
       
   482 
       
   483 int QAccessibleItemRow::navigate(RelationFlag relation, int index,
       
   484                                  QAccessibleInterface **iface) const
       
   485 {
       
   486     *iface = 0;
       
   487     if (!view)
       
   488         return -1;
       
   489 
       
   490     switch (relation) {
       
   491     case Ancestor: {
       
   492         if (!index)
       
   493             return -1;
       
   494         QAccessibleItemView *ancestor = new QAccessibleItemView(view->viewport());
       
   495         if (index == 1) {
       
   496             *iface = ancestor;
       
   497             return 0;
       
   498         } else if (index > 1) {
       
   499             int ret = ancestor->navigate(Ancestor, index - 1, iface);
       
   500             delete ancestor;
       
   501             return ret;
       
   502         }
       
   503         }
       
   504     case Child: {
       
   505         if (!index)
       
   506             return -1;
       
   507         if (index < 1 && index > childCount())
       
   508             return -1;
       
   509 
       
   510         return index;}
       
   511     case Sibling:
       
   512         if (index) {
       
   513             QAccessibleInterface *ifaceParent = 0;
       
   514             navigate(Ancestor, 1, &ifaceParent);
       
   515             if (ifaceParent) {
       
   516                 int entry = ifaceParent->navigate(Child, index, iface);
       
   517                 delete ifaceParent;
       
   518                 return entry;
       
   519             }
       
   520         }
       
   521         return -1;
       
   522     case Up:
       
   523     case Down:
       
   524     case Left:
       
   525     case Right: {
       
   526         // This is in the "not so nice" category. In order to find out which item
       
   527         // is geometrically around, we have to set the current index, navigate
       
   528         // and restore the index as well as the old selection
       
   529         view->setUpdatesEnabled(false);
       
   530         const QModelIndex oldIdx = view->currentIndex();
       
   531         QList<QModelIndex> kids = children();
       
   532         const QModelIndex currentIndex = index ? kids.at(index - 1) : QModelIndex(row);
       
   533         const QItemSelection oldSelection = view->selectionModel()->selection();
       
   534         view->setCurrentIndex(currentIndex);
       
   535         const QModelIndex idx = view->moveCursor(toCursorAction(relation), Qt::NoModifier);
       
   536         view->setCurrentIndex(oldIdx);
       
   537         view->selectionModel()->select(oldSelection, QItemSelectionModel::ClearAndSelect);
       
   538         view->setUpdatesEnabled(true);
       
   539         if (!idx.isValid())
       
   540             return -1;
       
   541 
       
   542         if (idx.parent() != row.parent() || idx.row() != row.row())
       
   543             *iface = new QAccessibleItemRow(view, idx);
       
   544         return index ? kids.indexOf(idx) + 1 : 0; }
       
   545     default:
       
   546         break;
       
   547     }
       
   548 
       
   549     return -1;
       
   550 }
       
   551 
       
   552 QAccessible::Role QAccessibleItemRow::role(int child) const
       
   553 {
       
   554     if (false) {
       
   555 #ifndef QT_NO_TREEVIEW
       
   556     } else if (qobject_cast<const QTreeView*>(view)) {
       
   557         if (horizontalHeader()) {
       
   558             if (!child)
       
   559                 return Row;
       
   560             return ColumnHeader;
       
   561         }
       
   562         return TreeItem;
       
   563 #endif
       
   564 #ifndef QT_NO_LISTVIEW
       
   565     } else if (qobject_cast<const QListView*>(view)) {
       
   566         return ListItem;
       
   567 #endif
       
   568 #ifndef QT_NO_TABLEVIEW
       
   569     } else if (qobject_cast<const QTableView *>(view)) {
       
   570         if (!child)
       
   571             return Row;
       
   572         if (child == 1) {
       
   573             if (verticalHeader())
       
   574                 return RowHeader;
       
   575         }
       
   576         if (m_header)
       
   577             return ColumnHeader;
       
   578 #endif
       
   579     }
       
   580     return Cell;
       
   581 }
       
   582 
       
   583 QAccessible::State QAccessibleItemRow::state(int child) const
       
   584 {
       
   585     State st = Normal;
       
   586 
       
   587     if (!view)
       
   588         return st;
       
   589 
       
   590     QAccessibleInterface *parent = 0;
       
   591     QRect globalRect;
       
   592     if (navigate(Ancestor, 1, &parent) == 0) {
       
   593         globalRect = parent->rect(0);
       
   594         delete parent;
       
   595     }
       
   596     if (!globalRect.intersects(rect(child)))
       
   597         st |= Invisible;
       
   598 
       
   599     if (!horizontalHeader()) {
       
   600         if (!(st & Invisible)) {
       
   601             if (child) {
       
   602                 if (QHeaderView *vheader = verticalHeader() ) {
       
   603                     if (child == 1) {
       
   604                         if (!vheader->isVisible())
       
   605                             st |= Invisible;
       
   606                     }
       
   607                     --child;
       
   608                 }
       
   609                 if (child) {
       
   610                     QModelIndex idx = childIndex(child);
       
   611                     if (!idx.isValid())
       
   612                         return st;
       
   613 
       
   614                     if (view->selectionModel()->isSelected(idx))
       
   615                         st |= Selected;
       
   616                     if (view->selectionModel()->currentIndex() == idx)
       
   617                         st |= Focused;
       
   618                     if (idx.model()->data(idx, Qt::CheckStateRole).toInt() == Qt::Checked)
       
   619                         st |= Checked;
       
   620 
       
   621                     Qt::ItemFlags flags = idx.flags();
       
   622                     if (flags & Qt::ItemIsSelectable) {
       
   623                         st |= Selectable;
       
   624                         if (view->selectionMode() == QAbstractItemView::MultiSelection)
       
   625                             st |= MultiSelectable;
       
   626                         if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
       
   627                             st |= ExtSelectable;
       
   628                     }
       
   629                 }
       
   630             } else {
       
   631                 Qt::ItemFlags flags = row.flags();
       
   632                 if (flags & Qt::ItemIsSelectable) {
       
   633                     st |= Selectable;
       
   634                     st |= Focusable;
       
   635                 }
       
   636                 if (view->selectionModel()->isRowSelected(row.row(), row.parent()))
       
   637                     st |= Selected;
       
   638                 if (view->selectionModel()->currentIndex().row() == row.row())
       
   639                     st |= Focused;
       
   640             }
       
   641         }
       
   642     }
       
   643 
       
   644     return st;
       
   645 }
       
   646 
       
   647 int QAccessibleItemRow::userActionCount(int) const
       
   648 {
       
   649     return 0;
       
   650 }
       
   651 
       
   652 QString QAccessibleItemRow::actionText(int, Text, int) const
       
   653 {
       
   654     return QString();
       
   655 }
       
   656 
       
   657 static QItemSelection rowAt(const QModelIndex &idx)
       
   658 {
       
   659     return QItemSelection(idx.sibling(idx.row(), 0),
       
   660                 idx.sibling(idx.row(), idx.model()->columnCount(idx.parent())));
       
   661 }
       
   662 
       
   663 bool QAccessibleItemRow::doAction(int action, int child, const QVariantList & /*params*/)
       
   664 {
       
   665     if (!view)
       
   666         return false;
       
   667 
       
   668     if (verticalHeader())
       
   669         --child;
       
   670 
       
   671     QModelIndex idx = child ? childIndex(child) : QModelIndex(row);
       
   672     if (!idx.isValid())
       
   673         return false;
       
   674 
       
   675     QItemSelectionModel::SelectionFlags command = QItemSelectionModel::NoUpdate;
       
   676 
       
   677     switch  (action) {
       
   678     case SetFocus:
       
   679         view->setCurrentIndex(idx);
       
   680         return true;
       
   681     case ExtendSelection:
       
   682         if (!child)
       
   683             return false;
       
   684         view->selectionModel()->select(QItemSelection(view->currentIndex(), idx),
       
   685                     QItemSelectionModel::SelectCurrent);
       
   686         return true;
       
   687     case Select:
       
   688         command = QItemSelectionModel::ClearAndSelect;
       
   689         break;
       
   690     case ClearSelection:
       
   691         command = QItemSelectionModel::Clear;
       
   692         break;
       
   693     case RemoveSelection:
       
   694         command = QItemSelectionModel::Deselect;
       
   695         break;
       
   696     case AddToSelection:
       
   697         command = QItemSelectionModel::SelectCurrent;
       
   698         break;
       
   699     }
       
   700     if (command == QItemSelectionModel::NoUpdate)
       
   701         return false;
       
   702 
       
   703     if (child)
       
   704         view->selectionModel()->select(idx, command);
       
   705     else
       
   706         view->selectionModel()->select(rowAt(row), command);
       
   707     return true;
       
   708 }
       
   709 
       
   710 class ModelIndexIterator
       
   711 {
       
   712 public:
       
   713     ModelIndexIterator(QAbstractItemView *view, const QModelIndex &start = QModelIndex()) : m_view(view)
       
   714     {
       
   715 #ifndef QT_NO_LISTVIEW
       
   716         list = qobject_cast<QListView*>(m_view);
       
   717 #endif
       
   718 #ifndef QT_NO_TREEVIEW
       
   719         tree = qobject_cast<QTreeView*>(m_view);
       
   720 #endif
       
   721 #ifndef QT_NO_TABLEVIEW
       
   722         table = qobject_cast<QTableView*>(m_view);
       
   723 #endif
       
   724         if (start.isValid()) {
       
   725             m_current = start;
       
   726         } else if (m_view && m_view->model()) {
       
   727             m_current = view->model()->index(0, 0);
       
   728         }
       
   729     }
       
   730 
       
   731     bool next(int count = 1) {
       
   732         for (int i = 0; i < count; ++i) {
       
   733             do {
       
   734                 if (m_current.isValid()) {
       
   735                     const QAbstractItemModel *m = m_current.model();
       
   736 #ifndef QT_NO_TREEVIEW
       
   737                     if (tree && m_current.model()->hasChildren(m_current) && tree->isExpanded(m_current)) {
       
   738                         m_current = m_current.child(0, 0);
       
   739                     } else
       
   740 #endif
       
   741                     {
       
   742                         int row = m_current.row();
       
   743                         QModelIndex par = m_current.parent();
       
   744                         
       
   745                         // Go up to the parent if we reach the end of the rows
       
   746                         // If m_curent becomses invalid, stop going up.
       
   747                         while (row + 1 >= m->rowCount(par)) {
       
   748                             m_current = par;
       
   749                             if (m_current.isValid()) {
       
   750                                 row = m_current.row();
       
   751                                 par = m_current.parent();
       
   752                             } else {
       
   753                                 row = 0;
       
   754                                 par = QModelIndex();
       
   755                                 break;
       
   756                             }
       
   757                         }
       
   758 
       
   759                         if (m_current.isValid())
       
   760                             m_current = m_current.sibling(row + 1, 0);
       
   761                     }
       
   762                 }
       
   763             } while (isHidden());
       
   764         }
       
   765         return m_current.isValid();
       
   766     }
       
   767 
       
   768     bool isHidden() const {
       
   769         if (false) {
       
   770 #ifndef QT_NO_LISTVIEW
       
   771         } else if (list) {
       
   772             return list->isRowHidden(m_current.row());
       
   773 #endif
       
   774 #ifndef QT_NO_TREEVIEW
       
   775         } else if (tree) {
       
   776             return tree->isRowHidden(m_current.row(), m_current.parent());
       
   777 #endif
       
   778 #ifndef QT_NO_TABLEVIEW
       
   779         } else if (table) {
       
   780             return table->isRowHidden(m_current.row());
       
   781 #endif
       
   782         }
       
   783         return false;
       
   784     }
       
   785 
       
   786     QModelIndex current() const {
       
   787         return m_current;
       
   788     }
       
   789 
       
   790 private:
       
   791     QModelIndex m_current;
       
   792     QAbstractItemView *m_view;
       
   793 
       
   794 #ifndef QT_NO_TREEVIEW
       
   795     QTreeView *tree;
       
   796 #endif
       
   797 #ifndef QT_NO_LISTVIEW
       
   798     QListView *list;
       
   799 #endif
       
   800 #ifndef QT_NO_TABLEVIEW
       
   801     QTableView *table;
       
   802 #endif
       
   803 };
       
   804 
       
   805 QAccessibleItemView::QAccessibleItemView(QWidget *w)
       
   806     : QAccessibleAbstractScrollArea(w->objectName() == QLatin1String("qt_scrollarea_viewport") ? w->parentWidget() : w)
       
   807 {
       
   808     atVP = w->objectName() == QLatin1String("qt_scrollarea_viewport");
       
   809 
       
   810 }
       
   811 
       
   812 
       
   813 QHeaderView *QAccessibleItemView::horizontalHeader() const
       
   814 {
       
   815     QHeaderView *header = 0;
       
   816     if (false) {
       
   817 #ifndef QT_NO_TABLEVIEW
       
   818     } else if (const QTableView *tv = qobject_cast<const QTableView*>(itemView())) {
       
   819         header = tv->horizontalHeader();
       
   820 #endif
       
   821 #ifndef QT_NO_TREEVIEW
       
   822     } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(itemView())) {
       
   823         header = tv->header();
       
   824 #endif
       
   825     }
       
   826     return header;
       
   827 }
       
   828 
       
   829 QHeaderView *QAccessibleItemView::verticalHeader() const
       
   830 {
       
   831     QHeaderView *header = 0;
       
   832     if (false) {
       
   833 #ifndef QT_NO_TABLEVIEW
       
   834     } else if (const QTableView *tv = qobject_cast<const QTableView*>(itemView())) {
       
   835         header = tv->verticalHeader();
       
   836 #endif
       
   837     }
       
   838     return header;
       
   839 }
       
   840 
       
   841 
       
   842 bool QAccessibleItemView::isValidChildRole(QAccessible::Role role) const
       
   843 {
       
   844     if (atViewport()) {
       
   845         if (false) {
       
   846 #ifndef QT_NO_TREEVIEW
       
   847         } else if (qobject_cast<const QTreeView*>(itemView())) {
       
   848             return (role == TreeItem || role == Row);
       
   849 #endif
       
   850 #ifndef QT_NO_LISTVIEW
       
   851         } else if (qobject_cast<const QListView*>(itemView())) {
       
   852             return (role == ListItem);
       
   853 #endif
       
   854         }
       
   855         // TableView
       
   856         return role == Row;
       
   857     } else {
       
   858         if (false) {
       
   859 #ifndef QT_NO_TREEVIEW
       
   860         } else if (qobject_cast<const QTreeView*>(itemView())) {
       
   861             return (role == Tree);
       
   862 #endif
       
   863 #ifndef QT_NO_LISTVIEW
       
   864         } else if (qobject_cast<const QListView*>(itemView())) {
       
   865             return (role == List);
       
   866 #endif
       
   867         }
       
   868         // TableView
       
   869         return (role == Table);
       
   870     }
       
   871 }
       
   872 
       
   873 QObject *QAccessibleItemView::object() const
       
   874 {
       
   875     QObject *view = QAccessibleAbstractScrollArea::object();
       
   876     Q_ASSERT(qobject_cast<const QAbstractItemView *>(view));
       
   877     if (atViewport())
       
   878         view = qobject_cast<const QAbstractItemView *>(view)->viewport();
       
   879     return view;
       
   880 }
       
   881 
       
   882 QAbstractItemView *QAccessibleItemView::itemView() const
       
   883 {
       
   884     return qobject_cast<QAbstractItemView *>(QAccessibleAbstractScrollArea::object());
       
   885 }
       
   886 
       
   887 int QAccessibleItemView::indexOfChild(const QAccessibleInterface *iface) const
       
   888 {
       
   889     if (atViewport()) {
       
   890         if (!iface || !isValidChildRole(iface->role(0)))
       
   891             return -1;
       
   892 
       
   893         int entry = -1;
       
   894         // ### This will fail if a row is hidden.
       
   895         const QAccessibleItemRow *ifRow = static_cast<const QAccessibleItemRow *>(iface);
       
   896         if (ifRow->horizontalHeader())
       
   897             return 1;
       
   898 
       
   899         QModelIndex idx = ifRow->row;
       
   900         if (!idx.isValid())
       
   901             return -1;
       
   902 
       
   903         entry = entryFromIndex(idx);
       
   904         if (horizontalHeader())
       
   905             ++entry;
       
   906 
       
   907         return entry;
       
   908 
       
   909     } else {
       
   910         return QAccessibleAbstractScrollArea::indexOfChild(iface);
       
   911     }
       
   912 }
       
   913 
       
   914 QModelIndex QAccessibleItemView::childIndex(int child) const
       
   915 {
       
   916     if (!atViewport())
       
   917         return QModelIndex();
       
   918     ModelIndexIterator it(itemView());
       
   919     it.next(child - 1);
       
   920     return it.current();
       
   921 }
       
   922 
       
   923 int QAccessibleItemView::entryFromIndex(const QModelIndex &index) const
       
   924 {
       
   925     int entry = -1;
       
   926     if (false) {
       
   927 #ifndef QT_NO_TREEVIEW
       
   928     } else if (QTreeView *tree = qobject_cast<QTreeView*>(itemView())) {
       
   929         entry = tree->visualIndex(index) + 1;
       
   930 #endif
       
   931 #ifndef QT_NO_LISTVIEW
       
   932     } else if (QListView *list = qobject_cast<QListView*>(itemView())) {
       
   933         entry = list->visualIndex(index) + 1;
       
   934 #endif
       
   935 #ifndef QT_NO_TABLEVIEW
       
   936     } else if (QTableView *table = qobject_cast<QTableView*>(itemView())) {
       
   937         entry = table->visualIndex(index) + 1;
       
   938 #endif
       
   939     }
       
   940     return entry;
       
   941 }
       
   942 
       
   943 int QAccessibleItemView::childCount() const
       
   944 {
       
   945     if (atViewport()) {
       
   946         if (itemView()->model() == 0)
       
   947             return 0;
       
   948         QAbstractItemModel *m = itemView()->model();
       
   949         QModelIndex idx = m->index(0,0);
       
   950         if (!idx.isValid())
       
   951             return 0;
       
   952         ModelIndexIterator it(itemView());
       
   953         int count = 1;
       
   954         while (it.next()) {
       
   955             ++count;
       
   956         }
       
   957         if (horizontalHeader())
       
   958             ++count;
       
   959 
       
   960         return count;
       
   961     } else {
       
   962         return QAccessibleAbstractScrollArea::childCount();
       
   963     }
       
   964 }
       
   965 
       
   966 QString QAccessibleItemView::text(Text t, int child) const
       
   967 {
       
   968     if (atViewport()) {
       
   969         if (!child)
       
   970             return QAccessibleAbstractScrollArea::text(t, child);
       
   971 
       
   972         QAccessibleItemRow item(itemView(), childIndex(child));
       
   973         return item.text(t, 1);
       
   974     } else {
       
   975         return QAccessibleAbstractScrollArea::text(t, child);
       
   976     }
       
   977 }
       
   978 
       
   979 void QAccessibleItemView::setText(Text t, int child, const QString &text)
       
   980 {
       
   981     if (atViewport()) {
       
   982         if (!child) {
       
   983             QAccessibleAbstractScrollArea::setText(t, child, text);
       
   984             return;
       
   985         }
       
   986 
       
   987         QAccessibleItemRow item(itemView(), childIndex(child));
       
   988         item.setText(t, 1, text);
       
   989     } else {
       
   990         QAccessibleAbstractScrollArea::setText(t, child, text);
       
   991     }
       
   992 }
       
   993 
       
   994 QRect QAccessibleItemView::rect(int child) const
       
   995 {
       
   996     if (atViewport()) {
       
   997         QRect r;
       
   998         if (!child) {
       
   999             // Make sure that the rect *include* the vertical and horizontal headers, while
       
  1000             // not including the potential vertical and horizontal scrollbars.
       
  1001             QAbstractItemView *w = itemView();
       
  1002 
       
  1003             int vscrollWidth = 0;
       
  1004             const QScrollBar *sb = w->verticalScrollBar();
       
  1005             if (sb && sb->isVisible())
       
  1006                 vscrollWidth = sb->width();
       
  1007 
       
  1008             int hscrollHeight = 0;
       
  1009             sb = w->horizontalScrollBar();
       
  1010             if (sb && sb->isVisible())
       
  1011                 hscrollHeight = sb->height();
       
  1012 
       
  1013             QPoint globalPos = w->mapToGlobal(QPoint(0,0));
       
  1014             r = w->rect().translated(globalPos);
       
  1015             if (w->isRightToLeft()) {
       
  1016                 r.adjust(vscrollWidth, 0, 0, -hscrollHeight);
       
  1017             } else {
       
  1018                 r.adjust(0, 0, -vscrollWidth, -hscrollHeight);
       
  1019             }
       
  1020         } else {
       
  1021             QAccessibleInterface *iface = 0;
       
  1022             if (navigate(Child, child, &iface) == 0) {
       
  1023                 r = iface->rect(0);
       
  1024                 delete iface;
       
  1025             }
       
  1026         }
       
  1027         return r;
       
  1028     } else {
       
  1029         QRect r = QAccessibleAbstractScrollArea::rect(child);
       
  1030         if (child == 1) {
       
  1031             // include the potential vertical and horizontal headers
       
  1032 
       
  1033             const QHeaderView *header = verticalHeader();
       
  1034             int headerWidth = (header && header->isVisible()) ? header->width() : 0;
       
  1035             header = horizontalHeader();
       
  1036             int headerHeight= (header && header->isVisible()) ? header->height() : 0;
       
  1037             if (itemView()->isRightToLeft()) {
       
  1038                 r.adjust(0, -headerHeight, headerWidth, 0);
       
  1039             } else {
       
  1040                 r.adjust(-headerWidth, -headerHeight, 0, 0);
       
  1041             }
       
  1042         }
       
  1043         return r;
       
  1044     }
       
  1045 }
       
  1046 
       
  1047 int QAccessibleItemView::childAt(int x, int y) const
       
  1048 {
       
  1049     if (atViewport()) {
       
  1050         QPoint p(x, y);
       
  1051         for (int i = childCount(); i >= 0; --i) {
       
  1052             if (rect(i).contains(p))
       
  1053                 return i;
       
  1054         }
       
  1055         return -1;
       
  1056     } else {
       
  1057         return QAccessibleAbstractScrollArea::childAt(x, y);
       
  1058     }
       
  1059 }
       
  1060 
       
  1061 QAccessible::Role QAccessibleItemView::role(int child) const
       
  1062 {
       
  1063     if ((!atViewport() && child) || (atViewport() && child == 0)) {
       
  1064         QAbstractItemView *view = itemView();
       
  1065 #ifndef QT_NO_TABLEVIEW
       
  1066         if (qobject_cast<QTableView *>(view))
       
  1067             return Table;
       
  1068 #endif
       
  1069 #ifndef QT_NO_LISTVIEW
       
  1070         if (qobject_cast<QListView *>(view))
       
  1071             return List;
       
  1072 #endif
       
  1073         return Tree;
       
  1074     }
       
  1075     if (atViewport()) {
       
  1076         if (child)
       
  1077             return Row;
       
  1078     }
       
  1079 
       
  1080     return QAccessibleAbstractScrollArea::role(child);
       
  1081 }
       
  1082 
       
  1083 QAccessible::State QAccessibleItemView::state(int child) const
       
  1084 {
       
  1085     State st = Normal;
       
  1086 
       
  1087     if (itemView() == 0)
       
  1088         return State(Unavailable);
       
  1089 
       
  1090     bool queryViewPort = (atViewport() && child == 0) || (!atViewport() && child == 1);
       
  1091     if (queryViewPort) {
       
  1092         if (itemView()->selectionMode() != QAbstractItemView::NoSelection) {
       
  1093             st |= Selectable;
       
  1094             st |= Focusable;
       
  1095         }
       
  1096     } else if (atViewport()) {    // children of viewport
       
  1097         if (horizontalHeader())
       
  1098             --child;
       
  1099         if (child) {
       
  1100             QAccessibleItemRow item(itemView(), childIndex(child));
       
  1101             st |= item.state(0);
       
  1102         }
       
  1103     } else if (!atViewport() && child != 1) {
       
  1104         st = QAccessibleAbstractScrollArea::state(child);
       
  1105     }
       
  1106     return st;
       
  1107 }
       
  1108 
       
  1109 bool QAccessibleItemView::isValid() const
       
  1110 {
       
  1111     if (atViewport())
       
  1112         return QAccessibleWidgetEx::isValid();
       
  1113     else
       
  1114         return QAccessibleAbstractScrollArea::isValid();
       
  1115 }
       
  1116 
       
  1117 int QAccessibleItemView::navigate(RelationFlag relation, int index,
       
  1118                                   QAccessibleInterface **iface) const
       
  1119 {
       
  1120     if (atViewport()) {
       
  1121         if (relation == Ancestor && index == 1) {
       
  1122             *iface = new QAccessibleItemView(itemView());
       
  1123             return 0;
       
  1124         } else if (relation == Child && index >= 1) {
       
  1125             if (horizontalHeader()) {
       
  1126                 if (index == 1) {
       
  1127                     *iface = new QAccessibleItemRow(itemView(), QModelIndex(), true);
       
  1128                     return 0;
       
  1129                 }
       
  1130                 --index;
       
  1131             }
       
  1132 
       
  1133             //###JAS hidden rows..
       
  1134             QModelIndex idx = childIndex(index);
       
  1135             if (idx.isValid()) {
       
  1136                 *iface = new QAccessibleItemRow(itemView(), idx);
       
  1137                 return 0;
       
  1138             }
       
  1139         } else if (relation == Sibling && index >= 1) {
       
  1140             QAccessibleInterface *parent = new QAccessibleItemView(itemView());
       
  1141             return parent->navigate(Child, index, iface);
       
  1142         }
       
  1143         *iface = 0;
       
  1144         return -1;
       
  1145     } else {
       
  1146         return QAccessibleAbstractScrollArea::navigate(relation, index, iface);
       
  1147     }
       
  1148 }
       
  1149 
       
  1150 /* returns the model index for a given row and column */
       
  1151 QModelIndex QAccessibleItemView::index(int row, int column) const
       
  1152 {
       
  1153     return itemView()->model()->index(row, column);
       
  1154 }
       
  1155 
       
  1156 QAccessibleInterface *QAccessibleItemView::accessibleAt(int row, int column)
       
  1157 {
       
  1158     QWidget *indexWidget = itemView()->indexWidget(index(row, column));
       
  1159     return QAccessible::queryAccessibleInterface(indexWidget);
       
  1160 }
       
  1161 
       
  1162 /* We don't have a concept of a "caption" in Qt's standard widgets */
       
  1163 QAccessibleInterface *QAccessibleItemView::caption()
       
  1164 {
       
  1165     return 0;
       
  1166 }
       
  1167 
       
  1168 /* childIndex is row * columnCount + columnIndex */
       
  1169 int QAccessibleItemView::childIndex(int rowIndex, int columnIndex)
       
  1170 {
       
  1171     return rowIndex * itemView()->model()->columnCount() + columnIndex;
       
  1172 }
       
  1173 
       
  1174 /* Return the header data as column description */
       
  1175 QString QAccessibleItemView::columnDescription(int column)
       
  1176 {
       
  1177     return itemView()->model()->headerData(column, Qt::Horizontal).toString();
       
  1178 }
       
  1179 
       
  1180 /* We don't support column spanning atm */
       
  1181 int QAccessibleItemView::columnSpan(int /* row */, int /* column */)
       
  1182 {
       
  1183     return 1;
       
  1184 }
       
  1185 
       
  1186 /* Return the horizontal header view */
       
  1187 QAccessibleInterface *QAccessibleItemView::columnHeader()
       
  1188 {
       
  1189 #ifndef QT_NO_TREEVIEW
       
  1190     if (QTreeView *tree = qobject_cast<QTreeView *>(itemView()))
       
  1191         return QAccessible::queryAccessibleInterface(tree->header());
       
  1192 #endif
       
  1193 #ifndef QT_NO_TABLEVIEW
       
  1194     if (QTableView *table = qobject_cast<QTableView *>(itemView()))
       
  1195         return QAccessible::queryAccessibleInterface(table->horizontalHeader());
       
  1196 #endif
       
  1197     return 0;
       
  1198 }
       
  1199 
       
  1200 int QAccessibleItemView::columnIndex(int childIndex)
       
  1201 {
       
  1202     int columnCount = itemView()->model()->columnCount();
       
  1203     if (!columnCount)
       
  1204         return 0;
       
  1205 
       
  1206     return childIndex % columnCount;
       
  1207 }
       
  1208 
       
  1209 int QAccessibleItemView::columnCount()
       
  1210 {
       
  1211     return itemView()->model()->columnCount();
       
  1212 }
       
  1213 
       
  1214 int QAccessibleItemView::rowCount()
       
  1215 {
       
  1216     return itemView()->model()->rowCount();
       
  1217 }
       
  1218 
       
  1219 int QAccessibleItemView::selectedColumnCount()
       
  1220 {
       
  1221     return itemView()->selectionModel()->selectedColumns().count();
       
  1222 }
       
  1223 
       
  1224 int QAccessibleItemView::selectedRowCount()
       
  1225 {
       
  1226     return itemView()->selectionModel()->selectedRows().count();
       
  1227 }
       
  1228 
       
  1229 QString QAccessibleItemView::rowDescription(int row)
       
  1230 {
       
  1231     return itemView()->model()->headerData(row, Qt::Vertical).toString();
       
  1232 }
       
  1233 
       
  1234 /* We don't support row spanning */
       
  1235 int QAccessibleItemView::rowSpan(int /*row*/, int /*column*/)
       
  1236 {
       
  1237     return 1;
       
  1238 }
       
  1239 
       
  1240 QAccessibleInterface *QAccessibleItemView::rowHeader()
       
  1241 {
       
  1242 #ifndef QT_NO_TABLEVIEW
       
  1243     if (QTableView *table = qobject_cast<QTableView *>(itemView()))
       
  1244         return QAccessible::queryAccessibleInterface(table->verticalHeader());
       
  1245 #endif
       
  1246     return 0;
       
  1247 }
       
  1248 
       
  1249 int QAccessibleItemView::rowIndex(int childIndex)
       
  1250 {
       
  1251     int columnCount = itemView()->model()->columnCount();
       
  1252     if (!columnCount)
       
  1253         return 0;
       
  1254 
       
  1255     return int(childIndex / columnCount);
       
  1256 }
       
  1257 
       
  1258 int QAccessibleItemView::selectedRows(int maxRows, QList<int> *rows)
       
  1259 {
       
  1260     Q_ASSERT(rows);
       
  1261 
       
  1262     const QModelIndexList selRows = itemView()->selectionModel()->selectedRows();
       
  1263     int maxCount = qMin(selRows.count(), maxRows);
       
  1264 
       
  1265     for (int i = 0; i < maxCount; ++i)
       
  1266         rows->append(selRows.at(i).row());
       
  1267 
       
  1268     return maxCount;
       
  1269 }
       
  1270 
       
  1271 int QAccessibleItemView::selectedColumns(int maxColumns, QList<int> *columns)
       
  1272 {
       
  1273     Q_ASSERT(columns);
       
  1274 
       
  1275     const QModelIndexList selColumns = itemView()->selectionModel()->selectedColumns();
       
  1276     int maxCount = qMin(selColumns.count(), maxColumns);
       
  1277 
       
  1278     for (int i = 0; i < maxCount; ++i)
       
  1279         columns->append(selColumns.at(i).row());
       
  1280 
       
  1281     return maxCount;
       
  1282 }
       
  1283 
       
  1284 /* Qt widgets don't have a concept of a summary */
       
  1285 QAccessibleInterface *QAccessibleItemView::summary()
       
  1286 {
       
  1287     return 0;
       
  1288 }
       
  1289 
       
  1290 bool QAccessibleItemView::isColumnSelected(int column)
       
  1291 {
       
  1292     return itemView()->selectionModel()->isColumnSelected(column, QModelIndex());
       
  1293 }
       
  1294 
       
  1295 bool QAccessibleItemView::isRowSelected(int row)
       
  1296 {
       
  1297     return itemView()->selectionModel()->isRowSelected(row, QModelIndex());
       
  1298 }
       
  1299 
       
  1300 bool QAccessibleItemView::isSelected(int row, int column)
       
  1301 {
       
  1302     return itemView()->selectionModel()->isSelected(index(row, column));
       
  1303 }
       
  1304 
       
  1305 void QAccessibleItemView::selectRow(int row)
       
  1306 {
       
  1307     QItemSelectionModel *s = itemView()->selectionModel();
       
  1308     s->select(index(row, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
       
  1309 }
       
  1310 
       
  1311 void QAccessibleItemView::selectColumn(int column)
       
  1312 {
       
  1313     QItemSelectionModel *s = itemView()->selectionModel();
       
  1314     s->select(index(0, column), QItemSelectionModel::Select | QItemSelectionModel::Columns);
       
  1315 }
       
  1316 
       
  1317 void QAccessibleItemView::unselectRow(int row)
       
  1318 {
       
  1319     QItemSelectionModel *s = itemView()->selectionModel();
       
  1320     s->select(index(row, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
       
  1321 }
       
  1322 
       
  1323 void QAccessibleItemView::unselectColumn(int column)
       
  1324 {
       
  1325     QItemSelectionModel *s = itemView()->selectionModel();
       
  1326     s->select(index(0, column), QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
       
  1327 }
       
  1328 
       
  1329 void QAccessibleItemView::cellAtIndex(int index, int *row, int *column, int *rSpan,
       
  1330                                       int *cSpan, bool *isSelect)
       
  1331 {
       
  1332     *row = rowIndex(index);
       
  1333     *column = columnIndex(index);
       
  1334     *rSpan = rowSpan(*row, *column);
       
  1335     *cSpan = columnSpan(*row, *column);
       
  1336     *isSelect = isSelected(*row, *column);
       
  1337 }
       
  1338 
       
  1339 /*!
       
  1340   \class QAccessibleHeader
       
  1341   \brief The QAccessibleHeader class implements the QAccessibleInterface for header widgets.
       
  1342   \internal
       
  1343 
       
  1344   \ingroup accessibility
       
  1345 */
       
  1346 
       
  1347 /*!
       
  1348   Constructs a QAccessibleHeader object for \a w.
       
  1349 */
       
  1350 QAccessibleHeader::QAccessibleHeader(QWidget *w)
       
  1351 : QAccessibleWidgetEx(w)
       
  1352 {
       
  1353     Q_ASSERT(header());
       
  1354     addControllingSignal(QLatin1String("sectionClicked(int)"));
       
  1355 }
       
  1356 
       
  1357 /*! Returns the QHeaderView. */
       
  1358 QHeaderView *QAccessibleHeader::header() const
       
  1359 {
       
  1360     return qobject_cast<QHeaderView*>(object());
       
  1361 }
       
  1362 
       
  1363 /*! \reimp */
       
  1364 QRect QAccessibleHeader::rect(int child) const
       
  1365 {
       
  1366     if (!child)
       
  1367         return QAccessibleWidgetEx::rect(0);
       
  1368 
       
  1369     QHeaderView *h = header();
       
  1370     QPoint zero = h->mapToGlobal(QPoint(0, 0));
       
  1371     int sectionSize = h->sectionSize(child - 1);
       
  1372     int sectionPos = h->sectionPosition(child - 1);
       
  1373     return h->orientation() == Qt::Horizontal
       
  1374         ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, h->height())
       
  1375         : QRect(zero.x(), zero.y() + sectionPos, h->width(), sectionSize);
       
  1376 }
       
  1377 
       
  1378 /*! \reimp */
       
  1379 int QAccessibleHeader::childCount() const
       
  1380 {
       
  1381     return header()->count();
       
  1382 }
       
  1383 
       
  1384 /*! \reimp */
       
  1385 QString QAccessibleHeader::text(Text t, int child) const
       
  1386 {
       
  1387     QString str;
       
  1388 
       
  1389     if (child > 0 && child <= childCount()) {
       
  1390         switch (t) {
       
  1391         case Name:
       
  1392             str = header()->model()->headerData(child - 1, header()->orientation()).toString();
       
  1393             break;
       
  1394         case Description: {
       
  1395             QAccessibleEvent event(QEvent::AccessibilityDescription, child);
       
  1396             if (QApplication::sendEvent(widget(), &event))
       
  1397                 str = event.value();
       
  1398             break; }
       
  1399         case Help: {
       
  1400             QAccessibleEvent event(QEvent::AccessibilityHelp, child);
       
  1401             if (QApplication::sendEvent(widget(), &event))
       
  1402                 str = event.value();
       
  1403             break; }
       
  1404         default:
       
  1405             break;
       
  1406         }
       
  1407     }
       
  1408     if (str.isEmpty())
       
  1409         str = QAccessibleWidgetEx::text(t, child);
       
  1410     return str;
       
  1411 }
       
  1412 
       
  1413 /*! \reimp */
       
  1414 QAccessible::Role QAccessibleHeader::role(int) const
       
  1415 {
       
  1416     return (header()->orientation() == Qt::Horizontal) ? ColumnHeader : RowHeader;
       
  1417 }
       
  1418 
       
  1419 /*! \reimp */
       
  1420 QAccessible::State QAccessibleHeader::state(int child) const
       
  1421 {
       
  1422     State state = QAccessibleWidgetEx::state(child);
       
  1423 
       
  1424     if (child) {
       
  1425         int section = child - 1;
       
  1426         if (header()->isSectionHidden(section))
       
  1427             state |= Invisible;
       
  1428         if (header()->resizeMode(section) != QHeaderView::Custom)
       
  1429             state |= Sizeable;
       
  1430     } else {
       
  1431         if (header()->isMovable())
       
  1432             state |= Movable;
       
  1433     }
       
  1434     if (!header()->isClickable())
       
  1435         state |= Unavailable;
       
  1436     return state;
       
  1437 }
       
  1438 #endif // QT_NO_ITEMVIEWS
       
  1439 
       
  1440 #ifndef QT_NO_TABBAR
       
  1441 /*!
       
  1442   \class QAccessibleTabBar
       
  1443   \brief The QAccessibleTabBar class implements the QAccessibleInterface for tab bars.
       
  1444   \internal
       
  1445 
       
  1446   \ingroup accessibility
       
  1447 */
       
  1448 
       
  1449 /*!
       
  1450   Constructs a QAccessibleTabBar object for \a w.
       
  1451 */
       
  1452 QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
       
  1453 : QAccessibleWidgetEx(w)
       
  1454 {
       
  1455     Q_ASSERT(tabBar());
       
  1456 }
       
  1457 
       
  1458 /*! Returns the QTabBar. */
       
  1459 QTabBar *QAccessibleTabBar::tabBar() const
       
  1460 {
       
  1461     return qobject_cast<QTabBar*>(object());
       
  1462 }
       
  1463 
       
  1464 QAbstractButton *QAccessibleTabBar::button(int child) const
       
  1465 {
       
  1466     if (child <= tabBar()->count())
       
  1467         return 0;
       
  1468     QTabBarPrivate * const tabBarPrivate = tabBar()->d_func();
       
  1469     if (child - tabBar()->count() == 1)
       
  1470         return tabBarPrivate->leftB;
       
  1471     if (child - tabBar()->count() == 2)
       
  1472         return tabBarPrivate->rightB;
       
  1473     Q_ASSERT(false);
       
  1474     return 0;
       
  1475 }
       
  1476 
       
  1477 /*! \reimp */
       
  1478 QRect QAccessibleTabBar::rect(int child) const
       
  1479 {
       
  1480     if (!child || !tabBar()->isVisible())
       
  1481         return QAccessibleWidgetEx::rect(0);
       
  1482 
       
  1483     QPoint tp = tabBar()->mapToGlobal(QPoint(0,0));
       
  1484     QRect rec;
       
  1485     if (child <= tabBar()->count()) {
       
  1486         rec = tabBar()->tabRect(child - 1);
       
  1487     } else {
       
  1488         QWidget *widget = button(child);
       
  1489         rec = widget ? widget->geometry() : QRect();
       
  1490     }
       
  1491     return QRect(tp.x() + rec.x(), tp.y() + rec.y(), rec.width(), rec.height());
       
  1492 }
       
  1493 
       
  1494 /*! \reimp */
       
  1495 int QAccessibleTabBar::childCount() const
       
  1496 {
       
  1497     // tabs + scroll buttons
       
  1498     return tabBar()->count() + 2;
       
  1499 }
       
  1500 
       
  1501 /*! \reimp */
       
  1502 QString QAccessibleTabBar::text(Text t, int child) const
       
  1503 {
       
  1504     QString str;
       
  1505 
       
  1506     if (child > tabBar()->count()) {
       
  1507         bool left = child - tabBar()->count() == 1;
       
  1508         switch (t) {
       
  1509         case Name:
       
  1510             return left ? QTabBar::tr("Scroll Left") : QTabBar::tr("Scroll Right");
       
  1511         default:
       
  1512             break;
       
  1513         }
       
  1514     } else if (child > 0) {
       
  1515         switch (t) {
       
  1516         case Name:
       
  1517             return qt_accStripAmp(tabBar()->tabText(child - 1));
       
  1518         default:
       
  1519             break;
       
  1520         }
       
  1521     }
       
  1522 
       
  1523     if (str.isEmpty())
       
  1524         str = QAccessibleWidgetEx::text(t, child);;
       
  1525     return str;
       
  1526 }
       
  1527 
       
  1528 /*! \reimp */
       
  1529 QAccessible::Role QAccessibleTabBar::role(int child) const
       
  1530 {
       
  1531     if (!child)
       
  1532         return PageTabList;
       
  1533     if (child > tabBar()->count())
       
  1534         return PushButton;
       
  1535     return PageTab;
       
  1536 }
       
  1537 
       
  1538 /*! \reimp */
       
  1539 QAccessible::State QAccessibleTabBar::state(int child) const
       
  1540 {
       
  1541     State st = QAccessibleWidgetEx::state(0);
       
  1542 
       
  1543     if (!child)
       
  1544         return st;
       
  1545 
       
  1546     QTabBar *tb = tabBar();
       
  1547 
       
  1548     if (child > tb->count()) {
       
  1549         QWidget *bt = button(child);
       
  1550         if (!bt)
       
  1551             return st;
       
  1552         if (bt->isEnabled() == false)
       
  1553             st |= Unavailable;
       
  1554         if (bt->isVisible() == false)
       
  1555             st |= Invisible;
       
  1556         if (bt->focusPolicy() != Qt::NoFocus && bt->isActiveWindow())
       
  1557             st |= Focusable;
       
  1558         if (bt->hasFocus())
       
  1559             st |= Focused;
       
  1560         return st;
       
  1561     }
       
  1562 
       
  1563     if (!tb->isTabEnabled(child - 1))
       
  1564         st |= Unavailable;
       
  1565     else
       
  1566         st |= Selectable;
       
  1567 
       
  1568     if (!tb->currentIndex() == child - 1)
       
  1569         st |= Selected;
       
  1570 
       
  1571     return st;
       
  1572 }
       
  1573 
       
  1574 /*! \reimp */
       
  1575 bool QAccessibleTabBar::doAction(int action, int child, const QVariantList &)
       
  1576 {
       
  1577     if (!child)
       
  1578         return false;
       
  1579 
       
  1580     if (action != QAccessible::DefaultAction && action != QAccessible::Press)
       
  1581         return false;
       
  1582 
       
  1583     if (child > tabBar()->count()) {
       
  1584         QAbstractButton *bt = button(child);
       
  1585         if (!bt->isEnabled())
       
  1586             return false;
       
  1587         bt->animateClick();
       
  1588         return true;
       
  1589     }
       
  1590     if (!tabBar()->isTabEnabled(child - 1))
       
  1591         return false;
       
  1592     tabBar()->setCurrentIndex(child - 1);
       
  1593     return true;
       
  1594 }
       
  1595 
       
  1596 /*!
       
  1597     Selects the item with index \a child if \a on is true; otherwise
       
  1598     unselects it. If \a extend is true and the selection mode is not
       
  1599     \c Single and there is an existing selection, the selection is
       
  1600     extended to include all the items from the existing selection up
       
  1601     to and including the item with index \a child. Returns true if a
       
  1602     selection was made or extended; otherwise returns false.
       
  1603 
       
  1604     \sa selection() clearSelection()
       
  1605 */
       
  1606 bool QAccessibleTabBar::setSelected(int child, bool on, bool extend)
       
  1607 {
       
  1608     if (!child || !on || extend || child > tabBar()->count())
       
  1609         return false;
       
  1610 
       
  1611     if (!tabBar()->isTabEnabled(child - 1))
       
  1612         return false;
       
  1613     tabBar()->setCurrentIndex(child - 1);
       
  1614     return true;
       
  1615 }
       
  1616 
       
  1617 /*!
       
  1618     Returns a (possibly empty) list of indexes of the items selected
       
  1619     in the list box.
       
  1620 
       
  1621     \sa setSelected() clearSelection()
       
  1622 */
       
  1623 QVector<int> QAccessibleTabBar::selection() const
       
  1624 {
       
  1625     QVector<int> array;
       
  1626     if (tabBar()->currentIndex() != -1)
       
  1627         array +=tabBar()->currentIndex() + 1;
       
  1628     return array;
       
  1629 }
       
  1630 
       
  1631 #endif // QT_NO_TABBAR
       
  1632 
       
  1633 #ifndef QT_NO_COMBOBOX
       
  1634 /*!
       
  1635   \class QAccessibleComboBox
       
  1636   \brief The QAccessibleComboBox class implements the QAccessibleInterface for editable and read-only combo boxes.
       
  1637   \internal
       
  1638 
       
  1639   \ingroup accessibility
       
  1640 */
       
  1641 
       
  1642 /*!
       
  1643     \enum QAccessibleComboBox::ComboBoxElements
       
  1644 
       
  1645     \internal
       
  1646 
       
  1647     \value ComboBoxSelf
       
  1648     \value CurrentText
       
  1649     \value OpenList
       
  1650     \value PopupList
       
  1651 */
       
  1652 
       
  1653 /*!
       
  1654   Constructs a QAccessibleComboBox object for \a w.
       
  1655 */
       
  1656 QAccessibleComboBox::QAccessibleComboBox(QWidget *w)
       
  1657 : QAccessibleWidgetEx(w, ComboBox)
       
  1658 {
       
  1659     Q_ASSERT(comboBox());
       
  1660 }
       
  1661 
       
  1662 /*!
       
  1663   Returns the combobox.
       
  1664 */
       
  1665 QComboBox *QAccessibleComboBox::comboBox() const
       
  1666 {
       
  1667     return qobject_cast<QComboBox*>(object());
       
  1668 }
       
  1669 
       
  1670 /*! \reimp */
       
  1671 QRect QAccessibleComboBox::rect(int child) const
       
  1672 {
       
  1673     QPoint tp;
       
  1674     QStyle::SubControl sc;
       
  1675     QRect r;
       
  1676     switch (child) {
       
  1677     case CurrentText:
       
  1678         if (comboBox()->isEditable()) {
       
  1679             tp = comboBox()->lineEdit()->mapToGlobal(QPoint(0,0));
       
  1680             r = comboBox()->lineEdit()->rect();
       
  1681             sc = QStyle::SC_None;
       
  1682         } else  {
       
  1683             tp = comboBox()->mapToGlobal(QPoint(0,0));
       
  1684             sc = QStyle::SC_ComboBoxEditField;
       
  1685         }
       
  1686         break;
       
  1687     case OpenList:
       
  1688         tp = comboBox()->mapToGlobal(QPoint(0,0));
       
  1689         sc = QStyle::SC_ComboBoxArrow;
       
  1690         break;
       
  1691     default:
       
  1692         return QAccessibleWidgetEx::rect(child);
       
  1693     }
       
  1694 
       
  1695     if (sc != QStyle::SC_None) {
       
  1696         QStyleOptionComboBox option;
       
  1697         option.initFrom(comboBox());
       
  1698         r = comboBox()->style()->subControlRect(QStyle::CC_ComboBox, &option, sc, comboBox());
       
  1699     }
       
  1700     return QRect(tp.x() + r.x(), tp.y() + r.y(), r.width(), r.height());
       
  1701 }
       
  1702 
       
  1703 /*! \reimp */
       
  1704 int QAccessibleComboBox::navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const
       
  1705 {
       
  1706     *target = 0;
       
  1707     if (entry > ComboBoxSelf) switch (rel) {
       
  1708     case Child:
       
  1709         if (entry < PopupList)
       
  1710             return entry;
       
  1711         if (entry == PopupList) {
       
  1712             QAbstractItemView *view = comboBox()->view();
       
  1713             QWidget *parent = view ? view->parentWidget() : 0;
       
  1714             *target = QAccessible::queryAccessibleInterface(parent);
       
  1715             return *target ? 0 : -1;
       
  1716         }
       
  1717     case QAccessible::Left:
       
  1718         return entry == OpenList ? CurrentText : -1;
       
  1719     case QAccessible::Right:
       
  1720         return entry == CurrentText ? OpenList : -1;
       
  1721     case QAccessible::Up:
       
  1722         return -1;
       
  1723     case QAccessible::Down:
       
  1724         return -1;
       
  1725     default:
       
  1726         break;
       
  1727     }
       
  1728     return QAccessibleWidgetEx::navigate(rel, entry, target);
       
  1729 }
       
  1730 
       
  1731 /*! \reimp */
       
  1732 int QAccessibleComboBox::childCount() const
       
  1733 {
       
  1734     return comboBox()->view() ? PopupList : OpenList;
       
  1735 }
       
  1736 
       
  1737 /*! \reimp */
       
  1738 int QAccessibleComboBox::childAt(int x, int y) const
       
  1739 {
       
  1740     if (!comboBox()->isVisible())
       
  1741         return -1;
       
  1742     QPoint gp = widget()->mapToGlobal(QPoint(0, 0));
       
  1743     if (!QRect(gp.x(), gp.y(), widget()->width(), widget()->height()).contains(x, y))
       
  1744         return -1;
       
  1745 
       
  1746     // a complex control
       
  1747     for (int i = 1; i < PopupList; ++i) {
       
  1748         if (rect(i).contains(x, y))
       
  1749             return i;
       
  1750     }
       
  1751     return 0;
       
  1752 }
       
  1753 
       
  1754 /*! \reimp */
       
  1755 int QAccessibleComboBox::indexOfChild(const QAccessibleInterface *child) const
       
  1756 {
       
  1757     QObject *viewParent = comboBox()->view() ? comboBox()->view()->parentWidget() : 0;
       
  1758     if (child->object() == viewParent)
       
  1759         return PopupList;
       
  1760     return -1;
       
  1761 }
       
  1762 
       
  1763 /*! \reimp */
       
  1764 QString QAccessibleComboBox::text(Text t, int child) const
       
  1765 {
       
  1766     QString str;
       
  1767 
       
  1768     switch (t) {
       
  1769     case Name:
       
  1770         if (child == OpenList)
       
  1771             str = QComboBox::tr("Open");
       
  1772         else
       
  1773             str = QAccessibleWidgetEx::text(t, 0);
       
  1774         break;
       
  1775 #ifndef QT_NO_SHORTCUT
       
  1776     case Accelerator:
       
  1777         if (child == OpenList)
       
  1778             str = (QString)QKeySequence(Qt::Key_Down);
       
  1779         // missing break?
       
  1780 #endif
       
  1781     case Value:
       
  1782         if (comboBox()->isEditable())
       
  1783             str = comboBox()->lineEdit()->text();
       
  1784         else
       
  1785             str = comboBox()->currentText();
       
  1786         break;
       
  1787     default:
       
  1788         break;
       
  1789     }
       
  1790     if (str.isEmpty())
       
  1791         str = QAccessibleWidgetEx::text(t, 0);
       
  1792     return str;
       
  1793 }
       
  1794 
       
  1795 /*! \reimp */
       
  1796 QAccessible::Role QAccessibleComboBox::role(int child) const
       
  1797 {
       
  1798     switch (child) {
       
  1799     case CurrentText:
       
  1800         if (comboBox()->isEditable())
       
  1801             return EditableText;
       
  1802         return StaticText;
       
  1803     case OpenList:
       
  1804         return PushButton;
       
  1805     case PopupList:
       
  1806         return List;
       
  1807     default:
       
  1808         return ComboBox;
       
  1809     }
       
  1810 }
       
  1811 
       
  1812 /*! \reimp */
       
  1813 QAccessible::State QAccessibleComboBox::state(int /*child*/) const
       
  1814 {
       
  1815     return QAccessibleWidgetEx::state(0);
       
  1816 }
       
  1817 
       
  1818 /*! \reimp */
       
  1819 bool QAccessibleComboBox::doAction(int action, int child, const QVariantList &)
       
  1820 {
       
  1821     if (child == 2 && (action == DefaultAction || action == Press)) {
       
  1822         if (comboBox()->view()->isVisible()) {
       
  1823             comboBox()->hidePopup();
       
  1824         } else {
       
  1825             comboBox()->showPopup();
       
  1826         }
       
  1827         return true;
       
  1828     }
       
  1829     return false;
       
  1830 }
       
  1831 
       
  1832 QString QAccessibleComboBox::actionText(int action, Text t, int child) const
       
  1833 {
       
  1834     QString text;
       
  1835     if (child == 2 && t == Name && (action == DefaultAction || action == Press))
       
  1836         text = comboBox()->view()->isVisible() ? QComboBox::tr("Close") : QComboBox::tr("Open");
       
  1837     return text;
       
  1838 }
       
  1839 #endif // QT_NO_COMBOBOX
       
  1840 
       
  1841 static inline void removeInvisibleWidgetsFromList(QWidgetList *list)
       
  1842 {
       
  1843     if (!list || list->isEmpty())
       
  1844         return;
       
  1845 
       
  1846     for (int i = 0; i < list->count(); ++i) {
       
  1847         QWidget *widget = list->at(i);
       
  1848         if (!widget->isVisible())
       
  1849             list->removeAt(i);
       
  1850     }
       
  1851 }
       
  1852 
       
  1853 #ifndef QT_NO_SCROLLAREA
       
  1854 // ======================= QAccessibleAbstractScrollArea =======================
       
  1855 QAccessibleAbstractScrollArea::QAccessibleAbstractScrollArea(QWidget *widget)
       
  1856     : QAccessibleWidgetEx(widget, Client)
       
  1857 {
       
  1858     Q_ASSERT(qobject_cast<QAbstractScrollArea *>(widget));
       
  1859 }
       
  1860 
       
  1861 QString QAccessibleAbstractScrollArea::text(Text textType, int child) const
       
  1862 {
       
  1863     if (child == Self)
       
  1864         return QAccessibleWidgetEx::text(textType, 0);
       
  1865     QWidgetList children = accessibleChildren();
       
  1866     if (child < 1 || child > children.count())
       
  1867         return QString();
       
  1868     QAccessibleInterface *childInterface = queryAccessibleInterface(children.at(child - 1));
       
  1869     if (!childInterface)
       
  1870         return QString();
       
  1871     QString string = childInterface->text(textType, 0);
       
  1872     delete childInterface;
       
  1873     return string;
       
  1874 }
       
  1875 
       
  1876 void QAccessibleAbstractScrollArea::setText(Text textType, int child, const QString &text)
       
  1877 {
       
  1878     if (text.isEmpty())
       
  1879         return;
       
  1880     if (child == 0) {
       
  1881         QAccessibleWidgetEx::setText(textType, 0, text);
       
  1882         return;
       
  1883     }
       
  1884     QWidgetList children = accessibleChildren();
       
  1885     if (child < 1 || child > children.count())
       
  1886         return;
       
  1887     QAccessibleInterface *childInterface = queryAccessibleInterface(children.at(child - 1));
       
  1888     if (!childInterface)
       
  1889         return;
       
  1890     childInterface->setText(textType, 0, text);
       
  1891     delete childInterface;
       
  1892 }
       
  1893 
       
  1894 QAccessible::State QAccessibleAbstractScrollArea::state(int child) const
       
  1895 {
       
  1896     if (child == Self)
       
  1897         return QAccessibleWidgetEx::state(child);
       
  1898     QWidgetList children = accessibleChildren();
       
  1899     if (child < 1 || child > children.count())
       
  1900         return QAccessibleWidgetEx::state(Self);
       
  1901     QAccessibleInterface *childInterface = queryAccessibleInterface(children.at(child - 1));
       
  1902     if (!childInterface)
       
  1903         return QAccessibleWidgetEx::state(Self);
       
  1904     QAccessible::State returnState = childInterface->state(0);
       
  1905     delete childInterface;
       
  1906     return returnState;
       
  1907 }
       
  1908 
       
  1909 QVariant QAccessibleAbstractScrollArea::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
       
  1910 {
       
  1911     return QVariant();
       
  1912 }
       
  1913 
       
  1914 int QAccessibleAbstractScrollArea::childCount() const
       
  1915 {
       
  1916     return accessibleChildren().count();
       
  1917 }
       
  1918 
       
  1919 int QAccessibleAbstractScrollArea::indexOfChild(const QAccessibleInterface *child) const
       
  1920 {
       
  1921     if (!child || !child->object())
       
  1922         return -1;
       
  1923     int index = accessibleChildren().indexOf(qobject_cast<QWidget *>(child->object()));
       
  1924     if (index >= 0)
       
  1925         return ++index;
       
  1926     return -1;
       
  1927 }
       
  1928 
       
  1929 bool QAccessibleAbstractScrollArea::isValid() const
       
  1930 {
       
  1931     return (QAccessibleWidgetEx::isValid() && abstractScrollArea() && abstractScrollArea()->viewport());
       
  1932 }
       
  1933 
       
  1934 int QAccessibleAbstractScrollArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
       
  1935 {
       
  1936     if (!target)
       
  1937         return -1;
       
  1938 
       
  1939     *target = 0;
       
  1940 
       
  1941     QWidget *targetWidget = 0;
       
  1942     QWidget *entryWidget = 0;
       
  1943 
       
  1944     if (relation == Child ||
       
  1945         relation == Left || relation == Up || relation == Right || relation == Down) {
       
  1946         QWidgetList children = accessibleChildren();
       
  1947         if (entry < 0 || entry > children.count())
       
  1948             return -1;
       
  1949 
       
  1950         if (entry == Self)
       
  1951             entryWidget = abstractScrollArea();
       
  1952         else
       
  1953             entryWidget = children.at(entry - 1);
       
  1954         AbstractScrollAreaElement entryElement = elementType(entryWidget);
       
  1955 
       
  1956         // Not one of the most beautiful switches I've ever seen, but I believe it has
       
  1957         // to be like this since each case need special handling.
       
  1958         // It might be possible to make it more general, but I'll leave that as an exercise
       
  1959         // to the reader. :-)
       
  1960         switch (relation) {
       
  1961         case Child:
       
  1962             if (entry > 0)
       
  1963                 targetWidget = children.at(entry - 1);
       
  1964             break;
       
  1965         case Left:
       
  1966             if (entry < 1)
       
  1967                 break;
       
  1968             switch (entryElement) {
       
  1969             case Viewport:
       
  1970                 if (!isLeftToRight())
       
  1971                     targetWidget = abstractScrollArea()->verticalScrollBar();
       
  1972                 break;
       
  1973             case HorizontalContainer:
       
  1974                 if (!isLeftToRight())
       
  1975                     targetWidget = abstractScrollArea()->cornerWidget();
       
  1976                 break;
       
  1977             case VerticalContainer:
       
  1978                 if (isLeftToRight())
       
  1979                     targetWidget = abstractScrollArea()->viewport();
       
  1980                 break;
       
  1981             case CornerWidget:
       
  1982                 if (isLeftToRight())
       
  1983                     targetWidget = abstractScrollArea()->horizontalScrollBar();
       
  1984                 break;
       
  1985             default:
       
  1986                 break;
       
  1987             }
       
  1988             break;
       
  1989         case Right:
       
  1990             if (entry < 1)
       
  1991                 break;
       
  1992             switch (entryElement) {
       
  1993             case Viewport:
       
  1994                 if (isLeftToRight())
       
  1995                     targetWidget = abstractScrollArea()->verticalScrollBar();
       
  1996                 break;
       
  1997             case HorizontalContainer:
       
  1998                 targetWidget = abstractScrollArea()->cornerWidget();
       
  1999                 break;
       
  2000             case VerticalContainer:
       
  2001                 if (!isLeftToRight())
       
  2002                     targetWidget = abstractScrollArea()->viewport();
       
  2003                 break;
       
  2004             case CornerWidget:
       
  2005                 if (!isLeftToRight())
       
  2006                     targetWidget = abstractScrollArea()->horizontalScrollBar();
       
  2007                 break;
       
  2008             default:
       
  2009                 break;
       
  2010             }
       
  2011             break;
       
  2012         case Up:
       
  2013             if (entry < 1)
       
  2014                 break;
       
  2015             switch (entryElement) {
       
  2016             case HorizontalContainer:
       
  2017                 targetWidget = abstractScrollArea()->viewport();
       
  2018                 break;
       
  2019             case CornerWidget:
       
  2020                 targetWidget = abstractScrollArea()->verticalScrollBar();
       
  2021                 break;
       
  2022             default:
       
  2023                 break;
       
  2024             }
       
  2025             break;
       
  2026         case Down:
       
  2027             if (entry < 1)
       
  2028                 break;
       
  2029             switch (entryElement) {
       
  2030             case Viewport:
       
  2031                 targetWidget = abstractScrollArea()->horizontalScrollBar();
       
  2032                 break;
       
  2033             case VerticalContainer:
       
  2034                 targetWidget = abstractScrollArea()->cornerWidget();
       
  2035                 break;
       
  2036             default:
       
  2037                 break;
       
  2038             }
       
  2039             break;
       
  2040         default:
       
  2041             break;
       
  2042         }
       
  2043     } else {
       
  2044         return QAccessibleWidgetEx::navigate(relation, entry, target);
       
  2045     }
       
  2046 
       
  2047     if (qobject_cast<const QScrollBar *>(targetWidget))
       
  2048         targetWidget = targetWidget->parentWidget();
       
  2049     *target = QAccessible::queryAccessibleInterface(targetWidget);
       
  2050     return *target ? 0: -1;
       
  2051 }
       
  2052 
       
  2053 QRect QAccessibleAbstractScrollArea::rect(int child) const
       
  2054 {
       
  2055     if (!abstractScrollArea()->isVisible())
       
  2056         return QRect();
       
  2057     if (child == Self)
       
  2058         return QAccessibleWidgetEx::rect(child);
       
  2059     QWidgetList children = accessibleChildren();
       
  2060     if (child < 1 || child > children.count())
       
  2061         return QRect();
       
  2062     const QWidget *childWidget = children.at(child - 1);
       
  2063     if (!childWidget->isVisible())
       
  2064         return QRect();
       
  2065     return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
       
  2066 }
       
  2067 
       
  2068 int QAccessibleAbstractScrollArea::childAt(int x, int y) const
       
  2069 {
       
  2070     if (!abstractScrollArea()->isVisible())
       
  2071         return -1;
       
  2072 #if 0
       
  2073     const QRect globalSelfGeometry = rect(Self);
       
  2074     if (!globalSelfGeometry.isValid() || !globalSelfGeometry.contains(QPoint(x, y)))
       
  2075         return -1;
       
  2076     const QWidgetList children = accessibleChildren();
       
  2077     for (int i = 0; i < children.count(); ++i) {
       
  2078         const QWidget *child = children.at(i);
       
  2079         const QRect globalChildGeometry = QRect(child->mapToGlobal(QPoint(0, 0)), child->size());
       
  2080         if (globalChildGeometry.contains(QPoint(x, y))) {
       
  2081             return ++i;
       
  2082         }
       
  2083     }
       
  2084     return 0;
       
  2085 #else
       
  2086     for (int i = childCount(); i >= 0; --i) {
       
  2087         if (rect(i).contains(x, y))
       
  2088             return i;
       
  2089     }
       
  2090     return -1;
       
  2091 #endif
       
  2092 }
       
  2093 
       
  2094 QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea() const
       
  2095 {
       
  2096     return static_cast<QAbstractScrollArea *>(object());
       
  2097 }
       
  2098 
       
  2099 QWidgetList QAccessibleAbstractScrollArea::accessibleChildren() const
       
  2100 {
       
  2101     QWidgetList children;
       
  2102 
       
  2103     // Viewport.
       
  2104     QWidget * viewport = abstractScrollArea()->viewport();
       
  2105     if (viewport)
       
  2106         children.append(viewport);
       
  2107 
       
  2108     // Horizontal scrollBar container.
       
  2109     QScrollBar *horizontalScrollBar = abstractScrollArea()->horizontalScrollBar();
       
  2110     if (horizontalScrollBar && horizontalScrollBar->isVisible()) {
       
  2111         children.append(horizontalScrollBar->parentWidget());
       
  2112     }
       
  2113 
       
  2114     // Vertical scrollBar container.
       
  2115     QScrollBar *verticalScrollBar = abstractScrollArea()->verticalScrollBar();
       
  2116     if (verticalScrollBar && verticalScrollBar->isVisible()) {
       
  2117         children.append(verticalScrollBar->parentWidget());
       
  2118     }
       
  2119 
       
  2120     // CornerWidget.
       
  2121     QWidget *cornerWidget = abstractScrollArea()->cornerWidget();
       
  2122     if (cornerWidget && cornerWidget->isVisible())
       
  2123         children.append(cornerWidget);
       
  2124 
       
  2125     return children;
       
  2126 }
       
  2127 
       
  2128 QAccessibleAbstractScrollArea::AbstractScrollAreaElement
       
  2129 QAccessibleAbstractScrollArea::elementType(QWidget *widget) const
       
  2130 {
       
  2131     if (!widget)
       
  2132         return Undefined;
       
  2133 
       
  2134     if (widget == abstractScrollArea())
       
  2135         return Self;
       
  2136     if (widget == abstractScrollArea()->viewport())
       
  2137         return Viewport;
       
  2138     if (widget->objectName() == QLatin1String("qt_scrollarea_hcontainer"))
       
  2139         return HorizontalContainer;
       
  2140     if (widget->objectName() == QLatin1String("qt_scrollarea_vcontainer"))
       
  2141         return VerticalContainer;
       
  2142     if (widget == abstractScrollArea()->cornerWidget())
       
  2143         return CornerWidget;
       
  2144 
       
  2145     return Undefined;
       
  2146 }
       
  2147 
       
  2148 bool QAccessibleAbstractScrollArea::isLeftToRight() const
       
  2149 {
       
  2150     return abstractScrollArea()->isLeftToRight();
       
  2151 }
       
  2152 
       
  2153 // ======================= QAccessibleScrollArea ===========================
       
  2154 QAccessibleScrollArea::QAccessibleScrollArea(QWidget *widget)
       
  2155     : QAccessibleAbstractScrollArea(widget)
       
  2156 {
       
  2157     Q_ASSERT(qobject_cast<QScrollArea *>(widget));
       
  2158 }
       
  2159 #endif // QT_NO_SCROLLAREA
       
  2160 
       
  2161 QT_END_NAMESPACE
       
  2162 
       
  2163 #endif // QT_NO_ACCESSIBILITY