Simplify QAccessibleTextEdit.
authorFrederik Gladhorn <frederik.gladhorn@nokia.com>
Tue, 27 Sep 2011 12:28:19 +0000 (14:28 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 28 Sep 2011 01:17:28 +0000 (03:17 +0200)
Before the text edit tried to represent each line of text as a child
of itself. With the editable text interface this is no longer needed.

Change-Id: If9927e522f955e863e91fd0a529a1ce6fafaddc3
Reviewed-on: http://codereview.qt-project.org/5624
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>
src/plugins/accessible/widgets/qaccessiblewidgets.cpp
src/plugins/accessible/widgets/qaccessiblewidgets.h
tests/auto/qaccessibility/tst_qaccessibility.cpp

index d811f97..9b3d37f 100644 (file)
@@ -254,7 +254,6 @@ QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
 : QAccessibleWidget(o, EditableText)
 {
     Q_ASSERT(widget()->inherits("QTextEdit"));
-    childOffset = QAccessibleWidget::childCount();
 }
 
 /*! Returns the text edit. */
@@ -263,96 +262,37 @@ QTextEdit *QAccessibleTextEdit::textEdit() const
     return static_cast<QTextEdit *>(widget());
 }
 
-QRect QAccessibleTextEdit::rect(int child) const
-{
-    if (child <= childOffset)
-        return QAccessibleWidget::rect(child);
-
-     QTextEdit *edit = textEdit();
-     QTextBlock block = qTextBlockAt(edit->document(), child - childOffset - 1);
-     if (!block.isValid())
-         return QRect();
-
-     QRect rect = edit->document()->documentLayout()->blockBoundingRect(block).toRect();
-     rect.translate(-edit->horizontalScrollBar()->value(), -edit->verticalScrollBar()->value());
-
-     rect = edit->viewport()->rect().intersect(rect);
-     if (rect.isEmpty())
-         return QRect();
-
-     return rect.translated(edit->viewport()->mapToGlobal(QPoint(0, 0)));
-}
-
-int QAccessibleTextEdit::childAt(int x, int y) const
-{
-    QTextEdit *edit = textEdit();
-    if (!edit->isVisible())
-        return -1;
-
-    QPoint point = edit->viewport()->mapFromGlobal(QPoint(x, y));
-    QTextBlock block = edit->cursorForPosition(point).block();
-    if (block.isValid())
-        return qTextBlockPosition(block) + childOffset;
-
-    return QAccessibleWidget::childAt(x, y);
-}
-
 /*! \reimp */
-QString QAccessibleTextEdit::text(Text t, int child) const
+QString QAccessibleTextEdit::text(Text t, int) const
 {
-    if (t == Value) {
-        if (child > childOffset)
-            return qTextBlockAt(textEdit()->document(), child - childOffset - 1).text();
-        if (!child)
-            return textEdit()->toPlainText();
-    }
+    if (t == Value)
+        return textEdit()->toPlainText();
 
-    return QAccessibleWidget::text(t, child);
+    return QAccessibleWidget::text(t, 0);
 }
 
 /*! \reimp */
-void QAccessibleTextEdit::setText(Text t, int child, const QString &text)
+void QAccessibleTextEdit::setText(Text t, int, const QString &text)
 {
-    if (t != Value || (child > 0 && child <= childOffset)) {
-        QAccessibleWidget::setText(t, child, text);
+    if (t != Value) {
+        QAccessibleWidget::setText(t, 0, text);
         return;
     }
     if (textEdit()->isReadOnly())
         return;
 
-    if (!child) {
-        textEdit()->setText(text);
-        return;
-    }
-    QTextBlock block = qTextBlockAt(textEdit()->document(), child - childOffset - 1);
-    if (!block.isValid())
-        return;
-
-    QTextCursor cursor(block);
-    cursor.select(QTextCursor::BlockUnderCursor);
-    cursor.insertText(text);
-}
-
-/*! \reimp */
-QAccessible::Role QAccessibleTextEdit::role(int child) const
-{
-    if (child > childOffset)
-        return EditableText;
-    return QAccessibleWidget::role(child);
+    textEdit()->setText(text);
 }
 
-QVariant QAccessibleTextEdit::invokeMethod(QAccessible::Method method, int child,
+QVariant QAccessibleTextEdit::invokeMethod(QAccessible::Method method, int,
                                                      const QVariantList &params)
 {
-    if (child)
-        return QVariant();
-
     switch (method) {
     case ListSupportedMethods: {
         QSet<QAccessible::Method> set;
         set << ListSupportedMethods << SetCursorPosition << GetCursorPosition;
         return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >(
-                    QAccessibleWidget::invokeMethod(method, child, params)));
+                    QAccessibleWidget::invokeMethod(method, 0, params)));
     }
     case SetCursorPosition:
         setCursorPosition(params.value(0).toInt());
@@ -360,1369 +300,1361 @@ QVariant QAccessibleTextEdit::invokeMethod(QAccessible::Method method, int child
     case GetCursorPosition:
         return textEdit()->textCursor().position();
     default:
-        return QAccessibleWidget::invokeMethod(method, child, params);
+        return QAccessibleWidget::invokeMethod(method, 0, params);
     }
 }
 
-int QAccessibleTextEdit::childCount() const
+void QAccessibleTextEdit::addSelection(int startOffset, int endOffset)
 {
-    return childOffset + textEdit()->document()->blockCount();
+    setSelection(0, startOffset, endOffset);
 }
-#endif // QT_NO_TEXTEDIT
 
-#ifndef QT_NO_STACKEDWIDGET
-// ======================= QAccessibleStackedWidget ======================
-QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
-    : QAccessibleWidget(widget, LayeredPane)
+QString QAccessibleTextEdit::attributes(int offset, int *startOffset, int *endOffset)
 {
-    Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
-}
+    /* The list of attributes can be found at:
+     http://linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes
+    */
 
-QVariant QAccessibleStackedWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
-{
-    return QVariant();
-}
+    if (offset >= characterCount()) {
+        *startOffset = -1;
+        *endOffset = -1;
+        return QString();
+    }
 
+    QMap<QString, QString> attrs;
 
-int QAccessibleStackedWidget::childAt(int x, int y) const
-{
-    if (!stackedWidget()->isVisible())
-        return -1;
-    QWidget *currentWidget = stackedWidget()->currentWidget();
-    if (!currentWidget)
-        return -1;
-    QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
-    if (currentWidget->rect().contains(position))
-        return 1;
-    return -1;
-}
+    QTextCursor cursor = textEdit()->textCursor();
 
-int QAccessibleStackedWidget::childCount() const
-{
-    return stackedWidget()->count();
-}
+    //cursor.charFormat returns the format of the previous character
+    cursor.setPosition(offset + 1);
+    QTextCharFormat charFormat = cursor.charFormat();
 
-int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
-{
-    if (!child)
-        return -1;
+    cursor.setPosition(offset);
+    QTextBlockFormat blockFormat = cursor.blockFormat();
 
-    QWidget* widget = qobject_cast<QWidget*>(child->object());
-    int index = stackedWidget()->indexOf(widget);
-    if (index >= 0) // one based counting of children
-        return index + 1;
-    return -1;
-}
+    QTextCharFormat charFormatComp;
+    QTextBlockFormat blockFormatComp;
 
-QAccessibleInterface *QAccessibleStackedWidget::child(int index) const
-{
-    if (index < 0 || index >= stackedWidget()->count())
-        return 0;
-    return QAccessible::queryAccessibleInterface(stackedWidget()->widget(index));
-}
+    *startOffset = offset;
+    cursor.setPosition(*startOffset);
+    while (*startOffset > 0) {
+        charFormatComp = cursor.charFormat();
+        cursor.setPosition(*startOffset - 1);
+        blockFormatComp = cursor.blockFormat();
+        if ((charFormat == charFormatComp) && (blockFormat == blockFormatComp))
+            (*startOffset)--;
+        else
+            break;
+    }
 
-int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
-{
-    switch (relation) {
-    case Child:
-        *target = child(entry - 1);
-        return *target ? 0 : -1;
-    default:
-        return QAccessibleWidget::navigate(relation, entry, target);
+    int limit = characterCount() + 1;
+    *endOffset = offset + 1;
+    cursor.setPosition(*endOffset);
+    while (*endOffset < limit) {
+        blockFormatComp = cursor.blockFormat();
+        cursor.setPosition(*endOffset + 1);
+        charFormatComp = cursor.charFormat();
+        if ((charFormat == charFormatComp) && (cursor.blockFormat() == blockFormatComp))
+            (*endOffset)++;
+        else
+            break;
     }
-}
 
-QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
-{
-    return static_cast<QStackedWidget *>(object());
-}
-#endif // QT_NO_STACKEDWIDGET
+    QString family = charFormat.fontFamily();
+    if (!family.isEmpty()) {
+        family = family.replace('\\',"\\\\");
+        family = family.replace(':',"\\:");
+        family = family.replace(',',"\\,");
+        family = family.replace('=',"\\=");
+        family = family.replace(';',"\\;");
+        family = family.replace('\"',"\\\"");
+        attrs["font-family"] = '"'+family+'"';
+    }
 
-#ifndef QT_NO_TOOLBOX
-// ======================= QAccessibleToolBox ======================
-QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
-    : QAccessibleWidget(widget, LayeredPane)
-{
-    Q_ASSERT(qobject_cast<QToolBox *>(widget));
+    int fontSize = int(charFormat.fontPointSize());
+    if (fontSize)
+        attrs["font-size"] = QString::number(fontSize).append("pt");
+
+    //Different weight values are not handled
+    attrs["font-weight"] = (charFormat.fontWeight() > QFont::Normal) ? "bold" : "normal";
+
+    QFont::Style style = charFormat.font().style();
+    attrs["font-style"] = (style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal");
+
+    attrs["text-underline-style"] = charFormat.font().underline() ? "solid" : "none";
+
+    QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
+    attrs["text-position"] = (alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" );
+
+    QBrush background = charFormat.background();
+    if (background.style() == Qt::SolidPattern) {
+        attrs["background-color"] = QString("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
+    }
+
+    QBrush foreground = charFormat.foreground();
+    if (foreground.style() == Qt::SolidPattern) {
+        attrs["color"] = QString("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
+    }
+
+    switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
+    case Qt::AlignLeft:
+        attrs["text-align"] = "left";
+        break;
+    case Qt::AlignRight:
+        attrs["text-align"] = "right";
+        break;
+    case Qt::AlignHCenter:
+        attrs["text-align"] = "center";
+        break;
+    case Qt::AlignJustify:
+        attrs["text-align"] = "left";
+        break;
+    }
+
+    QString result;
+    foreach (const QString &attributeName, attrs.keys()) {
+        result.append(attributeName).append(':').append(attrs[attributeName]).append(';');
+    }
+
+    return result;
 }
 
-QString QAccessibleToolBox::text(Text textType, int child) const
+int QAccessibleTextEdit::cursorPosition()
 {
-    if (textType != Value || child <= 0 || child > toolBox()->count())
-        return QAccessibleWidget::text(textType, child);
-    return toolBox()->itemText(child - 1);
+    return textEdit()->textCursor().position();
 }
 
-void QAccessibleToolBox::setText(Text textType, int child, const QString &text)
+QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
 {
-    if (textType != Value || child <= 0 || child > toolBox()->count()) {
-        QAccessibleWidget::setText(textType, child, text);
-        return;
+    QTextEdit *edit = textEdit();
+    QTextCursor cursor(edit->document());
+    cursor.setPosition(offset);
+
+    if (cursor.position() != offset)
+        return QRect();
+
+    QRect r = edit->cursorRect(cursor);
+    if (cursor.movePosition(QTextCursor::NextCharacter)) {
+        r.setWidth(edit->cursorRect(cursor).x() - r.x());
+    } else {
+        // we don't know the width of the character - maybe because we're at document end
+        // in that case, IAccessible2 tells us to return the width of a default character
+        int averageCharWidth = QFontMetrics(cursor.charFormat().font()).averageCharWidth();
+        if (edit->layoutDirection() == Qt::RightToLeft)
+            averageCharWidth *= -1;
+        r.setWidth(averageCharWidth);
     }
-    toolBox()->setItemText(child - 1, text);
-}
 
-QAccessible::State QAccessibleToolBox::state(int child) const
-{
-    QWidget *childWidget = toolBox()->widget(child - 1);
-    if (!childWidget)
-        return QAccessibleWidget::state(child);
-    QAccessible::State childState = QAccessible::Normal;
-    if (toolBox()->currentWidget() == childWidget)
-        childState |= QAccessible::Expanded;
-    else
-        childState |= QAccessible::Collapsed;
-    return childState;
+    switch (coordType) {
+    case RelativeToScreen:
+        r.moveTo(edit->viewport()->mapToGlobal(r.topLeft()));
+        break;
+    case RelativeToParent:
+        break;
+    }
+
+    return r;
 }
 
-QVariant QAccessibleToolBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
+int QAccessibleTextEdit::selectionCount()
 {
-    return QVariant();
+    return textEdit()->textCursor().hasSelection() ? 1 : 0;
 }
 
-int QAccessibleToolBox::childCount() const
+int QAccessibleTextEdit::offsetAtPoint(const QPoint &point, CoordinateType coordType)
 {
-    return toolBox()->count();
+    QTextEdit *edit = textEdit();
+
+    QPoint p = point;
+    if (coordType == RelativeToScreen)
+        p = edit->viewport()->mapFromGlobal(p);
+    // convert to document coordinates
+    p += QPoint(edit->horizontalScrollBar()->value(), edit->verticalScrollBar()->value());
+
+    return edit->document()->documentLayout()->hitTest(p, Qt::ExactHit);
 }
 
-int QAccessibleToolBox::indexOfChild(const QAccessibleInterface *child) const
+void QAccessibleTextEdit::selection(int selectionIndex, int *startOffset, int *endOffset)
 {
-    if (!child)
-        return -1;
-    QWidget *childWidget = qobject_cast<QWidget *>(child->object());
-    if (!childWidget)
-        return -1;
-    int index = toolBox()->indexOf(childWidget);
-    if (index != -1)
-        ++index;
-    return index;
-}
+    *startOffset = *endOffset = 0;
+    QTextCursor cursor = textEdit()->textCursor();
 
-int QAccessibleToolBox::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
-{
-    *target = 0;
-    if (entry <= 0 || entry > toolBox()->count())
-        return QAccessibleWidget::navigate(relation, entry, target);
-    int index = -1;
-    if (relation == QAccessible::Up)
-        index = entry - 2;
-    else if (relation == QAccessible::Down)
-        index = entry;
-    *target = QAccessible::queryAccessibleInterface(toolBox()->widget(index));
-    return *target ? 0: -1;
-}
+    if (selectionIndex != 0 || !cursor.hasSelection())
+        return;
 
-QToolBox * QAccessibleToolBox::toolBox() const
-{
-    return static_cast<QToolBox *>(object());
+    *startOffset = cursor.selectionStart();
+    *endOffset = cursor.selectionEnd();
 }
-#endif // QT_NO_TOOLBOX
 
-// ======================= QAccessibleMdiArea ======================
-#ifndef QT_NO_MDIAREA
-QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
-    : QAccessibleWidget(widget, LayeredPane)
+QString QAccessibleTextEdit::text(int startOffset, int endOffset)
 {
-    Q_ASSERT(qobject_cast<QMdiArea *>(widget));
-}
+    QTextCursor cursor(textEdit()->document());
 
-QAccessible::State QAccessibleMdiArea::state(int child) const
-{
-    if (child < 0)
-        return QAccessibleWidget::state(child);
-    if (child == 0)
-        return QAccessible::Normal;
-    QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
-    if (subWindows.isEmpty() || child > subWindows.count())
-        return QAccessibleWidget::state(child);
-    if (subWindows.at(child - 1) == mdiArea()->activeSubWindow())
-        return QAccessible::Focused;
-    return QAccessible::Normal;
-}
+    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
 
-QVariant QAccessibleMdiArea::invokeMethod(QAccessible::Method, int, const QVariantList &)
-{
-    return QVariant();
+    return cursor.selectedText();
 }
 
-int QAccessibleMdiArea::childCount() const
+QString QAccessibleTextEdit::textBeforeOffset (int offset, BoundaryType boundaryType,
+        int *startOffset, int *endOffset)
 {
-    return mdiArea()->subWindowList().count();
+    // TODO - what exactly is before?
+    Q_UNUSED(offset);
+    Q_UNUSED(boundaryType);
+    Q_UNUSED(startOffset);
+    Q_UNUSED(endOffset);
+    return QString();
 }
 
-int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
+QString QAccessibleTextEdit::textAfterOffset(int offset, BoundaryType boundaryType,
+        int *startOffset, int *endOffset)
 {
-    if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
-        return -1;
-    if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
-        int index = mdiArea()->subWindowList().indexOf(window);
-        if (index != -1)
-            return ++index;
-    }
-    return -1;
+    // TODO - what exactly is after?
+    Q_UNUSED(offset);
+    Q_UNUSED(boundaryType);
+    Q_UNUSED(startOffset);
+    Q_UNUSED(endOffset);
+    return QString();
 }
 
-int QAccessibleMdiArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
+QString QAccessibleTextEdit::textAtOffset(int offset, BoundaryType boundaryType,
+                                          int *startOffset, int *endOffset)
 {
-    *target = 0;
-    QWidget *targetObject = 0;
-    QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
-    switch (relation) {
-    case Child:
-        if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
-            return -1;
-        targetObject = subWindows.at(entry - 1);
+    Q_ASSERT(startOffset);
+    Q_ASSERT(endOffset);
+
+    *startOffset = *endOffset = -1;
+    QTextEdit *edit = textEdit();
+
+    QTextCursor cursor(edit->document());
+    if (offset >= characterCount())
+        return QString();
+
+    cursor.setPosition(offset);
+    switch (boundaryType) {
+    case CharBoundary:
+        *startOffset = cursor.position();
+        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+        *endOffset = cursor.position();
         break;
-    case Up:
-    case Down:
-    case Left:
-    case Right:
-        targetObject = mdiAreaNavigate(mdiArea(), relation, entry);
+    case WordBoundary:
+        cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
+        *startOffset = cursor.position();
+        cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+        *endOffset = cursor.position();
+        break;
+    case SentenceBoundary:
+        // TODO - what's a sentence?
+        return QString();
+    case LineBoundary:
+        cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
+        *startOffset = cursor.position();
+        cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
+        *endOffset = cursor.position();
+        break;
+    case ParagraphBoundary:
+        cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
+        *startOffset = cursor.position();
+        cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+        *endOffset = cursor.position();
         break;
+    case NoBoundary: {
+        *startOffset = 0;
+        const QString txt = edit->toPlainText();
+        *endOffset = txt.count();
+        return txt; }
     default:
-        return QAccessibleWidget::navigate(relation, entry, target);
+        qDebug("AccessibleTextAdaptor::textAtOffset: Unknown boundary type %d", boundaryType);
+        return QString();
     }
-    *target = QAccessible::queryAccessibleInterface(targetObject);
-    return *target ? 0: -1;
+
+    return cursor.selectedText();
 }
 
-QMdiArea *QAccessibleMdiArea::mdiArea() const
+void QAccessibleTextEdit::removeSelection(int selectionIndex)
 {
-    return static_cast<QMdiArea *>(object());
+    if (selectionIndex != 0)
+        return;
+
+    QTextCursor cursor = textEdit()->textCursor();
+    cursor.clearSelection();
+    textEdit()->setTextCursor(cursor);
 }
 
-// ======================= QAccessibleMdiSubWindow ======================
-QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
-    : QAccessibleWidget(widget, QAccessible::Window)
+void QAccessibleTextEdit::setCursorPosition(int position)
 {
-    Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
+    QTextCursor cursor = textEdit()->textCursor();
+    cursor.setPosition(position);
+    textEdit()->setTextCursor(cursor);
 }
 
-QString QAccessibleMdiSubWindow::text(Text textType, int child) const
+void QAccessibleTextEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
 {
-    if (textType == QAccessible::Name && (child == 0 || child == 1)) {
-        QString title = mdiSubWindow()->windowTitle();
-        title.replace(QLatin1String("[*]"), QLatin1String(""));
-        return title;
-    }
-    return QAccessibleWidget::text(textType, child);
+    if (selectionIndex != 0)
+        return;
+
+    QTextCursor cursor = textEdit()->textCursor();
+    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+    textEdit()->setTextCursor(cursor);
 }
 
-void QAccessibleMdiSubWindow::setText(Text textType, int child, const QString &text)
+int QAccessibleTextEdit::characterCount()
 {
-    if (textType == QAccessible::Name && (child == 0 || child == 1))
-        mdiSubWindow()->setWindowTitle(text);
-    else
-        QAccessibleWidget::setText(textType, child, text);
+    return textEdit()->toPlainText().count();
 }
 
-QAccessible::State QAccessibleMdiSubWindow::state(int child) const
+void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
 {
-    if (child != 0 || !mdiSubWindow()->parent())
-        return QAccessibleWidget::state(child);
-    QAccessible::State state = QAccessible::Normal | QAccessible::Focusable;
-    if (!mdiSubWindow()->isMaximized())
-        state |= (QAccessible::Movable | QAccessible::Sizeable);
-    if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
-            || QApplication::focusWidget() == mdiSubWindow())
-        state |= QAccessible::Focused;
-    if (!mdiSubWindow()->isVisible())
-        state |= QAccessible::Invisible;
-    if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
-        state |= QAccessible::Offscreen;
-    if (!mdiSubWindow()->isEnabled())
-        state |= QAccessible::Unavailable;
-    return state;
+    QTextEdit *edit = textEdit();
+
+    QTextCursor cursor(edit->document());
+    cursor.setPosition(startIndex);
+    QRect r = edit->cursorRect(cursor);
+
+    cursor.setPosition(endIndex);
+    r.setBottomRight(edit->cursorRect(cursor).bottomRight());
+
+    r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
+             r.y() + edit->verticalScrollBar()->value());
+
+    // E V I L, but ensureVisible is not public
+    if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
+        qWarning("AccessibleTextEdit::scrollToSubstring failed!");
 }
 
-QVariant QAccessibleMdiSubWindow::invokeMethod(QAccessible::Method, int, const QVariantList &)
+static QTextCursor cursorForRange(QTextEdit *textEdit, int startOffset, int endOffset)
 {
-    return QVariant();
+    QTextCursor cursor(textEdit->document());
+    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+
+    return cursor;
 }
 
-int QAccessibleMdiSubWindow::childCount() const
+void QAccessibleTextEdit::copyText(int startOffset, int endOffset)
 {
-    if (mdiSubWindow()->widget())
-        return 1;
-    return 0;
+    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+
+    if (!cursor.hasSelection())
+        return;
+
+//     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
 }
 
-int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
+void QAccessibleTextEdit::deleteText(int startOffset, int endOffset)
 {
-    if (child && child->object() && child->object() == mdiSubWindow()->widget())
-        return 1;
-    return -1;
+    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+
+    cursor.removeSelectedText();
 }
 
-int QAccessibleMdiSubWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
+void QAccessibleTextEdit::insertText(int offset, const QString &text)
 {
-    *target = 0;
+    QTextCursor cursor(textEdit()->document());
+    cursor.setPosition(offset);
 
-    if (!mdiSubWindow()->parent())
-        return QAccessibleWidget::navigate(relation, entry, target);
+    cursor.insertText(text);
+}
 
-    QWidget *targetObject = 0;
-    QMdiSubWindow *source = mdiSubWindow();
-    switch (relation) {
-    case Child:
-        if (entry != 1 || !source->widget())
-            return -1;
-        targetObject = source->widget();
-        break;
-    case Up:
-    case Down:
-    case Left:
-    case Right: {
-        if (entry != 0)
-            break;
-        QWidget *parent = source->parentWidget();
-        while (parent && !parent->inherits("QMdiArea"))
-            parent = parent->parentWidget();
-        QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parent);
-        if (!mdiArea)
-            break;
-        int index = mdiArea->subWindowList().indexOf(source);
-        if (index == -1)
-            break;
-        if (QWidget *dest = mdiAreaNavigate(mdiArea, relation, index + 1)) {
-            *target = QAccessible::queryAccessibleInterface(dest);
-            return *target ? 0 : -1;
-        }
-        break;
-    }
-    default:
-        return QAccessibleWidget::navigate(relation, entry, target);
-    }
-    *target = QAccessible::queryAccessibleInterface(targetObject);
-    return *target ? 0: -1;
+void QAccessibleTextEdit::cutText(int startOffset, int endOffset)
+{
+    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+
+    if (!cursor.hasSelection())
+        return;
+
+//     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
+    cursor.removeSelectedText();
 }
 
-QRect QAccessibleMdiSubWindow::rect(int child) const
+void QAccessibleTextEdit::pasteText(int offset)
 {
-    if (mdiSubWindow()->isHidden())
-        return QRect();
-    if (!mdiSubWindow()->parent())
-        return QAccessibleWidget::rect(child);
-    const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
-    if (child == 0)
-        return QRect(pos, mdiSubWindow()->size());
-    if (child == 1 && mdiSubWindow()->widget()) {
-        if (mdiSubWindow()->widget()->isHidden())
-            return QRect();
-        const QRect contentsRect = mdiSubWindow()->contentsRect();
-        return QRect(pos.x() + contentsRect.x(), pos.y() + contentsRect.y(),
-                     contentsRect.width(), contentsRect.height());
-    }
-    return QRect();
+    QTextEdit *edit = textEdit();
+
+    QTextCursor oldCursor = edit->textCursor();
+    QTextCursor newCursor = oldCursor;
+    newCursor.setPosition(offset);
+
+    edit->setTextCursor(newCursor);
+#ifndef QT_NO_CLIPBOARD
+    edit->paste();
+#endif
+    edit->setTextCursor(oldCursor);
 }
 
-int QAccessibleMdiSubWindow::childAt(int x, int y) const
+void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QString &text)
 {
-    if (!mdiSubWindow()->isVisible())
-        return -1;
-    if (!mdiSubWindow()->parent())
-        return QAccessibleWidget::childAt(x, y);
-    const QRect globalGeometry = rect(0);
-    if (!globalGeometry.isValid())
-        return -1;
-    const QRect globalChildGeometry = rect(1);
-    if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
-        return 1;
-    if (globalGeometry.contains(QPoint(x, y)))
-        return 0;
-    return -1;
+    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+
+    cursor.removeSelectedText();
+    cursor.insertText(text);
 }
 
-QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
+void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes)
 {
-    return static_cast<QMdiSubWindow *>(object());
+    // TODO
+    Q_UNUSED(startOffset);
+    Q_UNUSED(endOffset);
+    Q_UNUSED(attributes);
 }
-#endif // QT_NO_MDIAREA
+#endif // QT_NO_TEXTEDIT
 
-// ======================= QAccessibleWorkspace ======================
-#ifndef QT_NO_WORKSPACE
-QAccessibleWorkspace::QAccessibleWorkspace(QWidget *widget)
+#ifndef QT_NO_STACKEDWIDGET
+// ======================= QAccessibleStackedWidget ======================
+QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
     : QAccessibleWidget(widget, LayeredPane)
 {
-    Q_ASSERT(qobject_cast<QWorkspace *>(widget));
+    Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
 }
 
-QAccessible::State QAccessibleWorkspace::state(int child) const
+QVariant QAccessibleStackedWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-    if (child < 0)
-        return QAccessibleWidget::state(child);
-    if (child == 0)
-        return QAccessible::Normal;
-    QWidgetList subWindows = workspace()->windowList();
-    if (subWindows.isEmpty() || child > subWindows.count())
-        return QAccessibleWidget::state(child);
-    if (subWindows.at(child - 1) == workspace()->activeWindow())
-        return QAccessible::Focused;
-    return QAccessible::Normal;
+    return QVariant();
 }
 
-QVariant QAccessibleWorkspace::invokeMethod(QAccessible::Method, int, const QVariantList &)
+
+int QAccessibleStackedWidget::childAt(int x, int y) const
 {
-    return QVariant();
+    if (!stackedWidget()->isVisible())
+        return -1;
+    QWidget *currentWidget = stackedWidget()->currentWidget();
+    if (!currentWidget)
+        return -1;
+    QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
+    if (currentWidget->rect().contains(position))
+        return 1;
+    return -1;
 }
 
-int QAccessibleWorkspace::childCount() const
+int QAccessibleStackedWidget::childCount() const
 {
-    return workspace()->windowList().count();
+    return stackedWidget()->count();
 }
 
-int QAccessibleWorkspace::indexOfChild(const QAccessibleInterface *child) const
+int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
 {
-    if (!child || !child->object() || workspace()->windowList().isEmpty())
+    if (!child)
         return -1;
-    if (QWidget *window = qobject_cast<QWidget *>(child->object())) {
-        int index = workspace()->windowList().indexOf(window);
-        if (index != -1)
-            return ++index;
-    }
+
+    QWidget* widget = qobject_cast<QWidget*>(child->object());
+    int index = stackedWidget()->indexOf(widget);
+    if (index >= 0) // one based counting of children
+        return index + 1;
     return -1;
 }
 
-int QAccessibleWorkspace::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
+QAccessibleInterface *QAccessibleStackedWidget::child(int index) const
+{
+    if (index < 0 || index >= stackedWidget()->count())
+        return 0;
+    return QAccessible::queryAccessibleInterface(stackedWidget()->widget(index));
+}
+
+int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
-    *target = 0;
-    QWidget *targetObject = 0;
-    QWidgetList subWindows = workspace()->windowList();
     switch (relation) {
     case Child:
-        if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
-            return -1;
-        targetObject = subWindows.at(entry - 1);
-        break;
-    case Up:
-    case Down:
-    case Left:
-    case Right:
-        targetObject = mdiAreaNavigate(workspace(), relation, entry);
-        break;
+        *target = child(entry - 1);
+        return *target ? 0 : -1;
     default:
         return QAccessibleWidget::navigate(relation, entry, target);
     }
-    *target = QAccessible::queryAccessibleInterface(targetObject);
-    return *target ? 0: -1;
-}
-
-QWorkspace *QAccessibleWorkspace::workspace() const
-{
-    return static_cast<QWorkspace *>(object());
 }
-#endif
 
-#ifndef QT_NO_DIALOGBUTTONBOX
-// ======================= QAccessibleDialogButtonBox ======================
-QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
-    : QAccessibleWidget(widget, Grouping)
+QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
 {
-    Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
+    return static_cast<QStackedWidget *>(object());
 }
+#endif // QT_NO_STACKEDWIDGET
 
-QVariant QAccessibleDialogButtonBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
+#ifndef QT_NO_TOOLBOX
+// ======================= QAccessibleToolBox ======================
+QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
+    : QAccessibleWidget(widget, LayeredPane)
 {
-    return QVariant();
+    Q_ASSERT(qobject_cast<QToolBox *>(widget));
 }
-#endif // QT_NO_DIALOGBUTTONBOX
 
-#ifndef QT_NO_TEXTBROWSER
-QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
-    : QAccessibleTextEdit(widget)
+QString QAccessibleToolBox::text(Text textType, int child) const
 {
-    Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
+    if (textType != Value || child <= 0 || child > toolBox()->count())
+        return QAccessibleWidget::text(textType, child);
+    return toolBox()->itemText(child - 1);
 }
 
-QAccessible::Role QAccessibleTextBrowser::role(int child) const
+void QAccessibleToolBox::setText(Text textType, int child, const QString &text)
 {
-    if (child != 0)
-        return QAccessibleTextEdit::role(child);
-    return QAccessible::StaticText;
+    if (textType != Value || child <= 0 || child > toolBox()->count()) {
+        QAccessibleWidget::setText(textType, child, text);
+        return;
+    }
+    toolBox()->setItemText(child - 1, text);
 }
-#endif // QT_NO_TEXTBROWSER
 
-#ifndef QT_NO_CALENDARWIDGET
-// ===================== QAccessibleCalendarWidget ========================
-QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
-    : QAccessibleWidget(widget, Table)
+QAccessible::State QAccessibleToolBox::state(int child) const
 {
-    Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
+    QWidget *childWidget = toolBox()->widget(child - 1);
+    if (!childWidget)
+        return QAccessibleWidget::state(child);
+    QAccessible::State childState = QAccessible::Normal;
+    if (toolBox()->currentWidget() == childWidget)
+        childState |= QAccessible::Expanded;
+    else
+        childState |= QAccessible::Collapsed;
+    return childState;
 }
 
-QVariant QAccessibleCalendarWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
+QVariant QAccessibleToolBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
     return QVariant();
 }
 
-int QAccessibleCalendarWidget::childCount() const
+int QAccessibleToolBox::childCount() const
 {
-   return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
+    return toolBox()->count();
 }
 
-int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
+int QAccessibleToolBox::indexOfChild(const QAccessibleInterface *child) const
 {
-    if (!child || !child->object() || childCount() <= 0)
+    if (!child)
         return -1;
-    if (qobject_cast<QAbstractItemView *>(child->object()))
-        return childCount();
-    return 1;
+    QWidget *childWidget = qobject_cast<QWidget *>(child->object());
+    if (!childWidget)
+        return -1;
+    int index = toolBox()->indexOf(childWidget);
+    if (index != -1)
+        ++index;
+    return index;
 }
 
-int QAccessibleCalendarWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
+int QAccessibleToolBox::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
     *target = 0;
-    if (entry <= 0 || entry > childCount())
-        return QAccessibleWidget::navigate(relation, entry, target);
-    QWidget *targetWidget = 0;
-    switch (relation) {
-    case Child:
-        if (childCount() == 1) {
-            targetWidget = calendarView();
-        } else {
-            if (entry == 1)
-                targetWidget = navigationBar();
-            else
-                targetWidget = calendarView();
-        }
-        break;
-    case Up:
-        if (entry == 2)
-            targetWidget = navigationBar();
-        break;
-    case Down:
-        if (entry == 1 && childCount() == 2)
-            targetWidget = calendarView();
-        break;
-    default:
+    if (entry <= 0 || entry > toolBox()->count())
         return QAccessibleWidget::navigate(relation, entry, target);
-    }
-    *target = queryAccessibleInterface(targetWidget);
+    int index = -1;
+    if (relation == QAccessible::Up)
+        index = entry - 2;
+    else if (relation == QAccessible::Down)
+        index = entry;
+    *target = QAccessible::queryAccessibleInterface(toolBox()->widget(index));
     return *target ? 0: -1;
 }
 
-QRect QAccessibleCalendarWidget::rect(int child) const
-{
-    if (!calendarWidget()->isVisible() || child > childCount())
-        return QRect();
-    if (child == 0)
-        return QAccessibleWidget::rect(child);
-    QWidget *childWidget = 0;
-    if (childCount() == 2)
-        childWidget = child == 1 ? navigationBar() : calendarView();
-    else
-        childWidget = calendarView();
-    return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
-}
-
-int QAccessibleCalendarWidget::childAt(int x, int y) const
+QToolBox * QAccessibleToolBox::toolBox() const
 {
-    const QPoint globalTargetPos = QPoint(x, y);
-    if (!rect(0).contains(globalTargetPos))
-        return -1;
-    if (rect(1).contains(globalTargetPos))
-        return 1;
-    if (rect(2).contains(globalTargetPos))
-        return 2;
-    return 0;
+    return static_cast<QToolBox *>(object());
 }
+#endif // QT_NO_TOOLBOX
 
-QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
+// ======================= QAccessibleMdiArea ======================
+#ifndef QT_NO_MDIAREA
+QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
+    : QAccessibleWidget(widget, LayeredPane)
 {
-    return static_cast<QCalendarWidget *>(object());
+    Q_ASSERT(qobject_cast<QMdiArea *>(widget));
 }
 
-QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
+QAccessible::State QAccessibleMdiArea::state(int child) const
 {
-    foreach (QObject *child, calendarWidget()->children()) {
-        if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
-            return static_cast<QAbstractItemView *>(child);
-    }
-    return 0;
+    if (child < 0)
+        return QAccessibleWidget::state(child);
+    if (child == 0)
+        return QAccessible::Normal;
+    QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
+    if (subWindows.isEmpty() || child > subWindows.count())
+        return QAccessibleWidget::state(child);
+    if (subWindows.at(child - 1) == mdiArea()->activeSubWindow())
+        return QAccessible::Focused;
+    return QAccessible::Normal;
 }
 
-QWidget *QAccessibleCalendarWidget::navigationBar() const
+QVariant QAccessibleMdiArea::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-    foreach (QObject *child, calendarWidget()->children()) {
-        if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
-            return static_cast<QWidget *>(child);
-    }
-    return 0;
+    return QVariant();
 }
-#endif // QT_NO_CALENDARWIDGET
 
-#ifndef QT_NO_DOCKWIDGET
-QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
-    : QAccessibleWidget(widget, Window)
+int QAccessibleMdiArea::childCount() const
 {
-
+    return mdiArea()->subWindowList().count();
 }
 
-int QAccessibleDockWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
+int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
 {
-    if (relation == Child) {
-        if (entry == 1) {
-            *iface = new QAccessibleTitleBar(dockWidget());
-            return 0;
-        } else if (entry == 2) {
-            if (dockWidget()->widget())
-                *iface = QAccessible::queryAccessibleInterface(dockWidget()->widget());
-            return 0;
-        }
-        *iface = 0;
+    if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
         return -1;
+    if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
+        int index = mdiArea()->subWindowList().indexOf(window);
+        if (index != -1)
+            return ++index;
     }
-    return QAccessibleWidget::navigate(relation, entry, iface);
+    return -1;
 }
 
-int QAccessibleDockWidget::childAt(int x, int y) const
+int QAccessibleMdiArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
-    for (int i = childCount(); i >= 0; --i) {
-        if (rect(i).contains(x,y))
-            return i;
+    *target = 0;
+    QWidget *targetObject = 0;
+    QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
+    switch (relation) {
+    case Child:
+        if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
+            return -1;
+        targetObject = subWindows.at(entry - 1);
+        break;
+    case Up:
+    case Down:
+    case Left:
+    case Right:
+        targetObject = mdiAreaNavigate(mdiArea(), relation, entry);
+        break;
+    default:
+        return QAccessibleWidget::navigate(relation, entry, target);
     }
-    return -1;
+    *target = QAccessible::queryAccessibleInterface(targetObject);
+    return *target ? 0: -1;
 }
 
-int QAccessibleDockWidget::childCount() const
+QMdiArea *QAccessibleMdiArea::mdiArea() const
 {
-    return dockWidget()->widget() ? 2 : 1;
+    return static_cast<QMdiArea *>(object());
 }
 
-int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
+// ======================= QAccessibleMdiSubWindow ======================
+QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
+    : QAccessibleWidget(widget, QAccessible::Window)
 {
-    if (child) {
-        if (child->role(0) == TitleBar) {
-            return 1;
-        } else {
-            return 2;   //###
-        }
-    }
-    return -1;
+    Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
 }
 
-QAccessible::Role QAccessibleDockWidget::role(int child) const
+QString QAccessibleMdiSubWindow::text(Text textType, int child) const
 {
-    switch (child) {
-        case 0:
-            return Window;
-        case 1:
-            return TitleBar;
-        case 2:
-            //###
-            break;
-        default:
-            break;
+    if (textType == QAccessible::Name && (child == 0 || child == 1)) {
+        QString title = mdiSubWindow()->windowTitle();
+        title.replace(QLatin1String("[*]"), QLatin1String(""));
+        return title;
     }
-    return NoRole;
+    return QAccessibleWidget::text(textType, child);
 }
 
-QAccessible::State QAccessibleDockWidget::state(int child) const
+void QAccessibleMdiSubWindow::setText(Text textType, int child, const QString &text)
 {
-    //### mark tabified widgets as invisible
-    return QAccessibleWidget::state(child);
+    if (textType == QAccessible::Name && (child == 0 || child == 1))
+        mdiSubWindow()->setWindowTitle(text);
+    else
+        QAccessibleWidget::setText(textType, child, text);
 }
 
-QRect QAccessibleDockWidget::rect (int child ) const
+QAccessible::State QAccessibleMdiSubWindow::state(int child) const
 {
-    QRect rect;
-    bool mapToGlobal = true;
-    if (child == 0) {
-        if (dockWidget()->isFloating()) {
-            rect = dockWidget()->frameGeometry();
-            mapToGlobal = false;
-        } else {
-            rect = dockWidget()->rect();
-        }
-    }else if (child == 1) {
-        QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
-        rect = layout->titleArea();
-    }else if (child == 2) {
-        if (dockWidget()->widget())
-            rect = dockWidget()->widget()->geometry();
-    }
-    if (rect.isNull())
-        return rect;
-
-    if (mapToGlobal)
-        rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
-
-    return rect;
+    if (child != 0 || !mdiSubWindow()->parent())
+        return QAccessibleWidget::state(child);
+    QAccessible::State state = QAccessible::Normal | QAccessible::Focusable;
+    if (!mdiSubWindow()->isMaximized())
+        state |= (QAccessible::Movable | QAccessible::Sizeable);
+    if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
+            || QApplication::focusWidget() == mdiSubWindow())
+        state |= QAccessible::Focused;
+    if (!mdiSubWindow()->isVisible())
+        state |= QAccessible::Invisible;
+    if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
+        state |= QAccessible::Offscreen;
+    if (!mdiSubWindow()->isEnabled())
+        state |= QAccessible::Unavailable;
+    return state;
 }
 
-QVariant QAccessibleDockWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
+QVariant QAccessibleMdiSubWindow::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
     return QVariant();
 }
 
-QDockWidget *QAccessibleDockWidget::dockWidget() const
+int QAccessibleMdiSubWindow::childCount() const
 {
-    return static_cast<QDockWidget *>(object());
+    if (mdiSubWindow()->widget())
+        return 1;
+    return 0;
 }
 
-////
-//      QAccessibleTitleBar
-////
-QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget)
-    : m_dockWidget(widget)
+int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
 {
-
+    if (child && child->object() && child->object() == mdiSubWindow()->widget())
+        return 1;
+    return -1;
 }
 
-QAccessibleInterface *QAccessibleTitleBar::parent() const
+int QAccessibleMdiSubWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
-    return new QAccessibleDockWidget(dockWidget());
-}
+    *target = 0;
 
-QAccessibleInterface *QAccessibleTitleBar::child(int index) const
-{
-    if (index >= 0) {
-        QDockWidgetLayout *layout = dockWidgetLayout();
-        int role;
-        int currentIndex = 0;
-        for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
-            QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
-            if (!w || !w->isVisible())
-                continue;
-            if (currentIndex == index)
-                return QAccessible::queryAccessibleInterface(w);
-            ++currentIndex;
-        }
-    }
-    return 0;
-}
+    if (!mdiSubWindow()->parent())
+        return QAccessibleWidget::navigate(relation, entry, target);
 
-int QAccessibleTitleBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
-{
+    QWidget *targetObject = 0;
+    QMdiSubWindow *source = mdiSubWindow();
     switch (relation) {
     case Child:
-        *iface = child(entry - 1);
-        return *iface ? 0 : -1;
-    case FocusChild:
-        // ###
-        if (entry >= 1) {
-            QDockWidgetLayout *layout = dockWidgetLayout();
-            int index = 1;
-            int role;
-            for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
-                QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
-                if (!w->isVisible())
-                    continue;
-                if (index == entry)
-                    break;
-                ++index;
-            }
-            *iface = 0;
-            return role > QDockWidgetLayout::FloatButton ? -1 : index;
-        }
+        if (entry != 1 || !source->widget())
+            return -1;
+        targetObject = source->widget();
         break;
-    case Ancestor:
-        *iface = parent();
-        return iface ? 0 : -1;
-    case Sibling:
-        return navigate(Child, entry, iface);
+    case Up:
+    case Down:
+    case Left:
+    case Right: {
+        if (entry != 0)
+            break;
+        QWidget *parent = source->parentWidget();
+        while (parent && !parent->inherits("QMdiArea"))
+            parent = parent->parentWidget();
+        QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parent);
+        if (!mdiArea)
+            break;
+        int index = mdiArea->subWindowList().indexOf(source);
+        if (index == -1)
+            break;
+        if (QWidget *dest = mdiAreaNavigate(mdiArea, relation, index + 1)) {
+            *target = QAccessible::queryAccessibleInterface(dest);
+            return *target ? 0 : -1;
+        }
         break;
+    }
     default:
-        break;
+        return QAccessibleWidget::navigate(relation, entry, target);
     }
-    *iface = 0;
-    return -1;
+    *target = QAccessible::queryAccessibleInterface(targetObject);
+    return *target ? 0: -1;
 }
 
-QAccessible::Relation QAccessibleTitleBar::relationTo(int /*child*/,  const QAccessibleInterface * /*other*/, int /*otherChild*/) const
+QRect QAccessibleMdiSubWindow::rect(int child) const
 {
-    return Unrelated;   //###
+    if (mdiSubWindow()->isHidden())
+        return QRect();
+    if (!mdiSubWindow()->parent())
+        return QAccessibleWidget::rect(child);
+    const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
+    if (child == 0)
+        return QRect(pos, mdiSubWindow()->size());
+    if (child == 1 && mdiSubWindow()->widget()) {
+        if (mdiSubWindow()->widget()->isHidden())
+            return QRect();
+        const QRect contentsRect = mdiSubWindow()->contentsRect();
+        return QRect(pos.x() + contentsRect.x(), pos.y() + contentsRect.y(),
+                     contentsRect.width(), contentsRect.height());
+    }
+    return QRect();
 }
 
-int QAccessibleTitleBar::indexOfChild(const QAccessibleInterface * /*child*/) const
+int QAccessibleMdiSubWindow::childAt(int x, int y) const
 {
+    if (!mdiSubWindow()->isVisible())
+        return -1;
+    if (!mdiSubWindow()->parent())
+        return QAccessibleWidget::childAt(x, y);
+    const QRect globalGeometry = rect(0);
+    if (!globalGeometry.isValid())
+        return -1;
+    const QRect globalChildGeometry = rect(1);
+    if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
+        return 1;
+    if (globalGeometry.contains(QPoint(x, y)))
+        return 0;
     return -1;
 }
 
-int QAccessibleTitleBar::childCount() const
+QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
 {
-    QDockWidgetLayout *layout = dockWidgetLayout();
-    int count = 0;
-    for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
-        QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
-        if (w && w->isVisible())
-            ++count;
-    }
-    return count;
+    return static_cast<QMdiSubWindow *>(object());
 }
+#endif // QT_NO_MDIAREA
 
-QString QAccessibleTitleBar::text(Text t, int child) const
+// ======================= QAccessibleWorkspace ======================
+#ifndef QT_NO_WORKSPACE
+QAccessibleWorkspace::QAccessibleWorkspace(QWidget *widget)
+    : QAccessibleWidget(widget, LayeredPane)
 {
-    if (!child) {
-        if (t == Name || t == Value) {
-            return qt_accStripAmp(dockWidget()->windowTitle());
-        }
-    }
-    return QString();
+    Q_ASSERT(qobject_cast<QWorkspace *>(widget));
 }
 
-QAccessible::State QAccessibleTitleBar::state(int child) const
+QAccessible::State QAccessibleWorkspace::state(int child) const
 {
-    QAccessible::State state = Normal;
-    if (child) {
-        QDockWidgetLayout *layout = dockWidgetLayout();
-        QAbstractButton *b = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
-        if (b) {
-            if (b->isDown())
-                state |= Pressed;
-        }
-    } else {
-        QDockWidget *w = dockWidget();
-        if (w->testAttribute(Qt::WA_WState_Visible) == false)
-            state |= Invisible;
-        if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
-            state |= Focusable;
-        if (w->hasFocus())
-            state |= Focused;
-        if (!w->isEnabled())
-            state |= Unavailable;
-    }
-
-    return state;
+    if (child < 0)
+        return QAccessibleWidget::state(child);
+    if (child == 0)
+        return QAccessible::Normal;
+    QWidgetList subWindows = workspace()->windowList();
+    if (subWindows.isEmpty() || child > subWindows.count())
+        return QAccessibleWidget::state(child);
+    if (subWindows.at(child - 1) == workspace()->activeWindow())
+        return QAccessible::Focused;
+    return QAccessible::Normal;
 }
 
-QRect QAccessibleTitleBar::rect(int child) const
+QVariant QAccessibleWorkspace::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-    bool mapToGlobal = true;
-    QRect rect;
-    if (child == 0) {
-        if (dockWidget()->isFloating()) {
-            rect = dockWidget()->frameGeometry();
-            if (dockWidget()->widget()) {
-                QPoint globalPos = dockWidget()->mapToGlobal(dockWidget()->widget()->rect().topLeft());
-                globalPos.ry()--;
-                rect.setBottom(globalPos.y());
-                mapToGlobal = false;
-            }
-        } else {
-            QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
-            rect = layout->titleArea();
-        }
-    }else if (child >= 1 && child <= childCount()) {
-        QDockWidgetLayout *layout = dockWidgetLayout();
-        int index = 1;
-        for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
-            QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
-            if (!w || !w->isVisible())
-                continue;
-            if (index == child) {
-                rect = w->geometry();
-                break;
-            }
-            ++index;
-        }
-    }
-    if (rect.isNull())
-        return rect;
+    return QVariant();
+}
 
-    if (mapToGlobal)
-        rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
-    return rect;
+int QAccessibleWorkspace::childCount() const
+{
+    return workspace()->windowList().count();
 }
 
-int QAccessibleTitleBar::childAt(int x, int y) const
+int QAccessibleWorkspace::indexOfChild(const QAccessibleInterface *child) const
 {
-    for (int i = childCount(); i >= 0; --i) {
-        if (rect(i).contains(x,y))
-            return i;
+    if (!child || !child->object() || workspace()->windowList().isEmpty())
+        return -1;
+    if (QWidget *window = qobject_cast<QWidget *>(child->object())) {
+        int index = workspace()->windowList().indexOf(window);
+        if (index != -1)
+            return ++index;
     }
     return -1;
 }
 
-QObject *QAccessibleTitleBar::object() const
+int QAccessibleWorkspace::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
-    return 0;
+    *target = 0;
+    QWidget *targetObject = 0;
+    QWidgetList subWindows = workspace()->windowList();
+    switch (relation) {
+    case Child:
+        if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
+            return -1;
+        targetObject = subWindows.at(entry - 1);
+        break;
+    case Up:
+    case Down:
+    case Left:
+    case Right:
+        targetObject = mdiAreaNavigate(workspace(), relation, entry);
+        break;
+    default:
+        return QAccessibleWidget::navigate(relation, entry, target);
+    }
+    *target = QAccessible::queryAccessibleInterface(targetObject);
+    return *target ? 0: -1;
 }
 
-QDockWidgetLayout *QAccessibleTitleBar::dockWidgetLayout() const
+QWorkspace *QAccessibleWorkspace::workspace() const
 {
-    return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
+    return static_cast<QWorkspace *>(object());
 }
+#endif
 
-QDockWidget *QAccessibleTitleBar::dockWidget() const
+#ifndef QT_NO_DIALOGBUTTONBOX
+// ======================= QAccessibleDialogButtonBox ======================
+QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
+    : QAccessibleWidget(widget, Grouping)
 {
-    return m_dockWidget;
+    Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
 }
 
-QString QAccessibleTitleBar::actionText(int action, Text t, int child) const
+QVariant QAccessibleDialogButtonBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-    QString str;
-    if (child >= 1 && child <= childCount()) {
-        if (t == Name) {
-            switch (action) {
-            case Press:
-            case DefaultAction:
-                if (child == QDockWidgetLayout::CloseButton) {
-                    str = QDockWidget::tr("Close");
-                } else if (child == QDockWidgetLayout::FloatButton) {
-                    str = dockWidget()->isFloating() ? QDockWidget::tr("Dock")
-                                                     : QDockWidget::tr("Float");
-                }
-                break;
-            default:
-                break;
-            }
-        }
-    }
-    return str;
+    return QVariant();
 }
+#endif // QT_NO_DIALOGBUTTONBOX
 
-bool QAccessibleTitleBar::doAction(int action, int child, const QVariantList& /*params*/)
+#ifndef QT_NO_TEXTBROWSER
+QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
+    : QAccessibleTextEdit(widget)
 {
-    if (!child || !dockWidget()->isEnabled())
-        return false;
-
-    switch (action) {
-    case DefaultAction:
-    case Press: {
-        QDockWidgetLayout *layout = dockWidgetLayout();
-        QAbstractButton *btn = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
-        if (btn)
-            btn->animateClick();
-        return true;
-        break;}
-    default:
-        break;
-    }
-
-    return false;
+    Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
 }
 
-int QAccessibleTitleBar::userActionCount (int /*child*/) const
+QAccessible::Role QAccessibleTextBrowser::role(int child) const
 {
-    return 0;
+    if (child != 0)
+        return QAccessibleTextEdit::role(child);
+    return QAccessible::StaticText;
 }
+#endif // QT_NO_TEXTBROWSER
 
-QAccessible::Role QAccessibleTitleBar::role(int child) const
+#ifndef QT_NO_CALENDARWIDGET
+// ===================== QAccessibleCalendarWidget ========================
+QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
+    : QAccessibleWidget(widget, Table)
 {
-    switch (child) {
-        case 0:
-            return TitleBar;
-            break;
-        default:
-            if (child >= 1 && child <= childCount())
-                return PushButton;
-            break;
-    }
-
-    return NoRole;
+    Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
 }
 
-void QAccessibleTitleBar::setText(Text /*t*/, int /*child*/, const QString &/*text*/)
+QVariant QAccessibleCalendarWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-
+    return QVariant();
 }
 
-bool QAccessibleTitleBar::isValid() const
+int QAccessibleCalendarWidget::childCount() const
 {
-    return dockWidget();
+   return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
 }
 
-#endif // QT_NO_DOCKWIDGET
-
-#ifndef QT_NO_TEXTEDIT
-void QAccessibleTextEdit::addSelection(int startOffset, int endOffset)
+int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
 {
-    setSelection(0, startOffset, endOffset);
+    if (!child || !child->object() || childCount() <= 0)
+        return -1;
+    if (qobject_cast<QAbstractItemView *>(child->object()))
+        return childCount();
+    return 1;
 }
 
-QString QAccessibleTextEdit::attributes(int offset, int *startOffset, int *endOffset)
+int QAccessibleCalendarWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
 {
-    /* The list of attributes can be found at:
-     http://linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes
-    */
-
-    if (offset >= characterCount()) {
-        *startOffset = -1;
-        *endOffset = -1;
-        return QString();
+    *target = 0;
+    if (entry <= 0 || entry > childCount())
+        return QAccessibleWidget::navigate(relation, entry, target);
+    QWidget *targetWidget = 0;
+    switch (relation) {
+    case Child:
+        if (childCount() == 1) {
+            targetWidget = calendarView();
+        } else {
+            if (entry == 1)
+                targetWidget = navigationBar();
+            else
+                targetWidget = calendarView();
+        }
+        break;
+    case Up:
+        if (entry == 2)
+            targetWidget = navigationBar();
+        break;
+    case Down:
+        if (entry == 1 && childCount() == 2)
+            targetWidget = calendarView();
+        break;
+    default:
+        return QAccessibleWidget::navigate(relation, entry, target);
     }
+    *target = queryAccessibleInterface(targetWidget);
+    return *target ? 0: -1;
+}
 
-    QMap<QString, QString> attrs;
-
-    QTextCursor cursor = textEdit()->textCursor();
-
-    //cursor.charFormat returns the format of the previous character
-    cursor.setPosition(offset + 1);
-    QTextCharFormat charFormat = cursor.charFormat();
-
-    cursor.setPosition(offset);
-    QTextBlockFormat blockFormat = cursor.blockFormat();
+QRect QAccessibleCalendarWidget::rect(int child) const
+{
+    if (!calendarWidget()->isVisible() || child > childCount())
+        return QRect();
+    if (child == 0)
+        return QAccessibleWidget::rect(child);
+    QWidget *childWidget = 0;
+    if (childCount() == 2)
+        childWidget = child == 1 ? navigationBar() : calendarView();
+    else
+        childWidget = calendarView();
+    return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
+}
 
-    QTextCharFormat charFormatComp;
-    QTextBlockFormat blockFormatComp;
+int QAccessibleCalendarWidget::childAt(int x, int y) const
+{
+    const QPoint globalTargetPos = QPoint(x, y);
+    if (!rect(0).contains(globalTargetPos))
+        return -1;
+    if (rect(1).contains(globalTargetPos))
+        return 1;
+    if (rect(2).contains(globalTargetPos))
+        return 2;
+    return 0;
+}
 
-    *startOffset = offset;
-    cursor.setPosition(*startOffset);
-    while (*startOffset > 0) {
-        charFormatComp = cursor.charFormat();
-        cursor.setPosition(*startOffset - 1);
-        blockFormatComp = cursor.blockFormat();
-        if ((charFormat == charFormatComp) && (blockFormat == blockFormatComp))
-            (*startOffset)--;
-        else
-            break;
-    }
+QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
+{
+    return static_cast<QCalendarWidget *>(object());
+}
 
-    int limit = characterCount() + 1;
-    *endOffset = offset + 1;
-    cursor.setPosition(*endOffset);
-    while (*endOffset < limit) {
-        blockFormatComp = cursor.blockFormat();
-        cursor.setPosition(*endOffset + 1);
-        charFormatComp = cursor.charFormat();
-        if ((charFormat == charFormatComp) && (cursor.blockFormat() == blockFormatComp))
-            (*endOffset)++;
-        else
-            break;
+QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
+{
+    foreach (QObject *child, calendarWidget()->children()) {
+        if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
+            return static_cast<QAbstractItemView *>(child);
     }
+    return 0;
+}
 
-    QString family = charFormat.fontFamily();
-    if (!family.isEmpty()) {
-        family = family.replace('\\',"\\\\");
-        family = family.replace(':',"\\:");
-        family = family.replace(',',"\\,");
-        family = family.replace('=',"\\=");
-        family = family.replace(';',"\\;");
-        family = family.replace('\"',"\\\"");
-        attrs["font-family"] = '"'+family+'"';
+QWidget *QAccessibleCalendarWidget::navigationBar() const
+{
+    foreach (QObject *child, calendarWidget()->children()) {
+        if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
+            return static_cast<QWidget *>(child);
     }
+    return 0;
+}
+#endif // QT_NO_CALENDARWIDGET
 
-    int fontSize = int(charFormat.fontPointSize());
-    if (fontSize)
-        attrs["font-size"] = QString::number(fontSize).append("pt");
-
-    //Different weight values are not handled
-    attrs["font-weight"] = (charFormat.fontWeight() > QFont::Normal) ? "bold" : "normal";
-
-    QFont::Style style = charFormat.font().style();
-    attrs["font-style"] = (style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal");
-
-    attrs["text-underline-style"] = charFormat.font().underline() ? "solid" : "none";
-
-    QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
-    attrs["text-position"] = (alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" );
-
-    QBrush background = charFormat.background();
-    if (background.style() == Qt::SolidPattern) {
-        attrs["background-color"] = QString("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
-    }
+#ifndef QT_NO_DOCKWIDGET
+QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
+    : QAccessibleWidget(widget, Window)
+{
 
-    QBrush foreground = charFormat.foreground();
-    if (foreground.style() == Qt::SolidPattern) {
-        attrs["color"] = QString("rgb(%1,%2,%3)").arg(foreground.color().red()).arg(foreground.color().green()).arg(foreground.color().blue());
-    }
+}
 
-    switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
-    case Qt::AlignLeft:
-        attrs["text-align"] = "left";
-        break;
-    case Qt::AlignRight:
-        attrs["text-align"] = "right";
-        break;
-    case Qt::AlignHCenter:
-        attrs["text-align"] = "center";
-        break;
-    case Qt::AlignJustify:
-        attrs["text-align"] = "left";
-        break;
+int QAccessibleDockWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
+{
+    if (relation == Child) {
+        if (entry == 1) {
+            *iface = new QAccessibleTitleBar(dockWidget());
+            return 0;
+        } else if (entry == 2) {
+            if (dockWidget()->widget())
+                *iface = QAccessible::queryAccessibleInterface(dockWidget()->widget());
+            return 0;
+        }
+        *iface = 0;
+        return -1;
     }
+    return QAccessibleWidget::navigate(relation, entry, iface);
+}
 
-    QString result;
-    foreach (const QString &attributeName, attrs.keys()) {
-        result.append(attributeName).append(':').append(attrs[attributeName]).append(';');
+int QAccessibleDockWidget::childAt(int x, int y) const
+{
+    for (int i = childCount(); i >= 0; --i) {
+        if (rect(i).contains(x,y))
+            return i;
     }
-
-    return result;
+    return -1;
 }
 
-int QAccessibleTextEdit::cursorPosition()
+int QAccessibleDockWidget::childCount() const
 {
-    return textEdit()->textCursor().position();
+    return dockWidget()->widget() ? 2 : 1;
 }
 
-QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
+int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
 {
-    QTextEdit *edit = textEdit();
-    QTextCursor cursor(edit->document());
-    cursor.setPosition(offset);
-
-    if (cursor.position() != offset)
-        return QRect();
-
-    QRect r = edit->cursorRect(cursor);
-    if (cursor.movePosition(QTextCursor::NextCharacter)) {
-        r.setWidth(edit->cursorRect(cursor).x() - r.x());
-    } else {
-        // we don't know the width of the character - maybe because we're at document end
-        // in that case, IAccessible2 tells us to return the width of a default character
-        int averageCharWidth = QFontMetrics(cursor.charFormat().font()).averageCharWidth();
-        if (edit->layoutDirection() == Qt::RightToLeft)
-            averageCharWidth *= -1;
-        r.setWidth(averageCharWidth);
+    if (child) {
+        if (child->role(0) == TitleBar) {
+            return 1;
+        } else {
+            return 2;   //###
+        }
     }
+    return -1;
+}
 
-    switch (coordType) {
-    case RelativeToScreen:
-        r.moveTo(edit->viewport()->mapToGlobal(r.topLeft()));
-        break;
-    case RelativeToParent:
-        break;
+QAccessible::Role QAccessibleDockWidget::role(int child) const
+{
+    switch (child) {
+        case 0:
+            return Window;
+        case 1:
+            return TitleBar;
+        case 2:
+            //###
+            break;
+        default:
+            break;
     }
-
-    return r;
+    return NoRole;
 }
 
-int QAccessibleTextEdit::selectionCount()
+QAccessible::State QAccessibleDockWidget::state(int child) const
 {
-    return textEdit()->textCursor().hasSelection() ? 1 : 0;
+    //### mark tabified widgets as invisible
+    return QAccessibleWidget::state(child);
 }
 
-int QAccessibleTextEdit::offsetAtPoint(const QPoint &point, CoordinateType coordType)
+QRect QAccessibleDockWidget::rect (int child ) const
 {
-    QTextEdit *edit = textEdit();
+    QRect rect;
+    bool mapToGlobal = true;
+    if (child == 0) {
+        if (dockWidget()->isFloating()) {
+            rect = dockWidget()->frameGeometry();
+            mapToGlobal = false;
+        } else {
+            rect = dockWidget()->rect();
+        }
+    }else if (child == 1) {
+        QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
+        rect = layout->titleArea();
+    }else if (child == 2) {
+        if (dockWidget()->widget())
+            rect = dockWidget()->widget()->geometry();
+    }
+    if (rect.isNull())
+        return rect;
 
-    QPoint p = point;
-    if (coordType == RelativeToScreen)
-        p = edit->viewport()->mapFromGlobal(p);
-    // convert to document coordinates
-    p += QPoint(edit->horizontalScrollBar()->value(), edit->verticalScrollBar()->value());
+    if (mapToGlobal)
+        rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
 
-    return edit->document()->documentLayout()->hitTest(p, Qt::ExactHit);
+    return rect;
 }
 
-void QAccessibleTextEdit::selection(int selectionIndex, int *startOffset, int *endOffset)
+QVariant QAccessibleDockWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
 {
-    *startOffset = *endOffset = 0;
-    QTextCursor cursor = textEdit()->textCursor();
-
-    if (selectionIndex != 0 || !cursor.hasSelection())
-        return;
-
-    *startOffset = cursor.selectionStart();
-    *endOffset = cursor.selectionEnd();
+    return QVariant();
 }
 
-QString QAccessibleTextEdit::text(int startOffset, int endOffset)
+QDockWidget *QAccessibleDockWidget::dockWidget() const
 {
-    QTextCursor cursor(textEdit()->document());
+    return static_cast<QDockWidget *>(object());
+}
 
-    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
-    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+////
+//      QAccessibleTitleBar
+////
+QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget)
+    : m_dockWidget(widget)
+{
 
-    return cursor.selectedText();
 }
 
-QString QAccessibleTextEdit::textBeforeOffset (int offset, BoundaryType boundaryType,
-        int *startOffset, int *endOffset)
+QAccessibleInterface *QAccessibleTitleBar::parent() const
 {
-    // TODO - what exactly is before?
-    Q_UNUSED(offset);
-    Q_UNUSED(boundaryType);
-    Q_UNUSED(startOffset);
-    Q_UNUSED(endOffset);
-    return QString();
+    return new QAccessibleDockWidget(dockWidget());
 }
 
-QString QAccessibleTextEdit::textAfterOffset(int offset, BoundaryType boundaryType,
-        int *startOffset, int *endOffset)
+QAccessibleInterface *QAccessibleTitleBar::child(int index) const
 {
-    // TODO - what exactly is after?
-    Q_UNUSED(offset);
-    Q_UNUSED(boundaryType);
-    Q_UNUSED(startOffset);
-    Q_UNUSED(endOffset);
-    return QString();
+    if (index >= 0) {
+        QDockWidgetLayout *layout = dockWidgetLayout();
+        int role;
+        int currentIndex = 0;
+        for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
+            QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
+            if (!w || !w->isVisible())
+                continue;
+            if (currentIndex == index)
+                return QAccessible::queryAccessibleInterface(w);
+            ++currentIndex;
+        }
+    }
+    return 0;
 }
 
-QString QAccessibleTextEdit::textAtOffset(int offset, BoundaryType boundaryType,
-                                          int *startOffset, int *endOffset)
+int QAccessibleTitleBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
 {
-    Q_ASSERT(startOffset);
-    Q_ASSERT(endOffset);
-
-    *startOffset = *endOffset = -1;
-    QTextEdit *edit = textEdit();
-
-    QTextCursor cursor(edit->document());
-    if (offset >= characterCount())
-        return QString();
-
-    cursor.setPosition(offset);
-    switch (boundaryType) {
-    case CharBoundary:
-        *startOffset = cursor.position();
-        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
-        *endOffset = cursor.position();
-        break;
-    case WordBoundary:
-        cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
-        *startOffset = cursor.position();
-        cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
-        *endOffset = cursor.position();
-        break;
-    case SentenceBoundary:
-        // TODO - what's a sentence?
-        return QString();
-    case LineBoundary:
-        cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
-        *startOffset = cursor.position();
-        cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
-        *endOffset = cursor.position();
+    switch (relation) {
+    case Child:
+        *iface = child(entry - 1);
+        return *iface ? 0 : -1;
+    case FocusChild:
+        // ###
+        if (entry >= 1) {
+            QDockWidgetLayout *layout = dockWidgetLayout();
+            int index = 1;
+            int role;
+            for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
+                QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
+                if (!w->isVisible())
+                    continue;
+                if (index == entry)
+                    break;
+                ++index;
+            }
+            *iface = 0;
+            return role > QDockWidgetLayout::FloatButton ? -1 : index;
+        }
         break;
-    case ParagraphBoundary:
-        cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
-        *startOffset = cursor.position();
-        cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
-        *endOffset = cursor.position();
+    case Ancestor:
+        *iface = parent();
+        return iface ? 0 : -1;
+    case Sibling:
+        return navigate(Child, entry, iface);
         break;
-    case NoBoundary: {
-        *startOffset = 0;
-        const QString txt = edit->toPlainText();
-        *endOffset = txt.count();
-        return txt; }
     default:
-        qDebug("AccessibleTextAdaptor::textAtOffset: Unknown boundary type %d", boundaryType);
-        return QString();
+        break;
     }
-
-    return cursor.selectedText();
+    *iface = 0;
+    return -1;
 }
 
-void QAccessibleTextEdit::removeSelection(int selectionIndex)
+QAccessible::Relation QAccessibleTitleBar::relationTo(int /*child*/,  const QAccessibleInterface * /*other*/, int /*otherChild*/) const
 {
-    if (selectionIndex != 0)
-        return;
-
-    QTextCursor cursor = textEdit()->textCursor();
-    cursor.clearSelection();
-    textEdit()->setTextCursor(cursor);
+    return Unrelated;   //###
 }
 
-void QAccessibleTextEdit::setCursorPosition(int position)
+int QAccessibleTitleBar::indexOfChild(const QAccessibleInterface * /*child*/) const
 {
-    QTextCursor cursor = textEdit()->textCursor();
-    cursor.setPosition(position);
-    textEdit()->setTextCursor(cursor);
+    return -1;
 }
 
-void QAccessibleTextEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
+int QAccessibleTitleBar::childCount() const
 {
-    if (selectionIndex != 0)
-        return;
-
-    QTextCursor cursor = textEdit()->textCursor();
-    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
-    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
-    textEdit()->setTextCursor(cursor);
+    QDockWidgetLayout *layout = dockWidgetLayout();
+    int count = 0;
+    for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
+        QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
+        if (w && w->isVisible())
+            ++count;
+    }
+    return count;
 }
 
-int QAccessibleTextEdit::characterCount()
+QString QAccessibleTitleBar::text(Text t, int child) const
 {
-    return textEdit()->toPlainText().count();
+    if (!child) {
+        if (t == Name || t == Value) {
+            return qt_accStripAmp(dockWidget()->windowTitle());
+        }
+    }
+    return QString();
 }
 
-void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
+QAccessible::State QAccessibleTitleBar::state(int child) const
 {
-    QTextEdit *edit = textEdit();
-
-    QTextCursor cursor(edit->document());
-    cursor.setPosition(startIndex);
-    QRect r = edit->cursorRect(cursor);
-
-    cursor.setPosition(endIndex);
-    r.setBottomRight(edit->cursorRect(cursor).bottomRight());
-
-    r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
-             r.y() + edit->verticalScrollBar()->value());
+    QAccessible::State state = Normal;
+    if (child) {
+        QDockWidgetLayout *layout = dockWidgetLayout();
+        QAbstractButton *b = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
+        if (b) {
+            if (b->isDown())
+                state |= Pressed;
+        }
+    } else {
+        QDockWidget *w = dockWidget();
+        if (w->testAttribute(Qt::WA_WState_Visible) == false)
+            state |= Invisible;
+        if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
+            state |= Focusable;
+        if (w->hasFocus())
+            state |= Focused;
+        if (!w->isEnabled())
+            state |= Unavailable;
+    }
 
-    // E V I L, but ensureVisible is not public
-    if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
-        qWarning("AccessibleTextEdit::scrollToSubstring failed!");
+    return state;
 }
 
-static QTextCursor cursorForRange(QTextEdit *textEdit, int startOffset, int endOffset)
+QRect QAccessibleTitleBar::rect(int child) const
 {
-    QTextCursor cursor(textEdit->document());
-    cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
-    cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+    bool mapToGlobal = true;
+    QRect rect;
+    if (child == 0) {
+        if (dockWidget()->isFloating()) {
+            rect = dockWidget()->frameGeometry();
+            if (dockWidget()->widget()) {
+                QPoint globalPos = dockWidget()->mapToGlobal(dockWidget()->widget()->rect().topLeft());
+                globalPos.ry()--;
+                rect.setBottom(globalPos.y());
+                mapToGlobal = false;
+            }
+        } else {
+            QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
+            rect = layout->titleArea();
+        }
+    }else if (child >= 1 && child <= childCount()) {
+        QDockWidgetLayout *layout = dockWidgetLayout();
+        int index = 1;
+        for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
+            QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
+            if (!w || !w->isVisible())
+                continue;
+            if (index == child) {
+                rect = w->geometry();
+                break;
+            }
+            ++index;
+        }
+    }
+    if (rect.isNull())
+        return rect;
 
-    return cursor;
+    if (mapToGlobal)
+        rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
+    return rect;
 }
 
-void QAccessibleTextEdit::copyText(int startOffset, int endOffset)
+int QAccessibleTitleBar::childAt(int x, int y) const
 {
-    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
-
-    if (!cursor.hasSelection())
-        return;
-
-//     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
+    for (int i = childCount(); i >= 0; --i) {
+        if (rect(i).contains(x,y))
+            return i;
+    }
+    return -1;
 }
 
-void QAccessibleTextEdit::deleteText(int startOffset, int endOffset)
+QObject *QAccessibleTitleBar::object() const
 {
-    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+    return 0;
+}
 
-    cursor.removeSelectedText();
+QDockWidgetLayout *QAccessibleTitleBar::dockWidgetLayout() const
+{
+    return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
 }
 
-void QAccessibleTextEdit::insertText(int offset, const QString &text)
+QDockWidget *QAccessibleTitleBar::dockWidget() const
 {
-    QTextCursor cursor(textEdit()->document());
-    cursor.setPosition(offset);
+    return m_dockWidget;
+}
 
-    cursor.insertText(text);
+QString QAccessibleTitleBar::actionText(int action, Text t, int child) const
+{
+    QString str;
+    if (child >= 1 && child <= childCount()) {
+        if (t == Name) {
+            switch (action) {
+            case Press:
+            case DefaultAction:
+                if (child == QDockWidgetLayout::CloseButton) {
+                    str = QDockWidget::tr("Close");
+                } else if (child == QDockWidgetLayout::FloatButton) {
+                    str = dockWidget()->isFloating() ? QDockWidget::tr("Dock")
+                                                     : QDockWidget::tr("Float");
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    return str;
 }
 
-void QAccessibleTextEdit::cutText(int startOffset, int endOffset)
+bool QAccessibleTitleBar::doAction(int action, int child, const QVariantList& /*params*/)
 {
-    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
+    if (!child || !dockWidget()->isEnabled())
+        return false;
 
-    if (!cursor.hasSelection())
-        return;
+    switch (action) {
+    case DefaultAction:
+    case Press: {
+        QDockWidgetLayout *layout = dockWidgetLayout();
+        QAbstractButton *btn = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
+        if (btn)
+            btn->animateClick();
+        return true;
+        break;}
+    default:
+        break;
+    }
 
-//     QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
-    cursor.removeSelectedText();
+    return false;
 }
 
-void QAccessibleTextEdit::pasteText(int offset)
+int QAccessibleTitleBar::userActionCount (int /*child*/) const
 {
-    QTextEdit *edit = textEdit();
+    return 0;
+}
 
-    QTextCursor oldCursor = edit->textCursor();
-    QTextCursor newCursor = oldCursor;
-    newCursor.setPosition(offset);
+QAccessible::Role QAccessibleTitleBar::role(int child) const
+{
+    switch (child) {
+        case 0:
+            return TitleBar;
+            break;
+        default:
+            if (child >= 1 && child <= childCount())
+                return PushButton;
+            break;
+    }
 
-    edit->setTextCursor(newCursor);
-#ifndef QT_NO_CLIPBOARD
-    edit->paste();
-#endif
-    edit->setTextCursor(oldCursor);
+    return NoRole;
 }
 
-void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QString &text)
+void QAccessibleTitleBar::setText(Text /*t*/, int /*child*/, const QString &/*text*/)
 {
-    QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
 
-    cursor.removeSelectedText();
-    cursor.insertText(text);
 }
 
-void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes)
+bool QAccessibleTitleBar::isValid() const
 {
-    // TODO
-    Q_UNUSED(startOffset);
-    Q_UNUSED(endOffset);
-    Q_UNUSED(attributes);
+    return dockWidget();
 }
 
-#endif // QT_NO_TEXTEDIT
+#endif // QT_NO_DOCKWIDGET
 
 #ifndef QT_NO_MAINWINDOW
 QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
index 6cb3172..bf3c769 100644 (file)
@@ -75,15 +75,9 @@ public:
 
     QString text(Text t, int child) const;
     void setText(Text t, int control, const QString &text);
-    Role role(int child) const;
 
     QVariant invokeMethod(QAccessible::Method method, int child, const QVariantList &params);
 
-    QRect rect(int child) const;
-    int childAt(int x, int y) const;
-
-    int childCount() const;
-
     // QAccessibleTextInterface
     void addSelection(int startOffset, int endOffset);
     QString attributes(int offset, int *startOffset, int *endOffset);
index b00a0e8..4fb2106 100644 (file)
@@ -1773,16 +1773,12 @@ void tst_QAccessibility::textEditTest()
 
     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
     QCOMPARE(iface->text(QAccessible::Value, 0), text);
-    QCOMPARE(iface->childCount(), 6);
-    QCOMPARE(iface->text(QAccessible::Value, 4), QString("hello world"));
-    QCOMPARE(iface->text(QAccessible::Value, 5), QString("how are you today?"));
     QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
     QCOMPARE(startOffset, 6);
     QCOMPARE(endOffset, 11);
     QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
     QCOMPARE(startOffset, 12);
     QCOMPARE(endOffset, 30);
-    QCOMPARE(iface->text(QAccessible::Value, 6), QString());
     QCOMPARE(iface->textInterface()->characterCount(), 31);
     QFontMetrics fm(edit.font());
     QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
@@ -1800,14 +1796,19 @@ void tst_QAccessibility::textBrowserTest()
     textBrowser.setText(text);
     textBrowser.show();
 
-    QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textBrowser);
-    QVERIFY(interface);
-    QCOMPARE(interface->role(0), QAccessible::StaticText);
-    QCOMPARE(interface->text(QAccessible::Value, 0), text);
-    QCOMPARE(interface->childCount(), 6);
-    QCOMPARE(interface->text(QAccessible::Value, 4), QString("Hello world"));
-    QCOMPARE(interface->text(QAccessible::Value, 5), QString("how are you today?"));
-    QCOMPARE(interface->text(QAccessible::Value, 6), QString());
+    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
+    QVERIFY(iface);
+    QCOMPARE(iface->role(0), QAccessible::StaticText);
+    QCOMPARE(iface->text(QAccessible::Value, 0), text);
+    int startOffset;
+    int endOffset;
+    QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
+    QCOMPARE(startOffset, 6);
+    QCOMPARE(endOffset, 11);
+    QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
+    QCOMPARE(startOffset, 12);
+    QCOMPARE(endOffset, 30);
+    QCOMPARE(iface->textInterface()->characterCount(), 31);
     }
     QTestAccessibility::clearEvents();
 }