summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/accessible/accessible.pri21
-rw-r--r--src/widgets/accessible/complexwidgets.cpp459
-rw-r--r--src/widgets/accessible/complexwidgets.h145
-rw-r--r--src/widgets/accessible/itemviews.cpp1222
-rw-r--r--src/widgets/accessible/itemviews.h292
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp377
-rw-r--r--src/widgets/accessible/qaccessiblemenu.h131
-rw-r--r--src/widgets/accessible/qaccessiblewidget.cpp4
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory.cpp241
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory_p.h53
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp1019
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.h314
-rw-r--r--src/widgets/accessible/rangecontrols.cpp323
-rw-r--r--src/widgets/accessible/rangecontrols.h160
-rw-r--r--src/widgets/accessible/simplewidgets.cpp886
-rw-r--r--src/widgets/accessible/simplewidgets.h215
-rw-r--r--src/widgets/accessible/widgets.pro26
-rw-r--r--src/widgets/kernel/qapplication.cpp6
-rw-r--r--src/widgets/widgets.pro3
19 files changed, 5890 insertions, 7 deletions
diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri
index 9fb2f18950..bcdfbd639c 100644
--- a/src/widgets/accessible/accessible.pri
+++ b/src/widgets/accessible/accessible.pri
@@ -1,6 +1,23 @@
# Qt accessibility module
contains(QT_CONFIG, accessibility) {
- HEADERS += accessible/qaccessiblewidget.h
- SOURCES += accessible/qaccessiblewidget.cpp
+ HEADERS += \
+ accessible/qaccessiblewidget.h \
+ accessible/qaccessiblewidgetfactory_p.h \
+ accessible/complexwidgets.h \
+ accessible/itemviews.h \
+ accessible/qaccessiblemenu.h \
+ accessible/qaccessiblewidgets.h \
+ accessible/rangecontrols.h \
+ accessible/simplewidgets.h
+
+ SOURCES += \
+ accessible/qaccessiblewidget.cpp \
+ accessible/qaccessiblewidgetfactory.cpp \
+ accessible/complexwidgets.cpp \
+ accessible/itemviews.cpp \
+ accessible/qaccessiblemenu.cpp \
+ accessible/qaccessiblewidgets.cpp \
+ accessible/rangecontrols.cpp \
+ accessible/simplewidgets.cpp
}
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
new file mode 100644
index 0000000000..5d76ecafbc
--- /dev/null
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "complexwidgets.h"
+
+#include <qaccessible.h>
+#include <qapplication.h>
+#include <qabstractbutton.h>
+#include <qevent.h>
+#include <qheaderview.h>
+#include <qtabbar.h>
+#include <qcombobox.h>
+#include <qlistview.h>
+#include <qtableview.h>
+#include <qlineedit.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qtreeview.h>
+#include <private/qtabbar_p.h>
+#include <QAbstractScrollArea>
+#include <QScrollArea>
+#include <QScrollBar>
+#include <QDebug>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QString qt_accStripAmp(const QString &text);
+
+#ifndef QT_NO_TABBAR
+/*!
+ \class QAccessibleTabBar
+ \brief The QAccessibleTabBar class implements the QAccessibleInterface for tab bars.
+ \internal
+
+ \ingroup accessibility
+*/
+
+class QAccessibleTabButton: public QAccessibleInterface, public QAccessibleActionInterface
+{
+public:
+ QAccessibleTabButton(QTabBar *parent, int index)
+ : m_parent(parent), m_index(index)
+ {}
+
+ void *interface_cast(QAccessible::InterfaceType t) {
+ if (t == QAccessible::ActionInterface) {
+ return static_cast<QAccessibleActionInterface*>(this);
+ }
+ return 0;
+ }
+
+ QObject *object() const { return 0; }
+ QAccessible::Role role() const { return QAccessible::PageTab; }
+ QAccessible::State state() const {
+ QAccessibleInterface *parentInterface = parent();
+ QAccessible::State state = parentInterface->state();
+ return state;
+ }
+ QRect rect() const {
+ if (!isValid())
+ return QRect();
+
+ QPoint tp = m_parent->mapToGlobal(QPoint(0,0));
+ QRect rec = m_parent->tabRect(m_index);
+ rec = QRect(tp.x() + rec.x(), tp.y() + rec.y(), rec.width(), rec.height());
+ return rec;
+ }
+
+ bool isValid() const { return true; }// (!m_parent.isNull()) && m_parent->count() > m_index; }
+
+ QAccessibleInterface *childAt(int, int) const { return 0; }
+ int childCount() const { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const { return -1; }
+
+ QString text(QAccessible::Text) const { return qt_accStripAmp(m_parent->tabText(m_index)); }
+ void setText(QAccessible::Text, const QString &) {}
+
+ QAccessibleInterface *parent() const {
+ return QAccessible::queryAccessibleInterface(m_parent);
+ }
+ QAccessibleInterface *child(int) const { return 0; }
+ // action interface
+ QStringList actionNames() const
+ {
+ return QStringList(pressAction());
+ }
+
+ void doAction(const QString &actionName)
+ {
+ if (actionName == pressAction())
+ m_parent->setCurrentIndex(m_index);
+ }
+
+ QStringList keyBindingsForAction(const QString &) const
+ {
+ return QStringList();
+ }
+
+ int index() const { return m_index; }
+
+private:
+ QPointer<QTabBar> m_parent;
+ int m_index;
+
+};
+
+/*!
+ Constructs a QAccessibleTabBar object for \a w.
+*/
+QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
+: QAccessibleWidget(w, QAccessible::PageTabList)
+{
+ Q_ASSERT(tabBar());
+}
+
+QAccessibleTabBar::~QAccessibleTabBar()
+{
+ foreach (QAccessible::Id id, m_childInterfaces.values())
+ QAccessible::deleteAccessibleInterface(id);
+}
+
+/*! Returns the QTabBar. */
+QTabBar *QAccessibleTabBar::tabBar() const
+{
+ return qobject_cast<QTabBar*>(object());
+}
+
+QAccessibleInterface* QAccessibleTabBar::child(int index) const
+{
+ if (QAccessible::Id id = m_childInterfaces.value(index))
+ return QAccessible::accessibleInterface(id);
+
+ // first the tabs, then 2 buttons
+ if (index < tabBar()->count()) {
+ QAccessibleTabButton *button = new QAccessibleTabButton(tabBar(), index);
+ QAccessible::registerAccessibleInterface(button);
+ m_childInterfaces.insert(index, QAccessible::uniqueId(button));
+ return button;
+ } else if (index >= tabBar()->count()) {
+ // left button
+ if (index - tabBar()->count() == 0) {
+ return QAccessible::queryAccessibleInterface(tabBar()->d_func()->leftB);
+ }
+ // right button
+ if (index - tabBar()->count() == 1) {
+ return QAccessible::queryAccessibleInterface(tabBar()->d_func()->rightB);
+ }
+ }
+ return 0;
+}
+
+int QAccessibleTabBar::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child->object() && child->object() == tabBar()->d_func()->leftB)
+ return tabBar()->count();
+ if (child->object() && child->object() == tabBar()->d_func()->rightB)
+ return tabBar()->count() + 1;
+ if (child->role() == QAccessible::PageTab) {
+ QAccessibleInterface *parent = child->parent();
+ if (parent == this) {
+ const QAccessibleTabButton *tabButton = static_cast<const QAccessibleTabButton *>(child);
+ return tabButton->index();
+ }
+ }
+ return -1;
+}
+
+int QAccessibleTabBar::childCount() const
+{
+ // tabs + scroll buttons
+ return tabBar()->count() + 2;
+}
+
+QString QAccessibleTabBar::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Name) {
+ return qt_accStripAmp(tabBar()->tabText(tabBar()->currentIndex()));
+ }
+ return QString();
+}
+
+#endif // QT_NO_TABBAR
+
+#ifndef QT_NO_COMBOBOX
+/*!
+ \class QAccessibleComboBox
+ \brief The QAccessibleComboBox class implements the QAccessibleInterface for editable and read-only combo boxes.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleComboBox object for \a w.
+*/
+QAccessibleComboBox::QAccessibleComboBox(QWidget *w)
+: QAccessibleWidget(w, QAccessible::ComboBox)
+{
+ Q_ASSERT(comboBox());
+}
+
+/*!
+ Returns the combobox.
+*/
+QComboBox *QAccessibleComboBox::comboBox() const
+{
+ return qobject_cast<QComboBox*>(object());
+}
+
+QAccessibleInterface *QAccessibleComboBox::child(int index) const
+{
+ if (index == 0) {
+ QAbstractItemView *view = comboBox()->view();
+ //QWidget *parent = view ? view->parentWidget() : 0;
+ return QAccessible::queryAccessibleInterface(view);
+ } else if (index == 1 && comboBox()->isEditable()) {
+ return QAccessible::queryAccessibleInterface(comboBox()->lineEdit());
+ }
+ return 0;
+}
+
+int QAccessibleComboBox::childCount() const
+{
+ // list and text edit
+ return comboBox()->isEditable() ? 2 : 1;
+}
+
+QAccessibleInterface *QAccessibleComboBox::childAt(int x, int y) const
+{
+ if (comboBox()->isEditable() && comboBox()->lineEdit()->rect().contains(x, y))
+ return child(1);
+ return 0;
+}
+
+int QAccessibleComboBox::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (comboBox()->view() == child->object())
+ return 0;
+ if (comboBox()->isEditable() && comboBox()->lineEdit() == child->object())
+ return 1;
+ return -1;
+}
+
+/*! \reimp */
+QString QAccessibleComboBox::text(QAccessible::Text t) const
+{
+ QString str;
+
+ switch (t) {
+ case QAccessible::Name:
+#ifndef Q_OS_UNIX // on Linux we use relations for this, name is text (fall through to Value)
+ str = QAccessibleWidget::text(t);
+ break;
+#endif
+ case QAccessible::Value:
+ if (comboBox()->isEditable())
+ str = comboBox()->lineEdit()->text();
+ else
+ str = comboBox()->currentText();
+ break;
+#ifndef QT_NO_SHORTCUT
+ case QAccessible::Accelerator:
+ str = QKeySequence(Qt::Key_Down).toString(QKeySequence::NativeText);
+ break;
+#endif
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return str;
+}
+
+QStringList QAccessibleComboBox::actionNames() const
+{
+ return QStringList(showMenuAction());
+}
+
+QString QAccessibleComboBox::localizedActionDescription(const QString &actionName) const
+{
+ if (actionName == showMenuAction())
+ return QComboBox::tr("Open the combo box selection popup");
+ return QString();
+}
+
+void QAccessibleComboBox::doAction(const QString &actionName)
+{
+ if (actionName == showMenuAction()) {
+ if (comboBox()->view()->isVisible()) {
+ comboBox()->hidePopup();
+ } else {
+ comboBox()->showPopup();
+ }
+ }
+}
+
+QStringList QAccessibleComboBox::keyBindingsForAction(const QString &/*actionName*/) const
+{
+ return QStringList();
+}
+
+#endif // QT_NO_COMBOBOX
+
+#ifndef QT_NO_SCROLLAREA
+// ======================= QAccessibleAbstractScrollArea =======================
+QAccessibleAbstractScrollArea::QAccessibleAbstractScrollArea(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Client)
+{
+ Q_ASSERT(qobject_cast<QAbstractScrollArea *>(widget));
+}
+
+QAccessibleInterface *QAccessibleAbstractScrollArea::child(int index) const
+{
+ return QAccessible::queryAccessibleInterface(accessibleChildren().at(index));
+}
+
+int QAccessibleAbstractScrollArea::childCount() const
+{
+ return accessibleChildren().count();
+}
+
+int QAccessibleAbstractScrollArea::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object())
+ return -1;
+ return accessibleChildren().indexOf(qobject_cast<QWidget *>(child->object()));
+}
+
+bool QAccessibleAbstractScrollArea::isValid() const
+{
+ return (QAccessibleWidget::isValid() && abstractScrollArea() && abstractScrollArea()->viewport());
+}
+
+QAccessibleInterface *QAccessibleAbstractScrollArea::childAt(int x, int y) const
+{
+ if (!abstractScrollArea()->isVisible())
+ return 0;
+
+ for (int i = 0; i < childCount(); ++i) {
+ QPoint wpos = accessibleChildren().at(i)->mapToGlobal(QPoint(0, 0));
+ QRect rect = QRect(wpos, accessibleChildren().at(i)->size());
+ if (rect.contains(x, y))
+ return child(i);
+ }
+ return 0;
+}
+
+QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea() const
+{
+ return static_cast<QAbstractScrollArea *>(object());
+}
+
+QWidgetList QAccessibleAbstractScrollArea::accessibleChildren() const
+{
+ QWidgetList children;
+
+ // Viewport.
+ QWidget * viewport = abstractScrollArea()->viewport();
+ if (viewport)
+ children.append(viewport);
+
+ // Horizontal scrollBar container.
+ QScrollBar *horizontalScrollBar = abstractScrollArea()->horizontalScrollBar();
+ if (horizontalScrollBar && horizontalScrollBar->isVisible()) {
+ children.append(horizontalScrollBar->parentWidget());
+ }
+
+ // Vertical scrollBar container.
+ QScrollBar *verticalScrollBar = abstractScrollArea()->verticalScrollBar();
+ if (verticalScrollBar && verticalScrollBar->isVisible()) {
+ children.append(verticalScrollBar->parentWidget());
+ }
+
+ // CornerWidget.
+ QWidget *cornerWidget = abstractScrollArea()->cornerWidget();
+ if (cornerWidget && cornerWidget->isVisible())
+ children.append(cornerWidget);
+
+ return children;
+}
+
+QAccessibleAbstractScrollArea::AbstractScrollAreaElement
+QAccessibleAbstractScrollArea::elementType(QWidget *widget) const
+{
+ if (!widget)
+ return Undefined;
+
+ if (widget == abstractScrollArea())
+ return Self;
+ if (widget == abstractScrollArea()->viewport())
+ return Viewport;
+ if (widget->objectName() == QLatin1String("qt_scrollarea_hcontainer"))
+ return HorizontalContainer;
+ if (widget->objectName() == QLatin1String("qt_scrollarea_vcontainer"))
+ return VerticalContainer;
+ if (widget == abstractScrollArea()->cornerWidget())
+ return CornerWidget;
+
+ return Undefined;
+}
+
+bool QAccessibleAbstractScrollArea::isLeftToRight() const
+{
+ return abstractScrollArea()->isLeftToRight();
+}
+
+// ======================= QAccessibleScrollArea ===========================
+QAccessibleScrollArea::QAccessibleScrollArea(QWidget *widget)
+ : QAccessibleAbstractScrollArea(widget)
+{
+ Q_ASSERT(qobject_cast<QScrollArea *>(widget));
+}
+#endif // QT_NO_SCROLLAREA
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/complexwidgets.h b/src/widgets/accessible/complexwidgets.h
new file mode 100644
index 0000000000..00186282f3
--- /dev/null
+++ b/src/widgets/accessible/complexwidgets.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMPLEXWIDGETS_H
+#define COMPLEXWIDGETS_H
+
+#include <QtCore/qpointer.h>
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtWidgets/qabstractitemview.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractButton;
+class QHeaderView;
+class QTabBar;
+class QComboBox;
+class QTitleBar;
+class QAbstractScrollArea;
+class QScrollArea;
+
+#ifndef QT_NO_SCROLLAREA
+class QAccessibleAbstractScrollArea : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleAbstractScrollArea(QWidget *widget);
+
+ enum AbstractScrollAreaElement {
+ Self = 0,
+ Viewport,
+ HorizontalContainer,
+ VerticalContainer,
+ CornerWidget,
+ Undefined
+ };
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+
+//protected:
+ QAbstractScrollArea *abstractScrollArea() const;
+
+private:
+ QWidgetList accessibleChildren() const;
+ AbstractScrollAreaElement elementType(QWidget *widget) const;
+ bool isLeftToRight() const;
+};
+
+class QAccessibleScrollArea : public QAccessibleAbstractScrollArea
+{
+public:
+ explicit QAccessibleScrollArea(QWidget *widget);
+};
+#endif // QT_NO_SCROLLAREA
+
+#ifndef QT_NO_TABBAR
+class QAccessibleTabBar : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleTabBar(QWidget *w);
+ ~QAccessibleTabBar();
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface* child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QTabBar *tabBar() const;
+ mutable QHash<int, QAccessible::Id> m_childInterfaces;
+};
+#endif // QT_NO_TABBAR
+
+#ifndef QT_NO_COMBOBOX
+class QAccessibleComboBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleComboBox(QWidget *w);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface* child(int index) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ QString localizedActionDescription(const QString &actionName) const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+protected:
+ QComboBox *comboBox() const;
+};
+#endif // QT_NO_COMBOBOX
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // COMPLEXWIDGETS_H
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
new file mode 100644
index 0000000000..81736fc1c6
--- /dev/null
+++ b/src/widgets/accessible/itemviews.cpp
@@ -0,0 +1,1222 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemviews.h"
+
+#include <qheaderview.h>
+#include <qtableview.h>
+#include <qlistview.h>
+#include <qtreeview.h>
+#include <private/qtreewidget_p.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QString qt_accStripAmp(const QString &text);
+
+#ifndef QT_NO_ITEMVIEWS
+/*
+Implementation of the IAccessible2 table2 interface. Much simpler than
+the other table interfaces since there is only the main table and cells:
+
+TABLE/LIST/TREE
+ |- HEADER CELL
+ |- CELL
+ |- CELL
+ ...
+*/
+
+
+QAbstractItemView *QAccessibleTable::view() const
+{
+ return qobject_cast<QAbstractItemView*>(object());
+}
+
+int QAccessibleTable::logicalIndex(const QModelIndex &index) const
+{
+ if (!view()->model() || !index.isValid())
+ return -1;
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader);
+}
+
+QAccessibleTable::QAccessibleTable(QWidget *w)
+ : QAccessibleObject(w)
+{
+ Q_ASSERT(view());
+
+ if (qobject_cast<const QTableView*>(view())) {
+ m_role = QAccessible::Table;
+ } else if (qobject_cast<const QTreeView*>(view())) {
+ m_role = QAccessible::Tree;
+ } else if (qobject_cast<const QListView*>(view())) {
+ m_role = QAccessible::List;
+ } else {
+ // is this our best guess?
+ m_role = QAccessible::Table;
+ }
+}
+
+bool QAccessibleTable::isValid() const
+{
+ return (view() && !qobject_cast<QWidget*>(view())->d_func()->data.in_destructor);
+}
+
+QAccessibleTable::~QAccessibleTable()
+{
+ Q_FOREACH (QAccessible::Id id, childToId.values())
+ QAccessible::deleteAccessibleInterface(id);
+}
+
+QHeaderView *QAccessibleTable::horizontalHeader() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
+ header = tv->horizontalHeader();
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view())) {
+ header = tv->header();
+#endif
+ }
+ return header;
+}
+
+QHeaderView *QAccessibleTable::verticalHeader() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view())) {
+ header = tv->verticalHeader();
+#endif
+ }
+ return header;
+}
+
+QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const
+{
+ if (!view()->model())
+ return 0;
+ Q_ASSERT(role() != QAccessible::Tree);
+ QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
+ if (!index.isValid()) {
+ qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << view();
+ return 0;
+ }
+ return child(logicalIndex(index));
+}
+
+QAccessibleInterface *QAccessibleTable::caption() const
+{
+ return 0;
+}
+
+QString QAccessibleTable::columnDescription(int column) const
+{
+ if (!view()->model())
+ return QString();
+ return view()->model()->headerData(column, Qt::Horizontal).toString();
+}
+
+int QAccessibleTable::columnCount() const
+{
+ if (!view()->model())
+ return 0;
+ return view()->model()->columnCount();
+}
+
+int QAccessibleTable::rowCount() const
+{
+ if (!view()->model())
+ return 0;
+ return view()->model()->rowCount();
+}
+
+int QAccessibleTable::selectedCellCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedIndexes().count();
+}
+
+int QAccessibleTable::selectedColumnCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedColumns().count();
+}
+
+int QAccessibleTable::selectedRowCount() const
+{
+ if (!view()->selectionModel())
+ return 0;
+ return view()->selectionModel()->selectedRows().count();
+}
+
+QString QAccessibleTable::rowDescription(int row) const
+{
+ if (!view()->model())
+ return QString();
+ return view()->model()->headerData(row, Qt::Vertical).toString();
+}
+
+QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const
+{
+ QList<QAccessibleInterface*> cells;
+ if (!view()->selectionModel())
+ return cells;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes())
+ cells.append(child(logicalIndex(index)));
+ return cells;
+}
+
+QList<int> QAccessibleTable::selectedColumns() const
+{
+ if (!view()->selectionModel())
+ return QList<int>();
+ QList<int> columns;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedColumns()) {
+ columns.append(index.column());
+ }
+ return columns;
+}
+
+QList<int> QAccessibleTable::selectedRows() const
+{
+ if (!view()->selectionModel())
+ return QList<int>();
+ QList<int> rows;
+ Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedRows()) {
+ rows.append(index.row());
+ }
+ return rows;
+}
+
+QAccessibleInterface *QAccessibleTable::summary() const
+{
+ return 0;
+}
+
+bool QAccessibleTable::isColumnSelected(int column) const
+{
+ if (!view()->selectionModel())
+ return false;
+ return view()->selectionModel()->isColumnSelected(column, QModelIndex());
+}
+
+bool QAccessibleTable::isRowSelected(int row) const
+{
+ if (!view()->selectionModel())
+ return false;
+ return view()->selectionModel()->isRowSelected(row, QModelIndex());
+}
+
+bool QAccessibleTable::selectRow(int row)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+ QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ return true;
+}
+
+bool QAccessibleTable::selectColumn(int column)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+ QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectRows)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1)
+ return false;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Columns);
+ return true;
+}
+
+bool QAccessibleTable::unselectRow(int row)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+
+ QModelIndex index = view()->model()->index(row, 0, view()->rootIndex());
+ if (!index.isValid())
+ return false;
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedRowCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedRowCount() == 1)
+ return false;
+
+ if ((!row || view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) {
+ //If there are rows selected both up the current row and down the current rown,
+ //the ones which are down the current row will be deselected
+ selection = QItemSelection(index, view()->model()->index(rowCount() - 1, 0, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
+ return true;
+}
+
+bool QAccessibleTable::unselectColumn(int column)
+{
+ if (!view()->model() || !view()->selectionModel())
+ return false;
+
+ QModelIndex index = view()->model()->index(0, column, view()->rootIndex());
+ if (!index.isValid())
+ return false;
+
+ QItemSelection selection(index, index);
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::SingleSelection:
+ //In SingleSelection and ContiguousSelection once an item
+ //is selected, there's no way for the user to unselect all items
+ if (selectedColumnCount() == 1)
+ return false;
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if (selectedColumnCount() == 1)
+ return false;
+
+ if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
+ && view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
+ //If there are columns selected both at the left of the current row and at the right
+ //of the current rown, the ones which are at the right will be deselected
+ selection = QItemSelection(index, view()->model()->index(0, columnCount() - 1, view()->rootIndex()));
+ }
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(selection, QItemSelectionModel::Deselect | QItemSelectionModel::Columns);
+ return true;
+}
+
+QAccessible::Role QAccessibleTable::role() const
+{
+ return m_role;
+}
+
+QAccessible::State QAccessibleTable::state() const
+{
+ return QAccessible::State();
+}
+
+QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const
+{
+ QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
+ QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
+ // FIXME: if indexPosition < 0 in one coordinate, return header
+
+ QModelIndex index = view()->indexAt(indexPosition);
+ if (index.isValid()) {
+ return child(logicalIndex(index));
+ }
+ return 0;
+}
+
+int QAccessibleTable::childCount() const
+{
+ if (!view()->model())
+ return 0;
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (view()->model()->rowCount()+hHeader) * (view()->model()->columnCount()+vHeader);
+}
+
+int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const
+{
+ if (!view()->model())
+ return -1;
+ QAccessibleInterface *parent = iface->parent();
+ if (parent->object() != view())
+ return -1;
+
+ Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface);
+ return logicalIndex(cell->m_index);
+ } else if (iface->role() == QAccessible::ColumnHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return cell->index + (verticalHeader() ? 1 : 0);
+ } else if (iface->role() == QAccessible::RowHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return (cell->index + 1) * (view()->model()->columnCount() + 1);
+ } else if (iface->role() == QAccessible::Pane) {
+ return 0; // corner button
+ } else {
+ qWarning() << "WARNING QAccessibleTable::indexOfChild Fix my children..."
+ << iface->role() << iface->text(QAccessible::Name);
+ }
+ // FIXME: we are in denial of our children. this should stop.
+ return -1;
+}
+
+QString QAccessibleTable::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Description)
+ return view()->accessibleDescription();
+ return view()->accessibleName();
+}
+
+QRect QAccessibleTable::rect() const
+{
+ if (!view()->isVisible())
+ return QRect();
+ QPoint pos = view()->mapToGlobal(QPoint(0, 0));
+ return QRect(pos.x(), pos.y(), view()->width(), view()->height());
+}
+
+QAccessibleInterface *QAccessibleTable::parent() const
+{
+ if (view() && view()->parent()) {
+ if (qstrcmp("QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
+ return QAccessible::queryAccessibleInterface(view()->parent()->parent());
+ }
+ return QAccessible::queryAccessibleInterface(view()->parent());
+ }
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleTable::child(int logicalIndex) const
+{
+ if (!view()->model())
+ return 0;
+
+ if (childToId.contains(logicalIndex)) {
+ QAccessible::Id id = childToId.value(logicalIndex);
+ return QAccessible::accessibleInterface(id);
+ }
+
+ int vHeader = verticalHeader() ? 1 : 0;
+ int hHeader = horizontalHeader() ? 1 : 0;
+
+ int columns = view()->model()->columnCount() + vHeader;
+
+ int row = logicalIndex / columns;
+ int column = logicalIndex % columns;
+
+ QAccessibleInterface *iface = 0;
+
+ if (vHeader) {
+ if (column == 0) {
+ if (hHeader && row == 0) {
+ iface = new QAccessibleTableCornerButton(view());
+ } else {
+ iface = new QAccessibleTableHeaderCell(view(), row - hHeader, Qt::Vertical);
+ }
+ }
+ --column;
+ }
+ if (!iface && hHeader) {
+ if (row == 0) {
+ iface = new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal);
+ }
+ --row;
+ }
+
+ if (!iface) {
+ QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
+ if (!index.isValid()) {
+ qWarning() << "QAccessibleTable::child: Invalid index at: " << row << column;
+ return 0;
+ }
+ iface = new QAccessibleTableCell(view(), index, cellRole());
+ }
+
+ QAccessible::registerAccessibleInterface(iface);
+ childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
+ return iface;
+}
+
+void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TableInterface)
+ return static_cast<QAccessibleTableInterface*>(this);
+ return 0;
+}
+
+void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
+{
+ // if there is no cache yet, we don't update anything
+ if (childToId.isEmpty())
+ return;
+
+ switch (event->modelChangeType()) {
+ case QAccessibleTableModelChangeEvent::ModelReset:
+ Q_FOREACH (QAccessible::Id id, childToId.values())
+ QAccessible::deleteAccessibleInterface(id);
+ childToId.clear();
+ break;
+
+ // rows are inserted: move every row after that
+ case QAccessibleTableModelChangeEvent::RowsInserted:
+ case QAccessibleTableModelChangeEvent::ColumnsInserted: {
+ int newRows = event->lastRow() - event->firstRow() + 1;
+ int newColumns = event->lastColumn() - event->firstColumn() + 1;
+
+ ChildCache newCache;
+ ChildCache::ConstIterator iter = childToId.constBegin();
+
+ while (iter != childToId.constEnd()) {
+ QAccessible::Id id = iter.value();
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
+ Q_ASSERT(iface);
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ Q_ASSERT(iface->tableCellInterface());
+ QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
+ if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
+ && cell->m_index.row() >= event->firstRow()) {
+ int newRow = cell->m_index.row() + newRows;
+ cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
+ && cell->m_index.column() >= event->firstColumn()) {
+ int newColumn = cell->m_index.column() + newColumns;
+ cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted
+ && iface->role() == QAccessible::RowHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index >= event->firstRow()) {
+ cell->index += newRows;
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted
+ && iface->role() == QAccessible::ColumnHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index >= event->firstColumn()) {
+ cell->index += newColumns;
+ }
+ }
+ if (indexOfChild(iface) >= 0) {
+ newCache.insert(indexOfChild(iface), id);
+ } else {
+ // ### This should really not happen,
+ // but it might if the view has a root index set.
+ // This needs to be fixed.
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ ++iter;
+ }
+ childToId = newCache;
+ break;
+ }
+
+ case QAccessibleTableModelChangeEvent::ColumnsRemoved:
+ case QAccessibleTableModelChangeEvent::RowsRemoved: {
+ int deletedColumns = event->lastColumn() - event->firstColumn() + 1;
+ int deletedRows = event->lastRow() - event->firstRow() + 1;
+ ChildCache newCache;
+ ChildCache::ConstIterator iter = childToId.constBegin();
+ while (iter != childToId.constEnd()) {
+ QAccessible::Id id = iter.value();
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
+ Q_ASSERT(iface);
+ if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
+ Q_ASSERT(iface->tableCellInterface());
+ QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface());
+ if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved) {
+ if (cell->m_index.row() < event->firstRow()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->m_index.row() > event->lastRow()) {
+ int newRow = cell->m_index.row() - deletedRows;
+ cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column());
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved) {
+ if (cell->m_index.column() < event->firstColumn()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->m_index.column() > event->lastColumn()) {
+ int newColumn = cell->m_index.column() - deletedColumns;
+ cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn);
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved
+ && iface->role() == QAccessible::RowHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index < event->firstRow()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->index > event->lastRow()) {
+ cell->index -= deletedRows;
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved
+ && iface->role() == QAccessible::ColumnHeader) {
+ QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface);
+ if (cell->index < event->firstColumn()) {
+ newCache.insert(indexOfChild(cell), id);
+ } else if (cell->index > event->lastColumn()) {
+ cell->index -= deletedColumns;
+ newCache.insert(indexOfChild(cell), id);
+ } else {
+ QAccessible::deleteAccessibleInterface(id);
+ }
+ }
+ ++iter;
+ }
+ childToId = newCache;
+ break;
+ }
+
+ case QAccessibleTableModelChangeEvent::DataChanged:
+ // nothing to do in this case
+ break;
+ }
+}
+
+// TREE VIEW
+
+QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const
+{
+ if (!isValid() || !view()->model())
+ return QModelIndex();
+
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ if ((row < 0) || (column < 0) || (treeView->d_func()->viewItems.count() <= row)) {
+ qWarning() << "QAccessibleTree::indexFromLogical: invalid index: " << row << column << " for " << treeView;
+ return QModelIndex();
+ }
+ QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index;
+
+ if (modelIndex.isValid() && column > 0) {
+ modelIndex = view()->model()->index(modelIndex.row(), column, modelIndex.parent());
+ }
+ return modelIndex;
+}
+
+QAccessibleInterface *QAccessibleTree::childAt(int x, int y) const
+{
+ if (!view()->model())
+ return 0;
+ QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
+ QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
+
+ QModelIndex index = view()->indexAt(indexPosition);
+ if (!index.isValid())
+ return 0;
+
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
+ int column = index.column();
+
+ int i = row * view()->model()->columnCount() + column;
+ return child(i);
+}
+
+int QAccessibleTree::childCount() const
+{
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ if (!view()->model())
+ return 0;
+
+ int hHeader = horizontalHeader() ? 1 : 0;
+ return (treeView->d_func()->viewItems.count() + hHeader)* view()->model()->columnCount();
+}
+
+
+QAccessibleInterface *QAccessibleTree::child(int logicalIndex) const
+{
+ if (logicalIndex < 0 || !view()->model() || !view()->model()->columnCount())
+ return 0;
+
+ QAccessibleInterface *iface = 0;
+ int index = logicalIndex;
+
+ if (horizontalHeader()) {
+ if (index < view()->model()->columnCount()) {
+ iface = new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal);
+ } else {
+ index -= view()->model()->columnCount();
+ }
+ }
+
+ if (!iface) {
+ int row = index / view()->model()->columnCount();
+ int column = index % view()->model()->columnCount();
+ QModelIndex modelIndex = indexFromLogical(row, column);
+ if (!modelIndex.isValid())
+ return 0;
+ iface = new QAccessibleTableCell(view(), modelIndex, cellRole());
+ }
+ QAccessible::registerAccessibleInterface(iface);
+ // ### FIXME: get interfaces from the cache instead of re-creating them
+ return iface;
+}
+
+int QAccessibleTree::rowCount() const
+{
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ return treeView->d_func()->viewItems.count();
+}
+
+int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const
+{
+ if (!view()->model())
+ return -1;
+ QAccessibleInterface *parent = iface->parent();
+ if (parent->object() != view())
+ return -1;
+
+ if (iface->role() == QAccessible::TreeItem) {
+ const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface);
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0);
+ int column = cell->m_index.column();
+
+ int index = row * view()->model()->columnCount() + column;
+ return index;
+ } else if (iface->role() == QAccessible::ColumnHeader){
+ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface);
+ return cell->index;
+ } else {
+ qWarning() << "WARNING QAccessibleTable::indexOfChild invalid child"
+ << iface->role() << iface->text(QAccessible::Name);
+ }
+ // FIXME: add scrollbars and don't just ignore them
+ return -1;
+}
+
+QAccessibleInterface *QAccessibleTree::cellAt(int row, int column) const
+{
+ QModelIndex index = indexFromLogical(row, column);
+ if (!index.isValid()) {
+ qWarning() << "Requested invalid tree cell: " << row << column;
+ return 0;
+ }
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view());
+ Q_ASSERT(treeView);
+ int logicalIndex = treeView->d_func()->accessibleTable2Index(index);
+
+ return child(logicalIndex); // FIXME ### new QAccessibleTableCell(view(), index, cellRole());
+}
+
+QString QAccessibleTree::rowDescription(int) const
+{
+ return QString(); // no headers for rows in trees
+}
+
+bool QAccessibleTree::isRowSelected(int row) const
+{
+ if (!view()->selectionModel())
+ return false;
+ QModelIndex index = indexFromLogical(row);
+ return view()->selectionModel()->isRowSelected(index.row(), index.parent());
+}
+
+bool QAccessibleTree::selectRow(int row)
+{
+ if (!view()->selectionModel())
+ return false;
+ QModelIndex index = indexFromLogical(row);
+
+ if (!index.isValid() || view()->selectionBehavior() == QAbstractItemView::SelectColumns)
+ return false;
+
+ switch (view()->selectionMode()) {
+ case QAbstractItemView::NoSelection:
+ return false;
+ case QAbstractItemView::SingleSelection:
+ if ((view()->selectionBehavior() != QAbstractItemView::SelectRows) && (columnCount() > 1))
+ return false;
+ view()->clearSelection();
+ break;
+ case QAbstractItemView::ContiguousSelection:
+ if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex()))
+ && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex()))
+ view()->clearSelection();
+ break;
+ default:
+ break;
+ }
+
+ view()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ return true;
+}
+
+// TABLE CELL
+
+QAccessibleTableCell::QAccessibleTableCell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_)
+ : /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_)
+{
+ if (!index_.isValid())
+ qWarning() << "QAccessibleTableCell::QAccessibleTableCell with invalid index: " << index_;
+}
+
+void *QAccessibleTableCell::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TableCellInterface)
+ return static_cast<QAccessibleTableCellInterface*>(this);
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
+ return 0;
+}
+
+int QAccessibleTableCell::columnExtent() const { return 1; }
+int QAccessibleTableCell::rowExtent() const { return 1; }
+
+QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells() const
+{
+ QList<QAccessibleInterface*> headerCell;
+ if (verticalHeader()) {
+ // FIXME
+ headerCell.append(new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical));
+ }
+ return headerCell;
+}
+
+QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells() const
+{
+ QList<QAccessibleInterface*> headerCell;
+ if (horizontalHeader()) {
+ // FIXME
+ headerCell.append(new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal));
+ }
+ return headerCell;
+}
+
+QHeaderView *QAccessibleTableCell::horizontalHeader() const
+{
+ QHeaderView *header = 0;
+
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ header = tv->horizontalHeader();
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+
+ return header;
+}
+
+QHeaderView *QAccessibleTableCell::verticalHeader() const
+{
+ QHeaderView *header = 0;
+#ifndef QT_NO_TABLEVIEW
+ if (const QTableView *tv = qobject_cast<const QTableView*>(view))
+ header = tv->verticalHeader();
+#endif
+ return header;
+}
+
+int QAccessibleTableCell::columnIndex() const
+{
+ return m_index.column();
+}
+
+int QAccessibleTableCell::rowIndex() const
+{
+ if (role() == QAccessible::TreeItem) {
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
+ Q_ASSERT(treeView);
+ int row = treeView->d_func()->viewIndex(m_index);
+ return row;
+ }
+ return m_index.row();
+}
+
+bool QAccessibleTableCell::isSelected() const
+{
+ return view->selectionModel()->isSelected(m_index);
+}
+
+QStringList QAccessibleTableCell::actionNames() const
+{
+ QStringList names;
+ names << toggleAction();
+ return names;
+}
+
+void QAccessibleTableCell::doAction(const QString& actionName)
+{
+ if (actionName == toggleAction()) {
+ if (isSelected())
+ unselectCell();
+ else
+ selectCell();
+ }
+}
+
+QStringList QAccessibleTableCell::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+
+void QAccessibleTableCell::selectCell()
+{
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
+ return;
+ Q_ASSERT(table());
+ QAccessibleTableInterface *cellTable = table()->tableInterface();
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable)
+ cellTable->selectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable)
+ cellTable->selectRow(m_index.row());
+ return;
+ }
+
+ if (selectionMode == QAbstractItemView::SingleSelection) {
+ view->clearSelection();
+ }
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Select);
+}
+
+void QAccessibleTableCell::unselectCell()
+{
+
+ QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection))
+ return;
+
+ QAccessibleTableInterface *cellTable = table()->tableInterface();
+
+ switch (view->selectionBehavior()) {
+ case QAbstractItemView::SelectItems:
+ break;
+ case QAbstractItemView::SelectColumns:
+ if (cellTable)
+ cellTable->unselectColumn(m_index.column());
+ return;
+ case QAbstractItemView::SelectRows:
+ if (cellTable)
+ cellTable->unselectRow(m_index.row());
+ return;
+ }
+
+ //If the mode is not MultiSelection or ExtendedSelection and only
+ //one cell is selected it cannot be unselected by the user
+ if ((selectionMode != QAbstractItemView::MultiSelection)
+ && (selectionMode != QAbstractItemView::ExtendedSelection)
+ && (view->selectionModel()->selectedIndexes().count() <= 1))
+ return;
+
+ view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
+}
+
+QAccessibleInterface *QAccessibleTableCell::table() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessible::Role QAccessibleTableCell::role() const
+{
+ return m_role;
+}
+
+QAccessible::State QAccessibleTableCell::state() const
+{
+ QAccessible::State st;
+ QRect globalRect = view->rect();
+ globalRect.translate(view->mapToGlobal(QPoint(0,0)));
+ if (!globalRect.intersects(rect()))
+ st.invisible = true;
+
+ if (view->selectionModel()->isSelected(m_index))
+ st.selected = true;
+ if (view->selectionModel()->currentIndex() == m_index)
+ st.focused = true;
+ if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked)
+ st.checked = true;
+
+ Qt::ItemFlags flags = m_index.flags();
+ if (flags & Qt::ItemIsSelectable) {
+ st.selectable = true;
+ st.focusable = true;
+ if (view->selectionMode() == QAbstractItemView::MultiSelection)
+ st.multiSelectable = true;
+ if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
+ st.extSelectable = true;
+ }
+ if (m_role == QAccessible::TreeItem) {
+ const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
+ if (treeView->model()->hasChildren(m_index))
+ st.expandable = true;
+ if (treeView->isExpanded(m_index))
+ st.expanded = true;
+ }
+ return st;
+}
+
+
+QRect QAccessibleTableCell::rect() const
+{
+ QRect r;
+ r = view->visualRect(m_index);
+
+ if (!r.isNull()) {
+ r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
+ r.translate(view->mapToGlobal(QPoint(0, 0)));
+ }
+ return r;
+}
+
+QString QAccessibleTableCell::text(QAccessible::Text t) const
+{
+ QAbstractItemModel *model = view->model();
+ QString value;
+ switch (t) {
+ case QAccessible::Name:
+ value = model->data(m_index, Qt::AccessibleTextRole).toString();
+ if (value.isEmpty())
+ value = model->data(m_index, Qt::DisplayRole).toString();
+ break;
+ case QAccessible::Description:
+ value = model->data(m_index, Qt::AccessibleDescriptionRole).toString();
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+void QAccessibleTableCell::setText(QAccessible::Text /*t*/, const QString &text)
+{
+ if (!(m_index.flags() & Qt::ItemIsEditable))
+ return;
+ view->model()->setData(m_index, text);
+}
+
+bool QAccessibleTableCell::isValid() const
+{
+ return view && view->model() && m_index.isValid();
+}
+
+QAccessibleInterface *QAccessibleTableCell::parent() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessibleInterface *QAccessibleTableCell::child(int) const
+{
+ return 0;
+}
+
+QAccessibleTableHeaderCell::QAccessibleTableHeaderCell(QAbstractItemView *view_, int index_, Qt::Orientation orientation_)
+ : view(view_), index(index_), orientation(orientation_)
+{
+ Q_ASSERT(index_ >= 0);
+}
+
+QAccessible::Role QAccessibleTableHeaderCell::role() const
+{
+ if (orientation == Qt::Horizontal)
+ return QAccessible::ColumnHeader;
+ return QAccessible::RowHeader;
+}
+
+QAccessible::State QAccessibleTableHeaderCell::state() const
+{
+ QAccessible::State s;
+ if (QHeaderView *h = headerView()) {
+ s.invisible = !h->testAttribute(Qt::WA_WState_Visible);
+ s.disabled = !h->isEnabled();
+ }
+ return s;
+}
+
+QRect QAccessibleTableHeaderCell::rect() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ if (orientation == Qt::Horizontal) {
+ header = tv->horizontalHeader();
+ } else {
+ header = tv->verticalHeader();
+ }
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+ if (!header)
+ return QRect();
+ QPoint zero = header->mapToGlobal(QPoint(0, 0));
+ int sectionSize = header->sectionSize(index);
+ int sectionPos = header->sectionPosition(index);
+ return orientation == Qt::Horizontal
+ ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height())
+ : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize);
+}
+
+QString QAccessibleTableHeaderCell::text(QAccessible::Text t) const
+{
+ QAbstractItemModel *model = view->model();
+ QString value;
+ switch (t) {
+ case QAccessible::Name:
+ value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString();
+ if (value.isEmpty())
+ value = model->headerData(index, orientation, Qt::DisplayRole).toString();
+ break;
+ case QAccessible::Description:
+ value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString();
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+void QAccessibleTableHeaderCell::setText(QAccessible::Text, const QString &)
+{
+ return;
+}
+
+bool QAccessibleTableHeaderCell::isValid() const
+{
+ return view && view->model() && (index >= 0)
+ && ((orientation == Qt::Horizontal) ? (index < view->model()->columnCount()) : (index < view->model()->rowCount()));
+}
+
+QAccessibleInterface *QAccessibleTableHeaderCell::parent() const
+{
+ return QAccessible::queryAccessibleInterface(view);
+}
+
+QAccessibleInterface *QAccessibleTableHeaderCell::child(int) const
+{
+ return 0;
+}
+
+QHeaderView *QAccessibleTableHeaderCell::headerView() const
+{
+ QHeaderView *header = 0;
+ if (false) {
+#ifndef QT_NO_TABLEVIEW
+ } else if (const QTableView *tv = qobject_cast<const QTableView*>(view)) {
+ if (orientation == Qt::Horizontal) {
+ header = tv->horizontalHeader();
+ } else {
+ header = tv->verticalHeader();
+ }
+#endif
+#ifndef QT_NO_TREEVIEW
+ } else if (const QTreeView *tv = qobject_cast<const QTreeView*>(view)) {
+ header = tv->header();
+#endif
+ }
+ return header;
+}
+
+#endif // QT_NO_ITEMVIEWS
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/itemviews.h b/src/widgets/accessible/itemviews.h
new file mode 100644
index 0000000000..45a07c5972
--- /dev/null
+++ b/src/widgets/accessible/itemviews.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACCESSIBLE_ITEMVIEWS_H
+#define ACCESSIBLE_ITEMVIEWS_H
+
+#include "QtCore/qpointer.h"
+#include <QtGui/qaccessible.h>
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtWidgets/qabstractitemview.h>
+#include <QtWidgets/qheaderview.h>
+
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_ITEMVIEWS
+
+class QAccessibleTableCell;
+class QAccessibleTableHeaderCell;
+
+class QAccessibleTable :public QAccessibleTableInterface, public QAccessibleObject
+{
+public:
+ explicit QAccessibleTable(QWidget *w);
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // table interface
+ virtual QAccessibleInterface *cellAt(int row, int column) const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface *caption() const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface *summary() const Q_DECL_OVERRIDE;
+ virtual QString columnDescription(int column) const Q_DECL_OVERRIDE;
+ virtual QString rowDescription(int row) const Q_DECL_OVERRIDE;
+ virtual int columnCount() const Q_DECL_OVERRIDE;
+ virtual int rowCount() const Q_DECL_OVERRIDE;
+
+ // selection
+ virtual int selectedCellCount() const Q_DECL_OVERRIDE;
+ virtual int selectedColumnCount() const Q_DECL_OVERRIDE;
+ virtual int selectedRowCount() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> selectedCells() const Q_DECL_OVERRIDE;
+ virtual QList<int> selectedColumns() const Q_DECL_OVERRIDE;
+ virtual QList<int> selectedRows() const Q_DECL_OVERRIDE;
+ virtual bool isColumnSelected(int column) const Q_DECL_OVERRIDE;
+ virtual bool isRowSelected(int row) const Q_DECL_OVERRIDE;
+ virtual bool selectRow(int row) Q_DECL_OVERRIDE;
+ virtual bool selectColumn(int column) Q_DECL_OVERRIDE;
+ virtual bool unselectRow(int row) Q_DECL_OVERRIDE;
+ virtual bool unselectColumn(int column) Q_DECL_OVERRIDE;
+
+ QAbstractItemView *view() const;
+
+ void modelChange(QAccessibleTableModelChangeEvent *event) Q_DECL_OVERRIDE;
+
+protected:
+ inline QAccessible::Role cellRole() const {
+ switch (m_role) {
+ case QAccessible::List:
+ return QAccessible::ListItem;
+ case QAccessible::Table:
+ return QAccessible::Cell;
+ case QAccessible::Tree:
+ return QAccessible::TreeItem;
+ default:
+ Q_ASSERT(0);
+ }
+ return QAccessible::NoRole;
+ }
+
+ QHeaderView *horizontalHeader() const;
+ QHeaderView *verticalHeader() const;
+
+ // maybe vector
+ typedef QHash<int, QAccessible::Id> ChildCache;
+ mutable ChildCache childToId;
+
+ virtual ~QAccessibleTable();
+
+private:
+ // the child index for a model index
+ inline int logicalIndex(const QModelIndex &index) const;
+ QAccessible::Role m_role;
+};
+
+class QAccessibleTree :public QAccessibleTable
+{
+public:
+ explicit QAccessibleTree(QWidget *w)
+ : QAccessibleTable(w)
+ {}
+
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE;
+
+ int rowCount() const Q_DECL_OVERRIDE;
+
+ // table interface
+ QAccessibleInterface *cellAt(int row, int column) const Q_DECL_OVERRIDE;
+ QString rowDescription(int row) const Q_DECL_OVERRIDE;
+ bool isRowSelected(int row) const Q_DECL_OVERRIDE;
+ bool selectRow(int row) Q_DECL_OVERRIDE;
+
+private:
+ QModelIndex indexFromLogical(int row, int column = 0) const;
+
+ inline int logicalIndex(const QModelIndex &index) const;
+};
+
+class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
+{
+public:
+ QAccessibleTableCell(QAbstractItemView *view, const QModelIndex &m_index, QAccessible::Role role);
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int) const Q_DECL_OVERRIDE;
+
+ // cell interface
+ virtual int columnExtent() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> columnHeaderCells() const Q_DECL_OVERRIDE;
+ virtual int columnIndex() const Q_DECL_OVERRIDE;
+ virtual int rowExtent() const Q_DECL_OVERRIDE;
+ virtual QList<QAccessibleInterface*> rowHeaderCells() const Q_DECL_OVERRIDE;
+ virtual int rowIndex() const Q_DECL_OVERRIDE;
+ virtual bool isSelected() const Q_DECL_OVERRIDE;
+ virtual QAccessibleInterface* table() const Q_DECL_OVERRIDE;
+
+ //action interface
+ virtual QStringList actionNames() const Q_DECL_OVERRIDE;
+ virtual void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ virtual QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+private:
+ QHeaderView *verticalHeader() const;
+ QHeaderView *horizontalHeader() const;
+ QPointer<QAbstractItemView > view;
+ QModelIndex m_index;
+ QAccessible::Role m_role;
+
+ void selectCell();
+ void unselectCell();
+
+friend class QAccessibleTable;
+friend class QAccessibleTree;
+};
+
+
+class QAccessibleTableHeaderCell: public QAccessibleInterface
+{
+public:
+ // For header cells, pass the header view in addition
+ QAccessibleTableHeaderCell(QAbstractItemView *view, int index, Qt::Orientation orientation);
+
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+private:
+ QHeaderView *headerView() const;
+
+ QPointer<QAbstractItemView> view;
+ int index;
+ Qt::Orientation orientation;
+
+friend class QAccessibleTable;
+friend class QAccessibleTree;
+};
+
+// This is the corner button on the top left of a table.
+// It can be used to select all cells or it is not active at all.
+// For now it is ignored.
+class QAccessibleTableCornerButton: public QAccessibleInterface
+{
+public:
+ QAccessibleTableCornerButton(QAbstractItemView *view_)
+ :view(view_)
+ {}
+
+ QObject *object() const Q_DECL_OVERRIDE { return 0; }
+ QAccessible::Role role() const Q_DECL_OVERRIDE { return QAccessible::Pane; }
+ QAccessible::State state() const Q_DECL_OVERRIDE { return QAccessible::State(); }
+ QRect rect() const Q_DECL_OVERRIDE { return QRect(); }
+ bool isValid() const Q_DECL_OVERRIDE { return true; }
+
+ QAccessibleInterface *childAt(int, int) const Q_DECL_OVERRIDE { return 0; }
+ int childCount() const Q_DECL_OVERRIDE { return 0; }
+ int indexOfChild(const QAccessibleInterface *) const Q_DECL_OVERRIDE { return -1; }
+
+ QString text(QAccessible::Text) const Q_DECL_OVERRIDE { return QString(); }
+ void setText(QAccessible::Text, const QString &) Q_DECL_OVERRIDE {}
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE {
+ return QAccessible::queryAccessibleInterface(view);
+ }
+ QAccessibleInterface *child(int) const Q_DECL_OVERRIDE {
+ return 0;
+ }
+
+private:
+ QPointer<QAbstractItemView> view;
+};
+
+
+#endif
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // ACCESSIBLE_ITEMVIEWS_H
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
new file mode 100644
index 0000000000..a6877404eb
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblemenu.h"
+
+#include <qmenu.h>
+#include <qmenubar.h>
+#include <QtWidgets/QAction>
+#include <qstyle.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_MENU
+
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
+
+QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action)
+{
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(action);
+ if (!iface) {
+ iface = new QAccessibleMenuItem(menu, action);
+ QAccessible::registerAccessibleInterface(iface);
+ }
+ return iface;
+}
+
+QAccessibleMenu::QAccessibleMenu(QWidget *w)
+: QAccessibleWidget(w)
+{
+ Q_ASSERT(menu());
+}
+
+QMenu *QAccessibleMenu::menu() const
+{
+ return qobject_cast<QMenu*>(object());
+}
+
+int QAccessibleMenu::childCount() const
+{
+ return menu()->actions().count();
+}
+
+QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const
+{
+ QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y)));
+ if(act && act->isSeparator())
+ act = 0;
+ return act ? getOrCreateMenu(menu(), act) : 0;
+}
+
+QString QAccessibleMenu::text(QAccessible::Text t) const
+{
+ QString tx = QAccessibleWidget::text(t);
+ if (!tx.isEmpty())
+ return tx;
+
+ if (t == QAccessible::Name)
+ return menu()->windowTitle();
+ return tx;
+}
+
+QAccessible::Role QAccessibleMenu::role() const
+{
+ return QAccessible::PopupMenu;
+}
+
+QAccessibleInterface *QAccessibleMenu::child(int index) const
+{
+ if (index < childCount())
+ return getOrCreateMenu(menu(), menu()->actions().at(index));
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleMenu::parent() const
+{
+ if (QAction *menuAction = menu()->menuAction()) {
+ QList<QWidget *> parentCandidates;
+ parentCandidates << menu()->parentWidget();
+ parentCandidates << menuAction->associatedWidgets();
+ foreach (QWidget *w, parentCandidates) {
+ if (qobject_cast<QMenu*>(w) || qobject_cast<QMenuBar*>(w)) {
+ if (w->actions().indexOf(menuAction) != -1)
+ return getOrCreateMenu(w, menuAction);
+ }
+ }
+ }
+ return QAccessibleWidget::parent();
+}
+
+int QAccessibleMenu::indexOfChild( const QAccessibleInterface *child) const
+{
+ QAccessible::Role r = child->role();
+ if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menu()) {
+ return menu()->actions().indexOf(qobject_cast<QAction*>(child->object()));
+ }
+ return -1;
+}
+
+#ifndef QT_NO_MENUBAR
+QAccessibleMenuBar::QAccessibleMenuBar(QWidget *w)
+ : QAccessibleWidget(w, QAccessible::MenuBar)
+{
+ Q_ASSERT(menuBar());
+}
+
+QMenuBar *QAccessibleMenuBar::menuBar() const
+{
+ return qobject_cast<QMenuBar*>(object());
+}
+
+int QAccessibleMenuBar::childCount() const
+{
+ return menuBar()->actions().count();
+}
+
+QAccessibleInterface *QAccessibleMenuBar::child(int index) const
+{
+ if (index < childCount()) {
+ return getOrCreateMenu(menuBar(), menuBar()->actions().at(index));
+ }
+ return 0;
+}
+
+int QAccessibleMenuBar::indexOfChild(const QAccessibleInterface *child) const
+{
+ QAccessible::Role r = child->role();
+ if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menuBar()) {
+ return menuBar()->actions().indexOf(qobject_cast<QAction*>(child->object()));
+ }
+ return -1;
+}
+
+#endif // QT_NO_MENUBAR
+
+QAccessibleMenuItem::QAccessibleMenuItem(QWidget *owner, QAction *action)
+: m_action(action), m_owner(owner)
+{
+}
+
+QAccessibleMenuItem::~QAccessibleMenuItem()
+{}
+
+QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const
+{
+ for (int i = childCount() - 1; i >= 0; --i) {
+ QAccessibleInterface *childInterface = child(i);
+ if (childInterface->rect().contains(x,y)) {
+ return childInterface;
+ }
+ }
+ return 0;
+}
+
+int QAccessibleMenuItem::childCount() const
+{
+ return m_action->menu() ? 1 : 0;
+}
+
+int QAccessibleMenuItem::indexOfChild(const QAccessibleInterface * child) const
+{
+ if (child && child->role() == QAccessible::PopupMenu && child->object() == m_action->menu())
+ return 0;
+ return -1;
+}
+
+bool QAccessibleMenuItem::isValid() const
+{
+ return m_action && m_owner ? true : false;
+}
+
+QAccessibleInterface *QAccessibleMenuItem::parent() const
+{
+ return QAccessible::queryAccessibleInterface(owner());
+}
+
+QAccessibleInterface *QAccessibleMenuItem::child(int index) const
+{
+ if (index == 0 && action()->menu())
+ return QAccessible::queryAccessibleInterface(action()->menu());
+ return 0;
+}
+
+void *QAccessibleMenuItem::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
+ return 0;
+}
+
+QObject *QAccessibleMenuItem::object() const
+{
+ return m_action;
+}
+
+QRect QAccessibleMenuItem::rect() const
+{
+ QRect rect;
+ QWidget *own = owner();
+#ifndef QT_NO_MENUBAR
+ if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) {
+ rect = menuBar->actionGeometry(m_action);
+ QPoint globalPos = menuBar->mapToGlobal(QPoint(0,0));
+ rect = rect.translated(globalPos);
+ } else
+#endif // QT_NO_MENUBAR
+ if (QMenu *menu = qobject_cast<QMenu*>(own)) {
+ rect = menu->actionGeometry(m_action);
+ QPoint globalPos = menu->mapToGlobal(QPoint(0,0));
+ rect = rect.translated(globalPos);
+ }
+ return rect;
+}
+
+QAccessible::Role QAccessibleMenuItem::role() const
+{
+ return m_action->isSeparator() ? QAccessible::Separator : QAccessible::MenuItem;
+}
+
+void QAccessibleMenuItem::setText(QAccessible::Text /*t*/, const QString & /*text */)
+{
+}
+
+QAccessible::State QAccessibleMenuItem::state() const
+{
+ QAccessible::State s;
+ QWidget *own = owner();
+
+ if (own && (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false)) {
+ s.invisible = true;
+ }
+
+ if (QMenu *menu = qobject_cast<QMenu*>(own)) {
+ if (menu->activeAction() == m_action)
+ s.focused = true;
+#ifndef QT_NO_MENUBAR
+ } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) {
+ if (menuBar->activeAction() == m_action)
+ s.focused = true;
+#endif
+ }
+ if (own && own->style()->styleHint(QStyle::SH_Menu_MouseTracking))
+ s.hotTracked = true;
+ if (m_action->isSeparator() || !m_action->isEnabled())
+ s.disabled = true;
+ if (m_action->isChecked())
+ s.checked = true;
+
+ return s;
+}
+
+QString QAccessibleMenuItem::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = m_action->text();
+ str = qt_accStripAmp(str);
+ break;
+ case QAccessible::Accelerator: {
+#ifndef QT_NO_SHORTCUT
+ QKeySequence key = m_action->shortcut();
+ if (!key.isEmpty()) {
+ str = key.toString();
+ } else
+#endif
+ {
+ str = qt_accHotKey(m_action->text());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return str;
+}
+
+QStringList QAccessibleMenuItem::actionNames() const
+{
+ QStringList actions;
+ if (!m_action || m_action->isSeparator())
+ return actions;
+
+ if (m_action->menu()) {
+ actions << showMenuAction();
+ } else {
+ actions << pressAction();
+ }
+ return actions;
+}
+
+void QAccessibleMenuItem::doAction(const QString &actionName)
+{
+ if (!m_action->isEnabled())
+ return;
+
+ if (actionName == pressAction()) {
+ m_action->trigger();
+ } else if (actionName == showMenuAction()) {
+ if (QMenuBar *bar = qobject_cast<QMenuBar*>(owner())) {
+ if (m_action->menu() && m_action->menu()->isVisible()) {
+ m_action->menu()->hide();
+ } else {
+ bar->setActiveAction(m_action);
+ }
+ } else if (QMenu *menu = qobject_cast<QMenu*>(owner())){
+ if (m_action->menu() && m_action->menu()->isVisible()) {
+ m_action->menu()->hide();
+ } else {
+ menu->setActiveAction(m_action);
+ }
+ }
+ }
+}
+
+QStringList QAccessibleMenuItem::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+
+QAction *QAccessibleMenuItem::action() const
+{
+ return m_action;
+}
+
+QWidget *QAccessibleMenuItem::owner() const
+{
+ return m_owner;
+}
+
+#endif // QT_NO_MENU
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
diff --git a/src/widgets/accessible/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu.h
new file mode 100644
index 0000000000..e8c9f8af3a
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblemenu.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEMENU_H
+#define QACCESSIBLEMENU_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifndef QT_NO_MENU
+class QMenu;
+class QMenuBar;
+class QAction;
+
+class QAccessibleMenu : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMenu(QWidget *w);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ int indexOfChild( const QAccessibleInterface *child ) const Q_DECL_OVERRIDE;
+
+protected:
+ QMenu *menu() const;
+};
+
+#ifndef QT_NO_MENUBAR
+class QAccessibleMenuBar : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMenuBar(QWidget *w);
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QMenuBar *menuBar() const;
+};
+#endif // QT_NO_MENUBAR
+
+
+class QAccessibleMenuItem : public QAccessibleInterface, public QAccessibleActionInterface
+{
+public:
+ explicit QAccessibleMenuItem(QWidget *owner, QAction *w);
+
+ ~QAccessibleMenuItem();
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface * child) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *parent() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ QObject * object() const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString & text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+ QWidget *owner() const;
+protected:
+ QAction *action() const;
+private:
+ QAction *m_action;
+ QPointer<QWidget> m_owner; // can hold either QMenu or the QMenuBar that contains the action
+};
+
+#endif // QT_NO_MENU
+
+QT_END_NAMESPACE
+#endif // QT_NO_ACCESSIBILITY
+#endif // QACCESSIBLEMENU_H
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp
index 4e5fade3f4..8a2e38df7e 100644
--- a/src/widgets/accessible/qaccessiblewidget.cpp
+++ b/src/widgets/accessible/qaccessiblewidget.cpp
@@ -134,7 +134,7 @@ static int qt_accAmpIndex(const QString &text)
#endif
}
-QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
+QString qt_accStripAmp(const QString &text)
{
QString newText(text);
int ampIndex = qt_accAmpIndex(newText);
@@ -144,7 +144,7 @@ QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text)
return newText.replace(QLatin1String("&&"), QLatin1String("&"));
}
-QString Q_WIDGETS_EXPORT qt_accHotKey(const QString &text)
+QString qt_accHotKey(const QString &text)
{
int ampIndex = qt_accAmpIndex(text);
if (ampIndex != -1)
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
new file mode 100644
index 0000000000..a925dd2708
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidgets.h"
+#include "qaccessiblemenu.h"
+#include "simplewidgets.h"
+#include "rangecontrols.h"
+#include "complexwidgets.h"
+#include "itemviews.h"
+
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qtreeview.h>
+#include <qvariant.h>
+#include <qaccessible.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object)
+{
+ QAccessibleInterface *iface = 0;
+ if (!object || !object->isWidgetType())
+ return iface;
+ QWidget *widget = static_cast<QWidget*>(object);
+
+ if (false) {
+#ifndef QT_NO_LINEEDIT
+ } else if (classname == QLatin1String("QLineEdit")) {
+ iface = new QAccessibleLineEdit(widget);
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (classname == QLatin1String("QComboBox")) {
+ iface = new QAccessibleComboBox(widget);
+#endif
+#ifndef QT_NO_SPINBOX
+ } else if (classname == QLatin1String("QAbstractSpinBox")) {
+ iface = new QAccessibleAbstractSpinBox(widget);
+ } else if (classname == QLatin1String("QSpinBox")) {
+ iface = new QAccessibleSpinBox(widget);
+ } else if (classname == QLatin1String("QDoubleSpinBox")) {
+ iface = new QAccessibleDoubleSpinBox(widget);
+#endif
+#ifndef QT_NO_SCROLLBAR
+ } else if (classname == QLatin1String("QScrollBar")) {
+ iface = new QAccessibleScrollBar(widget);
+#endif
+ } else if (classname == QLatin1String("QAbstractSlider")) {
+ iface = new QAccessibleAbstractSlider(widget);
+#ifndef QT_NO_SLIDER
+ } else if (classname == QLatin1String("QSlider")) {
+ iface = new QAccessibleSlider(widget);
+#endif
+#ifndef QT_NO_TOOLBUTTON
+ } else if (classname == QLatin1String("QToolButton")) {
+ QAccessible::Role role = QAccessible::NoRole;
+#ifndef QT_NO_MENU
+ QToolButton *tb = qobject_cast<QToolButton*>(widget);
+ if (!tb->menu())
+ role = tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
+ else if (tb->popupMode() == QToolButton::DelayedPopup)
+ role = QAccessible::ButtonDropDown;
+ else
+#endif
+ role = QAccessible::ButtonMenu;
+ iface = new QAccessibleToolButton(widget, role);
+#endif // QT_NO_TOOLBUTTON
+ } else if (classname == QLatin1String("QCheckBox")) {
+ iface = new QAccessibleButton(widget, QAccessible::CheckBox);
+ } else if (classname == QLatin1String("QRadioButton")) {
+ iface = new QAccessibleButton(widget, QAccessible::RadioButton);
+ } else if (classname == QLatin1String("QPushButton")) {
+ QAccessible::Role role = QAccessible::NoRole;
+ QPushButton *pb = qobject_cast<QPushButton*>(widget);
+#ifndef QT_NO_MENU
+ if (pb->menu())
+ role = QAccessible::ButtonMenu;
+ else
+#endif
+ if (pb->isCheckable())
+ role = QAccessible::CheckBox;
+ else
+ role = QAccessible::PushButton;
+ iface = new QAccessibleButton(widget, role);
+ } else if (classname == QLatin1String("QAbstractButton")) {
+ iface = new QAccessibleButton(widget, QAccessible::PushButton);
+ } else if (classname == QLatin1String("QDialog")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Dialog);
+ } else if (classname == QLatin1String("QMessageBox")) {
+ iface = new QAccessibleWidget(widget, QAccessible::AlertMessage);
+#ifndef QT_NO_MAINWINDOW
+ } else if (classname == QLatin1String("QMainWindow")) {
+ iface = new QAccessibleMainWindow(widget);
+#endif
+ } else if (classname == QLatin1String("QLabel") || classname == QLatin1String("QLCDNumber")) {
+ iface = new QAccessibleDisplay(widget);
+#ifndef QT_NO_GROUPBOX
+ } else if (classname == QLatin1String("QGroupBox")) {
+ iface = new QAccessibleGroupBox(widget);
+#endif
+ } else if (classname == QLatin1String("QStatusBar")) {
+ iface = new QAccessibleDisplay(widget);
+#ifndef QT_NO_PROGRESSBAR
+ } else if (classname == QLatin1String("QProgressBar")) {
+ iface = new QAccessibleProgressBar(widget);
+#endif
+ } else if (classname == QLatin1String("QToolBar")) {
+ iface = new QAccessibleWidget(widget, QAccessible::ToolBar, widget->windowTitle());
+#ifndef QT_NO_MENUBAR
+ } else if (classname == QLatin1String("QMenuBar")) {
+ iface = new QAccessibleMenuBar(widget);
+#endif
+#ifndef QT_NO_MENU
+ } else if (classname == QLatin1String("QMenu")) {
+ iface = new QAccessibleMenu(widget);
+#endif
+#ifndef QT_NO_ITEMVIEWS
+ } else if (classname == QLatin1String("QTreeView")) {
+ iface = new QAccessibleTree(widget);
+ } else if (classname == QLatin1String("QTableView") || classname == QLatin1String("QListView")) {
+ iface = new QAccessibleTable(widget);
+ // ### This should be cleaned up. We return the parent for the scrollarea to hide it.
+#endif // QT_NO_ITEMVIEWS
+#ifndef QT_NO_TABBAR
+ } else if (classname == QLatin1String("QTabBar")) {
+ iface = new QAccessibleTabBar(widget);
+#endif
+ } else if (classname == QLatin1String("QSizeGrip")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Grip);
+#ifndef QT_NO_SPLITTER
+ } else if (classname == QLatin1String("QSplitter")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Splitter);
+ } else if (classname == QLatin1String("QSplitterHandle")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Grip);
+#endif
+#if !defined(QT_NO_TEXTEDIT) && !defined(QT_NO_CURSOR)
+ } else if (classname == QLatin1String("QTextEdit")) {
+ iface = new QAccessibleTextEdit(widget);
+ } else if (classname == QLatin1String("QPlainTextEdit")) {
+ iface = new QAccessiblePlainTextEdit(widget);
+#endif
+ } else if (classname == QLatin1String("QTipLabel")) {
+ iface = new QAccessibleDisplay(widget, QAccessible::ToolTip);
+ } else if (classname == QLatin1String("QFrame")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Border);
+#ifndef QT_NO_STACKEDWIDGET
+ } else if (classname == QLatin1String("QStackedWidget")) {
+ iface = new QAccessibleStackedWidget(widget);
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (classname == QLatin1String("QToolBox")) {
+ iface = new QAccessibleToolBox(widget);
+#endif
+#ifndef QT_NO_MDIAREA
+ } else if (classname == QLatin1String("QMdiArea")) {
+ iface = new QAccessibleMdiArea(widget);
+ } else if (classname == QLatin1String("QMdiSubWindow")) {
+ iface = new QAccessibleMdiSubWindow(widget);
+#endif
+ } else if (classname == QLatin1String("QDialogButtonBox")) {
+ iface = new QAccessibleDialogButtonBox(widget);
+#ifndef QT_NO_DIAL
+ } else if (classname == QLatin1String("QDial")) {
+ iface = new QAccessibleDial(widget);
+#endif
+#ifndef QT_NO_RUBBERBAND
+ } else if (classname == QLatin1String("QRubberBand")) {
+ iface = new QAccessibleWidget(widget, QAccessible::Border);
+#endif
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+ } else if (classname == QLatin1String("QTextBrowser")) {
+ iface = new QAccessibleTextBrowser(widget);
+#endif
+#ifndef QT_NO_SCROLLAREA
+ } else if (classname == QLatin1String("QAbstractScrollArea")) {
+ iface = new QAccessibleAbstractScrollArea(widget);
+ } else if (classname == QLatin1String("QScrollArea")) {
+ iface = new QAccessibleScrollArea(widget);
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+ } else if (classname == QLatin1String("QCalendarWidget")) {
+ iface = new QAccessibleCalendarWidget(widget);
+#endif
+#ifndef QT_NO_DOCKWIDGET
+ } else if (classname == QLatin1String("QDockWidget")) {
+ iface = new QAccessibleDockWidget(widget);
+#endif
+
+ } else if (classname == QLatin1String("QDesktopScreenWidget")) {
+ iface = 0;
+ } else if (classname == QLatin1String("QWidget")) {
+ iface = new QAccessibleWidget(widget);
+ } else if (classname == QLatin1String("QWindowContainer")) {
+ iface = new QAccessibleWindowContainer(widget);
+ }
+
+ return iface;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory_p.h b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
new file mode 100644
index 0000000000..70ac462950
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgetfactory_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qaccessible.h>
+
+#ifndef QACCESSIBLEWIDGETFACTORY_H
+#define QACCESSIBLEWIDGETFACTORY_H
+
+QT_BEGIN_NAMESPACE
+
+QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
new file mode 100644
index 0000000000..fa976ea94d
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -0,0 +1,1019 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidgets.h"
+#include "qabstracttextdocumentlayout.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+#include "qtextedit.h"
+#include "private/qtextedit_p.h"
+#include "qtextdocument.h"
+#include "qtextobject.h"
+#include "qplaintextedit.h"
+#include "qtextboundaryfinder.h"
+#include "qscrollbar.h"
+#include "qdebug.h"
+#include <QApplication>
+#include <QStackedWidget>
+#include <QToolBox>
+#include <QMdiArea>
+#include <QMdiSubWindow>
+#include <QDialogButtonBox>
+#include <limits.h>
+#include <QRubberBand>
+#include <QTextBrowser>
+#include <QCalendarWidget>
+#include <QAbstractItemView>
+#include <QDockWidget>
+#include <QMainWindow>
+#include <QAbstractButton>
+#include <private/qdockwidget_p.h>
+#include <QFocusFrame>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+QString qt_accStripAmp(const QString &text);
+
+QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel)
+{
+ if (widget == 0)
+ return QList<QWidget*>();
+ QList<QObject*> list = widget->children();
+ QList<QWidget*> widgets;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(list.at(i));
+ if (!w)
+ continue;
+ QString objectName = w->objectName();
+ if ((includeTopLevel || !w->isWindow())
+ && !qobject_cast<QFocusFrame*>(w)
+ && !qobject_cast<QMenu*>(w)
+ && objectName != QLatin1String("qt_rubberband")
+ && objectName != QLatin1String("qt_qmainwindow_extended_splitter")) {
+ widgets.append(w);
+ }
+ }
+ return widgets;
+}
+
+#if !defined(QT_NO_TEXTEDIT) && !defined(QT_NO_CURSOR)
+
+QAccessiblePlainTextEdit::QAccessiblePlainTextEdit(QWidget* o)
+ :QAccessibleTextWidget(o)
+{
+ Q_ASSERT(widget()->inherits("QPlainTextEdit"));
+}
+
+QPlainTextEdit* QAccessiblePlainTextEdit::plainTextEdit() const
+{
+ return static_cast<QPlainTextEdit *>(widget());
+}
+
+QString QAccessiblePlainTextEdit::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return plainTextEdit()->toPlainText();
+
+ return QAccessibleWidget::text(t);
+}
+
+void QAccessiblePlainTextEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+ if (plainTextEdit()->isReadOnly())
+ return;
+
+ plainTextEdit()->setPlainText(text);
+}
+
+QAccessible::State QAccessiblePlainTextEdit::state() const
+{
+ QAccessible::State st = QAccessibleTextWidget::state();
+ if (plainTextEdit()->isReadOnly())
+ st.readOnly = true;
+ else
+ st.editable = true;
+ return st;
+}
+
+void *QAccessiblePlainTextEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QPoint QAccessiblePlainTextEdit::scrollBarPosition() const
+{
+ QPoint result;
+ result.setX(plainTextEdit()->horizontalScrollBar() ? plainTextEdit()->horizontalScrollBar()->sliderPosition() : 0);
+ result.setY(plainTextEdit()->verticalScrollBar() ? plainTextEdit()->verticalScrollBar()->sliderPosition() : 0);
+ return result;
+}
+
+QTextCursor QAccessiblePlainTextEdit::textCursor() const
+{
+ return plainTextEdit()->textCursor();
+}
+
+void QAccessiblePlainTextEdit::setTextCursor(const QTextCursor &textCursor)
+{
+ plainTextEdit()->setTextCursor(textCursor);
+}
+
+QTextDocument* QAccessiblePlainTextEdit::textDocument() const
+{
+ return plainTextEdit()->document();
+}
+
+QWidget* QAccessiblePlainTextEdit::viewport() const
+{
+ return plainTextEdit()->viewport();
+}
+
+void QAccessiblePlainTextEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ //TODO: Not implemented
+ Q_UNUSED(startIndex);
+ Q_UNUSED(endIndex);
+}
+
+
+/*!
+ \class QAccessibleTextEdit
+ \brief The QAccessibleTextEdit class implements the QAccessibleInterface for richtext editors.
+ \internal
+*/
+
+/*!
+ \fn QAccessibleTextEdit::QAccessibleTextEdit(QWidget *widget)
+
+ Constructs a QAccessibleTextEdit object for a \a widget.
+*/
+QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
+: QAccessibleTextWidget(o, QAccessible::EditableText)
+{
+ Q_ASSERT(widget()->inherits("QTextEdit"));
+}
+
+/*! Returns the text edit. */
+QTextEdit *QAccessibleTextEdit::textEdit() const
+{
+ return static_cast<QTextEdit *>(widget());
+}
+
+QTextCursor QAccessibleTextEdit::textCursor() const
+{
+ return textEdit()->textCursor();
+}
+
+QTextDocument *QAccessibleTextEdit::textDocument() const
+{
+ return textEdit()->document();
+}
+
+void QAccessibleTextEdit::setTextCursor(const QTextCursor &textCursor)
+{
+ textEdit()->setTextCursor(textCursor);
+}
+
+QWidget *QAccessibleTextEdit::viewport() const
+{
+ return textEdit()->viewport();
+}
+
+QPoint QAccessibleTextEdit::scrollBarPosition() const
+{
+ QPoint result;
+ result.setX(textEdit()->horizontalScrollBar() ? textEdit()->horizontalScrollBar()->sliderPosition() : 0);
+ result.setY(textEdit()->verticalScrollBar() ? textEdit()->verticalScrollBar()->sliderPosition() : 0);
+ return result;
+}
+
+QString QAccessibleTextEdit::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return textEdit()->toPlainText();
+
+ return QAccessibleWidget::text(t);
+}
+
+void QAccessibleTextEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+ if (textEdit()->isReadOnly())
+ return;
+
+ textEdit()->setText(text);
+}
+
+QAccessible::State QAccessibleTextEdit::state() const
+{
+ QAccessible::State st = QAccessibleTextWidget::state();
+ if (textEdit()->isReadOnly())
+ st.readOnly = true;
+ else
+ st.editable = true;
+ return st;
+}
+
+void *QAccessibleTextEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ QTextEdit *edit = textEdit();
+
+ QTextCursor cursor = textCursor();
+ 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!");
+}
+
+#endif // QT_NO_TEXTEDIT && QT_NO_CURSOR
+
+#ifndef QT_NO_STACKEDWIDGET
+// ======================= QAccessibleStackedWidget ======================
+QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
+}
+
+QAccessibleInterface *QAccessibleStackedWidget::childAt(int x, int y) const
+{
+ if (!stackedWidget()->isVisible())
+ return 0;
+ QWidget *currentWidget = stackedWidget()->currentWidget();
+ if (!currentWidget)
+ return 0;
+ QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
+ if (currentWidget->rect().contains(position))
+ return child(stackedWidget()->currentIndex());
+ return 0;
+}
+
+int QAccessibleStackedWidget::childCount() const
+{
+ return stackedWidget()->count();
+}
+
+int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child)
+ return -1;
+
+ QWidget *widget = qobject_cast<QWidget*>(child->object());
+ return stackedWidget()->indexOf(widget);
+}
+
+QAccessibleInterface *QAccessibleStackedWidget::child(int index) const
+{
+ if (index < 0 || index >= stackedWidget()->count())
+ return 0;
+ return QAccessible::queryAccessibleInterface(stackedWidget()->widget(index));
+}
+
+QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
+{
+ return static_cast<QStackedWidget *>(object());
+}
+#endif // QT_NO_STACKEDWIDGET
+
+#ifndef QT_NO_TOOLBOX
+// ======================= QAccessibleToolBox ======================
+QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QToolBox *>(widget));
+}
+
+QToolBox * QAccessibleToolBox::toolBox() const
+{
+ return static_cast<QToolBox *>(object());
+}
+#endif // QT_NO_TOOLBOX
+
+// ======================= QAccessibleMdiArea ======================
+#ifndef QT_NO_MDIAREA
+QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::LayeredPane)
+{
+ Q_ASSERT(qobject_cast<QMdiArea *>(widget));
+}
+
+int QAccessibleMdiArea::childCount() const
+{
+ return mdiArea()->subWindowList().count();
+}
+
+QAccessibleInterface *QAccessibleMdiArea::child(int index) const
+{
+ QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
+ QWidget *targetObject = subWindows.value(index);
+ if (!targetObject)
+ return 0;
+ return QAccessible::queryAccessibleInterface(targetObject);
+}
+
+
+int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
+ return -1;
+ if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
+ return mdiArea()->subWindowList().indexOf(window);
+ }
+ return -1;
+}
+
+QMdiArea *QAccessibleMdiArea::mdiArea() const
+{
+ return static_cast<QMdiArea *>(object());
+}
+
+// ======================= QAccessibleMdiSubWindow ======================
+QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window)
+{
+ Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
+}
+
+QString QAccessibleMdiSubWindow::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Name) {
+ QString title = mdiSubWindow()->windowTitle();
+ title.replace(QLatin1String("[*]"), QLatin1String(""));
+ return title;
+ }
+ return QAccessibleWidget::text(textType);
+}
+
+void QAccessibleMdiSubWindow::setText(QAccessible::Text textType, const QString &text)
+{
+ if (textType == QAccessible::Name)
+ mdiSubWindow()->setWindowTitle(text);
+ else
+ QAccessibleWidget::setText(textType, text);
+}
+
+QAccessible::State QAccessibleMdiSubWindow::state() const
+{
+ QAccessible::State state;
+ state.focusable = true;
+ if (!mdiSubWindow()->isMaximized()) {
+ state.movable = true;
+ state.sizeable = true;
+ }
+ if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
+ || QApplication::focusWidget() == mdiSubWindow())
+ state.focused = true;
+ if (!mdiSubWindow()->isVisible())
+ state.invisible = true;
+ if (const QWidget *parent = mdiSubWindow()->parentWidget())
+ if (!parent->contentsRect().contains(mdiSubWindow()->geometry()))
+ state.offscreen = true;
+ if (!mdiSubWindow()->isEnabled())
+ state.disabled = true;
+ return state;
+}
+
+int QAccessibleMdiSubWindow::childCount() const
+{
+ if (mdiSubWindow()->widget())
+ return 1;
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleMdiSubWindow::child(int index) const
+{
+ QMdiSubWindow *source = mdiSubWindow();
+ if (index != 0 || !source->widget())
+ return 0;
+
+ return QAccessible::queryAccessibleInterface(source->widget());
+}
+
+int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child && child->object() && child->object() == mdiSubWindow()->widget())
+ return 0;
+ return -1;
+}
+
+QRect QAccessibleMdiSubWindow::rect() const
+{
+ if (mdiSubWindow()->isHidden())
+ return QRect();
+ if (!mdiSubWindow()->parent())
+ return QAccessibleWidget::rect();
+ const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
+ return QRect(pos, mdiSubWindow()->size());
+}
+
+QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
+{
+ return static_cast<QMdiSubWindow *>(object());
+}
+#endif // QT_NO_MDIAREA
+
+#ifndef QT_NO_DIALOGBUTTONBOX
+// ======================= QAccessibleDialogButtonBox ======================
+QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Grouping)
+{
+ Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
+}
+
+#endif // QT_NO_DIALOGBUTTONBOX
+
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
+ : QAccessibleTextEdit(widget)
+{
+ Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
+}
+
+QAccessible::Role QAccessibleTextBrowser::role() const
+{
+ return QAccessible::StaticText;
+}
+#endif // QT_NO_TEXTBROWSER && QT_NO_CURSOR
+
+#ifndef QT_NO_CALENDARWIDGET
+// ===================== QAccessibleCalendarWidget ========================
+QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Table)
+{
+ Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
+}
+
+int QAccessibleCalendarWidget::childCount() const
+{
+ return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
+}
+
+int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || childCount() <= 0)
+ return -1;
+ if (qobject_cast<QAbstractItemView *>(child->object()))
+ return childCount() - 1; // FIXME
+ return 0;
+}
+
+QAccessibleInterface *QAccessibleCalendarWidget::child(int index) const
+{
+ if (index < 0 || index >= childCount())
+ return 0;
+
+ if (childCount() > 1 && index == 0)
+ return QAccessible::queryAccessibleInterface(navigationBar());
+
+ return QAccessible::queryAccessibleInterface(calendarView());
+}
+
+QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
+{
+ return static_cast<QCalendarWidget *>(object());
+}
+
+QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
+{
+ foreach (QObject *child, calendarWidget()->children()) {
+ if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
+ return static_cast<QAbstractItemView *>(child);
+ }
+ return 0;
+}
+
+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
+
+#ifndef QT_NO_DOCKWIDGET
+
+// Dock Widget - order of children:
+// - Content widget
+// - Float button
+// - Close button
+// If there is a custom title bar widget, that one becomes child 1, after the content 0
+// (in that case the buttons are ignored)
+QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window)
+{
+}
+
+QDockWidgetLayout *QAccessibleDockWidget::dockWidgetLayout() const
+{
+ return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
+}
+
+int QAccessibleDockWidget::childCount() const
+{
+ if (dockWidget()->titleBarWidget()) {
+ return dockWidget()->widget() ? 2 : 1;
+ }
+ return dockWidgetLayout()->count();
+}
+
+QAccessibleInterface *QAccessibleDockWidget::child(int index) const
+{
+ if (dockWidget()->titleBarWidget()) {
+ if ((!dockWidget()->widget() && index == 0) || (index == 1))
+ return QAccessible::queryAccessibleInterface(dockWidget()->titleBarWidget());
+ if (index == 0)
+ return QAccessible::queryAccessibleInterface(dockWidget()->widget());
+ } else {
+ QLayoutItem *item = dockWidgetLayout()->itemAt(index);
+ if (item)
+ return QAccessible::queryAccessibleInterface(item->widget());
+ }
+ return 0;
+}
+
+int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child || !child->object() || child->object()->parent() != object())
+ return -1;
+
+ if (dockWidget()->titleBarWidget() == child->object()) {
+ return dockWidget()->widget() ? 1 : 0;
+ }
+
+ return dockWidgetLayout()->indexOf(qobject_cast<QWidget*>(child->object()));
+}
+
+QRect QAccessibleDockWidget::rect() const
+{
+ QRect rect;
+
+ if (dockWidget()->isFloating()) {
+ rect = dockWidget()->frameGeometry();
+ } else {
+ rect = dockWidget()->rect();
+ rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
+ }
+
+ return rect;
+}
+
+QDockWidget *QAccessibleDockWidget::dockWidget() const
+{
+ return static_cast<QDockWidget *>(object());
+}
+
+QString QAccessibleDockWidget::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Name) {
+ return qt_accStripAmp(dockWidget()->windowTitle());
+ }
+ return QString();
+}
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_CURSOR
+
+QAccessibleTextWidget::QAccessibleTextWidget(QWidget *o, QAccessible::Role r, const QString &name):
+ QAccessibleWidget(o, r, name)
+{
+
+}
+
+QAccessible::State QAccessibleTextWidget::state() const
+{
+ QAccessible::State s = QAccessibleWidget::state();
+ s.multiLine = true;
+ return s;
+}
+
+QRect QAccessibleTextWidget::characterRect(int offset) const
+{
+ QTextBlock block = textDocument()->findBlock(offset);
+ if (!block.isValid())
+ return QRect();
+
+ QTextLayout *layout = block.layout();
+ QPointF layoutPosition = layout->position();
+ int relativeOffset = offset - block.position();
+ QTextLine line = layout->lineForTextPosition(relativeOffset);
+
+ QRect r;
+
+ if (line.isValid()) {
+ qreal x = line.cursorToX(relativeOffset);
+ QFontMetrics fm(textCursor().charFormat().font());
+ const QString ch = text(offset, offset + 1);
+ if (!ch.isEmpty()) {
+ int w = fm.width(ch);
+ int h = fm.height();
+ r = QRect(layoutPosition.x() + x, layoutPosition.y() + line.y(),
+ w, h);
+ r.moveTo(viewport()->mapToGlobal(r.topLeft()));
+ }
+ r.translate(-scrollBarPosition());
+ }
+
+ return r;
+}
+
+int QAccessibleTextWidget::offsetAtPoint(const QPoint &point) const
+{
+ QPoint p = viewport()->mapFromGlobal(point);
+ // convert to document coordinates
+ p += scrollBarPosition();
+ return textDocument()->documentLayout()->hitTest(p, Qt::ExactHit);
+}
+
+int QAccessibleTextWidget::selectionCount() const
+{
+ return textCursor().hasSelection() ? 1 : 0;
+}
+
+QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *endOffset) 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();
+ }
+
+ QMap<QString, QString> attrs;
+
+ QTextCursor cursor = 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();
+
+ QTextCharFormat charFormatComp;
+ QTextBlockFormat blockFormatComp;
+
+ *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 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;
+ }
+
+ 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+'"';
+ }
+
+ 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;
+}
+
+int QAccessibleTextWidget::cursorPosition() const
+{
+ return textCursor().position();
+}
+
+void QAccessibleTextWidget::selection(int selectionIndex, int *startOffset, int *endOffset) const
+{
+ *startOffset = *endOffset = 0;
+ QTextCursor cursor = textCursor();
+
+ if (selectionIndex != 0 || !cursor.hasSelection())
+ return;
+
+ *startOffset = cursor.selectionStart();
+ *endOffset = cursor.selectionEnd();
+}
+
+QString QAccessibleTextWidget::text(int startOffset, int endOffset) const
+{
+ QTextCursor cursor(textCursor());
+
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+
+ return cursor.selectedText();
+}
+
+QPoint QAccessibleTextWidget::scrollBarPosition() const
+{
+ return QPoint(0, 0);
+}
+
+
+QString QAccessibleTextWidget::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ cursor.setPosition(boundaries.first - 1);
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+ }
+
+
+QString QAccessibleTextWidget::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ cursor.setPosition(boundaries.second);
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+}
+
+QString QAccessibleTextWidget::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return text(boundaries.first, boundaries.second);
+}
+
+void QAccessibleTextWidget::setCursorPosition(int position)
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(position);
+ setTextCursor(cursor);
+}
+
+void QAccessibleTextWidget::addSelection(int startOffset, int endOffset)
+{
+ setSelection(0, startOffset, endOffset);
+}
+
+void QAccessibleTextWidget::removeSelection(int selectionIndex)
+{
+ if (selectionIndex != 0)
+ return;
+
+ QTextCursor cursor = textCursor();
+ cursor.clearSelection();
+ setTextCursor(cursor);
+}
+
+void QAccessibleTextWidget::setSelection(int selectionIndex, int startOffset, int endOffset)
+{
+ if (selectionIndex != 0)
+ return;
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+ setTextCursor(cursor);
+}
+
+int QAccessibleTextWidget::characterCount() const
+{
+ QTextCursor cursor = textCursor();
+ cursor.movePosition(QTextCursor::End);
+ return cursor.position();
+}
+
+QTextCursor QAccessibleTextWidget::textCursorForRange(int startOffset, int endOffset) const
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
+ cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
+
+ return cursor;
+}
+
+void QAccessibleTextWidget::deleteText(int startOffset, int endOffset)
+{
+ QTextCursor cursor = textCursorForRange(startOffset, endOffset);
+ cursor.removeSelectedText();
+}
+
+void QAccessibleTextWidget::insertText(int offset, const QString &text)
+{
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(offset);
+ cursor.insertText(text);
+}
+
+void QAccessibleTextWidget::replaceText(int startOffset, int endOffset, const QString &text)
+{
+ QTextCursor cursor = textCursorForRange(startOffset, endOffset);
+ cursor.removeSelectedText();
+ cursor.insertText(text);
+}
+#endif // QT_NO_CURSOR
+
+
+#ifndef QT_NO_MAINWINDOW
+QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
+ : QAccessibleWidget(widget, QAccessible::Window) { }
+
+QAccessibleInterface *QAccessibleMainWindow::child(int index) const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow(), true);
+ if (index >= 0 && index < kids.count()) {
+ return QAccessible::queryAccessibleInterface(kids.at(index));
+ }
+ return 0;
+}
+
+int QAccessibleMainWindow::childCount() const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow(), true);
+ return kids.count();
+}
+
+int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const
+{
+ QList<QWidget*> kids = childWidgets(mainWindow(), true);
+ return kids.indexOf(static_cast<QWidget*>(iface->object()));
+}
+
+QAccessibleInterface *QAccessibleMainWindow::childAt(int x, int y) const
+{
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return 0;
+ QPoint gp = w->mapToGlobal(QPoint(0, 0));
+ if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
+ return 0;
+
+ QWidgetList kids = childWidgets(mainWindow(), true);
+ QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y));
+ for (int i = 0; i < kids.size(); ++i) {
+ QWidget *child = kids.at(i);
+ if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
+ return QAccessible::queryAccessibleInterface(child);
+ }
+ }
+ return 0;
+}
+
+QMainWindow *QAccessibleMainWindow::mainWindow() const
+{
+ return qobject_cast<QMainWindow *>(object());
+}
+
+#endif //QT_NO_MAINWINDOW
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets.h
new file mode 100644
index 0000000000..3f50010685
--- /dev/null
+++ b/src/widgets/accessible/qaccessiblewidgets.h
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEWIDGETS_H
+#define QACCESSIBLEWIDGETS_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include <QtCore/QPointer>
+#include <QtCore/QPair>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+class QStackedWidget;
+class QToolBox;
+class QMdiArea;
+class QMdiSubWindow;
+class QRubberBand;
+class QTextBrowser;
+class QCalendarWidget;
+class QAbstractItemView;
+class QDockWidget;
+class QDockWidgetLayout;
+class QMainWindow;
+class QPlainTextEdit;
+class QTextCursor;
+class QTextDocument;
+
+#ifndef QT_NO_CURSOR
+class QAccessibleTextWidget : public QAccessibleWidget,
+ public QAccessibleTextInterface,
+ public QAccessibleEditableTextInterface
+{
+public:
+ QAccessibleTextWidget(QWidget *o, QAccessible::Role r = QAccessible::EditableText, const QString &name = QString());
+
+ QAccessible::State state() const;
+
+ // QAccessibleTextInterface
+ // selection
+ void selection(int selectionIndex, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int selectionCount() const Q_DECL_OVERRIDE;
+ void addSelection(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void removeSelection(int selectionIndex) Q_DECL_OVERRIDE;
+ void setSelection(int selectionIndex, int startOffset, int endOffset) Q_DECL_OVERRIDE;
+
+ // cursor
+ int cursorPosition() const Q_DECL_OVERRIDE;
+ void setCursorPosition(int position) Q_DECL_OVERRIDE;
+
+ // text
+ QString text(int startOffset, int endOffset) const Q_DECL_OVERRIDE;
+ QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int characterCount() const;
+
+ // character <-> geometry
+ QRect characterRect(int offset) const Q_DECL_OVERRIDE;
+ int offsetAtPoint(const QPoint &point) const Q_DECL_OVERRIDE;
+
+ QString attributes(int offset, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+
+ // QAccessibleEditableTextInterface
+ void deleteText(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void insertText(int offset, const QString &text) Q_DECL_OVERRIDE;
+ void replaceText(int startOffset, int endOffset, const QString &text) Q_DECL_OVERRIDE;
+
+ using QAccessibleWidget::text;
+
+protected:
+ QTextCursor textCursorForRange(int startOffset, int endOffset) const;
+ virtual QPoint scrollBarPosition() const;
+ // return the current text cursor at the caret position including a potential selection
+ virtual QTextCursor textCursor() const = 0;
+ virtual void setTextCursor(const QTextCursor &) = 0;
+ virtual QTextDocument *textDocument() const = 0;
+ virtual QWidget *viewport() const = 0;
+};
+
+#ifndef QT_NO_TEXTEDIT
+class QAccessiblePlainTextEdit : public QAccessibleTextWidget
+{
+public:
+ explicit QAccessiblePlainTextEdit(QWidget *o);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ using QAccessibleTextWidget::text;
+
+protected:
+ QPlainTextEdit *plainTextEdit() const;
+
+ QPoint scrollBarPosition() const Q_DECL_OVERRIDE;
+ QTextCursor textCursor() const Q_DECL_OVERRIDE;
+ void setTextCursor(const QTextCursor &textCursor) Q_DECL_OVERRIDE;
+ QTextDocument *textDocument() const Q_DECL_OVERRIDE;
+ QWidget *viewport() const Q_DECL_OVERRIDE;
+};
+
+class QAccessibleTextEdit : public QAccessibleTextWidget
+{
+public:
+ explicit QAccessibleTextEdit(QWidget *o);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ using QAccessibleTextWidget::text;
+
+protected:
+ QTextEdit *textEdit() const;
+
+ QPoint scrollBarPosition() const Q_DECL_OVERRIDE;
+ QTextCursor textCursor() const Q_DECL_OVERRIDE;
+ void setTextCursor(const QTextCursor &textCursor) Q_DECL_OVERRIDE;
+ QTextDocument *textDocument() const Q_DECL_OVERRIDE;
+ QWidget *viewport() const Q_DECL_OVERRIDE;
+};
+#endif // QT_NO_TEXTEDIT
+#endif //QT_NO_CURSOR
+
+class QAccessibleStackedWidget : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleStackedWidget(QWidget *widget);
+
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+protected:
+ QStackedWidget *stackedWidget() const;
+};
+
+class QAccessibleToolBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleToolBox(QWidget *widget);
+
+// FIXME we currently expose the toolbox but it is not keyboard navigatable
+// and the accessible hierarchy is not exactly beautiful.
+// int childCount() const;
+// QAccessibleInterface *child(int index) const;
+// int indexOfChild(const QAccessibleInterface *child) const;
+
+protected:
+ QToolBox *toolBox() const;
+};
+
+#ifndef QT_NO_MDIAREA
+class QAccessibleMdiArea : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMdiArea(QWidget *widget);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+protected:
+ QMdiArea *mdiArea() const;
+};
+
+class QAccessibleMdiSubWindow : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMdiSubWindow(QWidget *widget);
+
+ QString text(QAccessible::Text textType) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text textType, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QRect rect() const Q_DECL_OVERRIDE;
+
+protected:
+ QMdiSubWindow *mdiSubWindow() const;
+};
+#endif // QT_NO_MDIAREA
+
+class QAccessibleDialogButtonBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleDialogButtonBox(QWidget *widget);
+};
+
+#if !defined(QT_NO_TEXTBROWSER) && !defined(QT_NO_CURSOR)
+class QAccessibleTextBrowser : public QAccessibleTextEdit
+{
+public:
+ explicit QAccessibleTextBrowser(QWidget *widget);
+
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+};
+#endif // QT_NO_TEXTBROWSER && QT_NO_CURSOR
+
+#ifndef QT_NO_CALENDARWIDGET
+class QAccessibleCalendarWidget : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleCalendarWidget(QWidget *widget);
+
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+protected:
+ QCalendarWidget *calendarWidget() const;
+
+private:
+ QAbstractItemView *calendarView() const;
+ QWidget *navigationBar() const;
+};
+#endif // QT_NO_CALENDARWIDGET
+
+#ifndef QT_NO_DOCKWIDGET
+class QAccessibleDockWidget: public QAccessibleWidget
+{
+public:
+ explicit QAccessibleDockWidget(QWidget *widget);
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ QRect rect () const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QDockWidget *dockWidget() const;
+protected:
+ QDockWidgetLayout *dockWidgetLayout() const;
+};
+
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_MAINWINDOW
+class QAccessibleMainWindow : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleMainWindow(QWidget *widget);
+
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *iface) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE;
+ QMainWindow *mainWindow() const;
+
+};
+#endif //QT_NO_MAINWINDOW
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // QACESSIBLEWIDGETS_H
diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
new file mode 100644
index 0000000000..d2917e535c
--- /dev/null
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rangecontrols.h"
+
+#include <qslider.h>
+#include <qdial.h>
+#include <qspinbox.h>
+#include <qscrollbar.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qdebug.h>
+#include <qglobal.h>
+#include <QDoubleSpinBox>
+#include <QDial>
+#include <qmath.h>
+#include <private/qmath_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+QString qt_accStripAmp(const QString &text);
+#ifndef QT_NO_SCROLLBAR
+extern QStyleOptionSlider Q_GUI_EXPORT qt_qscrollbarStyleOption(QScrollBar *scrollBar);
+#endif
+#ifndef QT_NO_SLIDER
+extern QStyleOptionSlider Q_GUI_EXPORT qt_qsliderStyleOption(QSlider *slider);
+#endif
+
+#ifndef QT_NO_SPINBOX
+QAccessibleAbstractSpinBox::QAccessibleAbstractSpinBox(QWidget *w)
+: QAccessibleWidget(w, QAccessible::SpinBox)
+{
+ Q_ASSERT(abstractSpinBox());
+}
+
+/*!
+ Returns the underlying QAbstractSpinBox.
+*/
+QAbstractSpinBox *QAccessibleAbstractSpinBox::abstractSpinBox() const
+{
+ return qobject_cast<QAbstractSpinBox*>(object());
+}
+
+QString QAccessibleAbstractSpinBox::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return abstractSpinBox()->text();
+ return QAccessibleWidget::text(t);
+}
+
+void *QAccessibleAbstractSpinBox::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QVariant QAccessibleAbstractSpinBox::currentValue() const
+{
+ QVariant result = abstractSpinBox()->property("value");
+ QVariant::Type type = result.type();
+
+ // IA2 only allows numeric types
+ if (type == QVariant::Int || type == QVariant::UInt || type == QVariant::LongLong
+ || type == QVariant::ULongLong || type == QVariant::Double)
+ return result;
+
+ return QVariant();
+}
+
+void QAccessibleAbstractSpinBox::setCurrentValue(const QVariant &value)
+{
+ abstractSpinBox()->setProperty("value", value);
+}
+
+QVariant QAccessibleAbstractSpinBox::maximumValue() const
+{
+ return abstractSpinBox()->property("maximum");
+}
+
+QVariant QAccessibleAbstractSpinBox::minimumValue() const
+{
+ return abstractSpinBox()->property("minimum");
+}
+
+QVariant QAccessibleAbstractSpinBox::minimumStepSize() const
+{
+ return abstractSpinBox()->property("stepSize");
+}
+
+/*!
+ \class QAccessibleSpinBox
+ \brief The QAccessibleSpinBox class implements the QAccessibleInterface for spinbox widgets.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleSpinWidget object for \a w.
+*/
+QAccessibleSpinBox::QAccessibleSpinBox(QWidget *w)
+: QAccessibleAbstractSpinBox(w)
+{
+ Q_ASSERT(spinBox());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+ addControllingSignal(QLatin1String("valueChanged(QString)"));
+}
+
+/*!
+ Returns the underlying QSpinBox.
+*/
+QSpinBox *QAccessibleSpinBox::spinBox() const
+{
+ return qobject_cast<QSpinBox*>(object());
+}
+
+
+// ================================== QAccessibleDoubleSpinBox ==================================
+QAccessibleDoubleSpinBox::QAccessibleDoubleSpinBox(QWidget *widget)
+ : QAccessibleAbstractSpinBox(widget)
+{
+ Q_ASSERT(qobject_cast<QDoubleSpinBox *>(widget));
+ addControllingSignal(QLatin1String("valueChanged(double)"));
+ addControllingSignal(QLatin1String("valueChanged(QString)"));
+}
+
+/*!
+ Returns the underlying QDoubleSpinBox.
+*/
+QDoubleSpinBox *QAccessibleDoubleSpinBox::doubleSpinBox() const
+{
+ return static_cast<QDoubleSpinBox*>(object());
+}
+
+QString QAccessibleDoubleSpinBox::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Value)
+ return doubleSpinBox()->textFromValue(doubleSpinBox()->value());
+ return QAccessibleWidget::text(textType);
+}
+
+#endif // QT_NO_SPINBOX
+
+#ifndef QT_NO_SCROLLBAR
+/*!
+ \class QAccessibleScrollBar
+ \brief The QAccessibleScrollBar class implements the QAccessibleInterface for scroll bars.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleScrollBar object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleScrollBar::QAccessibleScrollBar(QWidget *w)
+: QAccessibleAbstractSlider(w, QAccessible::ScrollBar)
+{
+ Q_ASSERT(scrollBar());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+/*! Returns the scroll bar. */
+QScrollBar *QAccessibleScrollBar::scrollBar() const
+{
+ return qobject_cast<QScrollBar*>(object());
+}
+
+QString QAccessibleScrollBar::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return QString::number(scrollBar()->value());
+ return QAccessibleAbstractSlider::text(t);
+}
+
+#endif // QT_NO_SCROLLBAR
+
+#ifndef QT_NO_SLIDER
+/*!
+ \class QAccessibleSlider
+ \brief The QAccessibleSlider class implements the QAccessibleInterface for sliders.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleScrollBar object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleSlider::QAccessibleSlider(QWidget *w)
+: QAccessibleAbstractSlider(w)
+{
+ Q_ASSERT(slider());
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+/*! Returns the slider. */
+QSlider *QAccessibleSlider::slider() const
+{
+ return qobject_cast<QSlider*>(object());
+}
+
+QString QAccessibleSlider::text(QAccessible::Text t) const
+{
+ if (t == QAccessible::Value)
+ return QString::number(slider()->value());
+
+ return QAccessibleAbstractSlider::text(t);
+}
+
+QAccessibleAbstractSlider::QAccessibleAbstractSlider(QWidget *w, QAccessible::Role r)
+ : QAccessibleWidget(w, r)
+{
+ Q_ASSERT(qobject_cast<QAbstractSlider *>(w));
+}
+
+void *QAccessibleAbstractSlider::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+QVariant QAccessibleAbstractSlider::currentValue() const
+{
+ return abstractSlider()->value();
+}
+
+void QAccessibleAbstractSlider::setCurrentValue(const QVariant &value)
+{
+ abstractSlider()->setValue(value.toInt());
+}
+
+QVariant QAccessibleAbstractSlider::maximumValue() const
+{
+ return abstractSlider()->maximum();
+}
+
+QVariant QAccessibleAbstractSlider::minimumValue() const
+{
+ return abstractSlider()->minimum();
+}
+
+QVariant QAccessibleAbstractSlider::minimumStepSize() const
+{
+ return abstractSlider()->singleStep();
+}
+
+QAbstractSlider *QAccessibleAbstractSlider::abstractSlider() const
+{
+ return static_cast<QAbstractSlider *>(object());
+}
+
+#endif // QT_NO_SLIDER
+
+#ifndef QT_NO_DIAL
+// ======================================= QAccessibleDial ======================================
+QAccessibleDial::QAccessibleDial(QWidget *widget)
+ : QAccessibleAbstractSlider(widget, QAccessible::Dial)
+{
+ Q_ASSERT(qobject_cast<QDial *>(widget));
+ addControllingSignal(QLatin1String("valueChanged(int)"));
+}
+
+QString QAccessibleDial::text(QAccessible::Text textType) const
+{
+ if (textType == QAccessible::Value)
+ return QString::number(dial()->value());
+
+ return QAccessibleAbstractSlider::text(textType);
+}
+
+QDial *QAccessibleDial::dial() const
+{
+ return static_cast<QDial*>(object());
+}
+#endif // QT_NO_DIAL
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
diff --git a/src/widgets/accessible/rangecontrols.h b/src/widgets/accessible/rangecontrols.h
new file mode 100644
index 0000000000..dd69788bb1
--- /dev/null
+++ b/src/widgets/accessible/rangecontrols.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RANGECONTROLS_H
+#define RANGECONTROLS_H
+
+#include <QtWidgets/qaccessiblewidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractSpinBox;
+class QAbstractSlider;
+class QScrollBar;
+class QSlider;
+class QSpinBox;
+class QDoubleSpinBox;
+class QDial;
+
+#ifndef QT_NO_SPINBOX
+class QAccessibleAbstractSpinBox: public QAccessibleWidget, public QAccessibleValueInterface // TODO, public QAccessibleActionInterface
+{
+public:
+ explicit QAccessibleAbstractSpinBox(QWidget *w);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &value) Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+
+ // FIXME Action interface
+
+protected:
+ QAbstractSpinBox *abstractSpinBox() const;
+};
+
+class QAccessibleSpinBox : public QAccessibleAbstractSpinBox
+{
+public:
+ explicit QAccessibleSpinBox(QWidget *w);
+
+protected:
+ QSpinBox *spinBox() const;
+};
+
+class QAccessibleDoubleSpinBox : public QAccessibleAbstractSpinBox
+{
+public:
+ explicit QAccessibleDoubleSpinBox(QWidget *widget);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QDoubleSpinBox *doubleSpinBox() const;
+};
+#endif // QT_NO_SPINBOX
+
+class QAccessibleAbstractSlider: public QAccessibleWidget, public QAccessibleValueInterface
+{
+public:
+ explicit QAccessibleAbstractSlider(QWidget *w, QAccessible::Role r = QAccessible::Slider);
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &value) Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+
+protected:
+ QAbstractSlider *abstractSlider() const;
+};
+
+#ifndef QT_NO_SCROLLBAR
+class QAccessibleScrollBar : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleScrollBar(QWidget *w);
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QScrollBar *scrollBar() const;
+};
+#endif // QT_NO_SCROLLBAR
+
+#ifndef QT_NO_SLIDER
+class QAccessibleSlider : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleSlider(QWidget *w);
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+protected:
+ QSlider *slider() const;
+};
+#endif // QT_NO_SLIDER
+
+#ifndef QT_NO_DIAL
+class QAccessibleDial : public QAccessibleAbstractSlider
+{
+public:
+ explicit QAccessibleDial(QWidget *w);
+
+ QString text(QAccessible::Text textType) const Q_DECL_OVERRIDE;
+
+protected:
+ QDial *dial() const;
+};
+#endif // QT_NO_DIAL
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // RANGECONTROLS_H
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
new file mode 100644
index 0000000000..b729e66d3c
--- /dev/null
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -0,0 +1,886 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "simplewidgets.h"
+
+#include <qabstractbutton.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qprogressbar.h>
+#include <qstatusbar.h>
+#include <qradiobutton.h>
+#include <qtoolbutton.h>
+#include <qmenu.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qlcdnumber.h>
+#include <qlineedit.h>
+#include <private/qlineedit_p.h>
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include <qtextdocument.h>
+#include <qwindow.h>
+#include <private/qwindowcontainer_p.h>
+#include <QtCore/qvarlengtharray.h>
+
+#ifdef Q_OS_MAC
+#include <qfocusframe.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+extern QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel = false);
+
+QString qt_accStripAmp(const QString &text);
+QString qt_accHotKey(const QString &text);
+
+/*!
+ \class QAccessibleButton
+ \brief The QAccessibleButton class implements the QAccessibleInterface for button type widgets.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Creates a QAccessibleButton object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleButton::QAccessibleButton(QWidget *w, QAccessible::Role role)
+: QAccessibleWidget(w, role)
+{
+ Q_ASSERT(button());
+ if (button()->isCheckable())
+ addControllingSignal(QLatin1String("toggled(bool)"));
+ else
+ addControllingSignal(QLatin1String("clicked()"));
+}
+
+/*! Returns the button. */
+QAbstractButton *QAccessibleButton::button() const
+{
+ return qobject_cast<QAbstractButton*>(object());
+}
+
+/*! \reimp */
+QString QAccessibleButton::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Accelerator:
+ {
+#ifndef QT_NO_SHORTCUT
+ QPushButton *pb = qobject_cast<QPushButton*>(object());
+ if (pb && pb->isDefault())
+ str = QKeySequence(Qt::Key_Enter).toString(QKeySequence::NativeText);
+#endif
+ if (str.isEmpty())
+ str = qt_accHotKey(button()->text());
+ }
+ break;
+ case QAccessible::Name:
+ str = widget()->accessibleName();
+ if (str.isEmpty())
+ str = button()->text();
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+QAccessible::State QAccessibleButton::state() const
+{
+ QAccessible::State state = QAccessibleWidget::state();
+
+ QAbstractButton *b = button();
+ QCheckBox *cb = qobject_cast<QCheckBox *>(b);
+ if (b->isChecked())
+ state.checked = true;
+ else if (cb && cb->checkState() == Qt::PartiallyChecked)
+ state.checkStateMixed = true;
+ if (b->isDown())
+ state.pressed = true;
+ QPushButton *pb = qobject_cast<QPushButton*>(b);
+ if (pb) {
+ if (pb->isDefault())
+ state.defaultButton = true;
+#ifndef QT_NO_MENU
+ if (pb->menu())
+ state.hasPopup = true;
+#endif
+ }
+
+ return state;
+}
+
+QStringList QAccessibleButton::actionNames() const
+{
+ QStringList names;
+ if (widget()->isEnabled()) {
+ switch (role()) {
+ case QAccessible::ButtonMenu:
+ names << showMenuAction();
+ break;
+ case QAccessible::RadioButton:
+ names << toggleAction();
+ break;
+ default:
+ if (button()->isCheckable()) {
+ names << toggleAction();
+ } else {
+ names << pressAction();
+ }
+ break;
+ }
+ }
+ names << QAccessibleWidget::actionNames();
+ return names;
+}
+
+void QAccessibleButton::doAction(const QString &actionName)
+{
+ if (!widget()->isEnabled())
+ return;
+ if (actionName == pressAction() ||
+ actionName == showMenuAction()) {
+#ifndef QT_NO_MENU
+ QPushButton *pb = qobject_cast<QPushButton*>(object());
+ if (pb && pb->menu())
+ pb->showMenu();
+ else
+#endif
+ button()->animateClick();
+ } else if (actionName == toggleAction()) {
+ button()->toggle();
+ } else {
+ QAccessibleWidget::doAction(actionName);
+ }
+}
+
+QStringList QAccessibleButton::keyBindingsForAction(const QString &actionName) const
+{
+ if (actionName == pressAction()) {
+#ifndef QT_NO_SHORTCUT
+ return QStringList() << button()->shortcut().toString();
+#endif
+ }
+ return QStringList();
+}
+
+
+#ifndef QT_NO_TOOLBUTTON
+/*!
+ \class QAccessibleToolButton
+ \brief The QAccessibleToolButton class implements the QAccessibleInterface for tool buttons.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Creates a QAccessibleToolButton object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleToolButton::QAccessibleToolButton(QWidget *w, QAccessible::Role role)
+: QAccessibleButton(w, role)
+{
+ Q_ASSERT(toolButton());
+}
+
+/*! Returns the button. */
+QToolButton *QAccessibleToolButton::toolButton() const
+{
+ return qobject_cast<QToolButton*>(object());
+}
+
+/*!
+ Returns \c true if this tool button is a split button.
+*/
+bool QAccessibleToolButton::isSplitButton() const
+{
+#ifndef QT_NO_MENU
+ return toolButton()->menu() && toolButton()->popupMode() == QToolButton::MenuButtonPopup;
+#else
+ return false;
+#endif
+}
+
+QAccessible::State QAccessibleToolButton::state() const
+{
+ QAccessible::State st = QAccessibleButton::state();
+ if (toolButton()->autoRaise())
+ st.hotTracked = true;
+#ifndef QT_NO_MENU
+ if (toolButton()->menu())
+ st.hasPopup = true;
+#endif
+ return st;
+}
+
+int QAccessibleToolButton::childCount() const
+{
+ return isSplitButton() ? 1 : 0;
+}
+
+QAccessibleInterface *QAccessibleToolButton::child(int index) const
+{
+#ifndef QT_NO_MENU
+ if (index == 0 && toolButton()->menu())
+ {
+ return QAccessible::queryAccessibleInterface(toolButton()->menu());
+ }
+#endif
+ return 0;
+}
+
+/*!
+ \internal
+
+ Returns the button's text label, depending on the text \a t, and
+ the \a child.
+*/
+QString QAccessibleToolButton::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = toolButton()->accessibleName();
+ if (str.isEmpty())
+ str = toolButton()->text();
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleButton::text(t);
+ return qt_accStripAmp(str);
+}
+
+/*
+ The three different tool button types can have the following actions:
+| DelayedPopup | ShowMenuAction + (PressedAction || CheckedAction) |
+| MenuButtonPopup | ShowMenuAction + (PressedAction || CheckedAction) |
+| InstantPopup | ShowMenuAction |
+*/
+QStringList QAccessibleToolButton::actionNames() const
+{
+ QStringList names;
+ if (widget()->isEnabled()) {
+ if (toolButton()->menu())
+ names << showMenuAction();
+ if (toolButton()->popupMode() != QToolButton::InstantPopup)
+ names << QAccessibleButton::actionNames();
+ }
+ return names;
+}
+
+void QAccessibleToolButton::doAction(const QString &actionName)
+{
+ if (!widget()->isEnabled())
+ return;
+
+ if (actionName == pressAction()) {
+ button()->click();
+ } else if (actionName == showMenuAction()) {
+ if (toolButton()->popupMode() != QToolButton::InstantPopup) {
+ toolButton()->setDown(true);
+#ifndef QT_NO_MENU
+ toolButton()->showMenu();
+#endif
+ }
+ } else {
+ QAccessibleButton::doAction(actionName);
+ }
+
+}
+
+#endif // QT_NO_TOOLBUTTON
+
+/*!
+ \class QAccessibleDisplay
+ \brief The QAccessibleDisplay class implements the QAccessibleInterface for widgets that display information.
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleDisplay object for \a w.
+ \a role is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleDisplay::QAccessibleDisplay(QWidget *w, QAccessible::Role role)
+: QAccessibleWidget(w, role)
+{
+}
+
+QAccessible::Role QAccessibleDisplay::role() const
+{
+ QLabel *l = qobject_cast<QLabel*>(object());
+ if (l) {
+ if (l->pixmap())
+ return QAccessible::Graphic;
+#ifndef QT_NO_PICTURE
+ if (l->picture())
+ return QAccessible::Graphic;
+#endif
+#ifndef QT_NO_MOVIE
+ if (l->movie())
+ return QAccessible::Animation;
+#endif
+#ifndef QT_NO_PROGRESSBAR
+ } else if (qobject_cast<QProgressBar*>(object())) {
+ return QAccessible::ProgressBar;
+#endif
+ } else if (qobject_cast<QStatusBar*>(object())) {
+ return QAccessible::StatusBar;
+ }
+ return QAccessibleWidget::role();
+}
+
+QString QAccessibleDisplay::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Name:
+ str = widget()->accessibleName();
+ if (str.isEmpty()) {
+ if (qobject_cast<QLabel*>(object())) {
+ QLabel *label = qobject_cast<QLabel*>(object());
+ str = label->text();
+ if (label->textFormat() == Qt::RichText
+ || (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) {
+ QTextDocument doc;
+ doc.setHtml(str);
+ str = doc.toPlainText();
+ }
+#ifndef QT_NO_LCDNUMBER
+ } else if (qobject_cast<QLCDNumber*>(object())) {
+ QLCDNumber *l = qobject_cast<QLCDNumber*>(object());
+ if (l->digitCount())
+ str = QString::number(l->value());
+ else
+ str = QString::number(l->intValue());
+#endif
+ } else if (qobject_cast<QStatusBar*>(object())) {
+ return qobject_cast<QStatusBar*>(object())->currentMessage();
+ }
+ }
+ break;
+ case QAccessible::Value:
+#ifndef QT_NO_PROGRESSBAR
+ if (qobject_cast<QProgressBar*>(object()))
+ str = QString::number(qobject_cast<QProgressBar*>(object())->value());
+#endif
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+/*! \reimp */
+QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
+QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
+{
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
+ if (match & QAccessible::Labelled) {
+ QVarLengthArray<QObject *, 4> relatedObjects;
+
+#ifndef QT_NO_SHORTCUT
+ if (QLabel *label = qobject_cast<QLabel*>(object())) {
+ relatedObjects.append(label->buddy());
+ }
+#endif
+ for (int i = 0; i < relatedObjects.count(); ++i) {
+ const QAccessible::Relation rel = QAccessible::Labelled;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i));
+ if (iface)
+ rels.append(qMakePair(iface, rel));
+ }
+ }
+ return rels;
+}
+
+void *QAccessibleDisplay::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ImageInterface)
+ return static_cast<QAccessibleImageInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+/*! \internal */
+QString QAccessibleDisplay::imageDescription() const
+{
+#ifndef QT_NO_TOOLTIP
+ return widget()->toolTip();
+#else
+ return QString::null;
+#endif
+}
+
+/*! \internal */
+QSize QAccessibleDisplay::imageSize() const
+{
+ QLabel *label = qobject_cast<QLabel *>(widget());
+ if (!label)
+ return QSize();
+ const QPixmap *pixmap = label->pixmap();
+ if (!pixmap)
+ return QSize();
+ return pixmap->size();
+}
+
+/*! \internal */
+QPoint QAccessibleDisplay::imagePosition() const
+{
+ QLabel *label = qobject_cast<QLabel *>(widget());
+ if (!label)
+ return QPoint();
+ const QPixmap *pixmap = label->pixmap();
+ if (!pixmap)
+ return QPoint();
+
+ return QPoint(label->mapToGlobal(label->pos()));
+}
+
+#ifndef QT_NO_GROUPBOX
+QAccessibleGroupBox::QAccessibleGroupBox(QWidget *w)
+: QAccessibleWidget(w)
+{
+}
+
+QGroupBox* QAccessibleGroupBox::groupBox() const
+{
+ return static_cast<QGroupBox *>(widget());
+}
+
+QString QAccessibleGroupBox::text(QAccessible::Text t) const
+{
+ QString txt = QAccessibleWidget::text(t);
+
+ if (txt.isEmpty()) {
+ switch (t) {
+ case QAccessible::Name:
+ txt = qt_accStripAmp(groupBox()->title());
+ break;
+ case QAccessible::Description:
+ txt = qt_accStripAmp(groupBox()->toolTip());
+ break;
+ default:
+ break;
+ }
+ }
+
+ return txt;
+}
+
+QAccessible::State QAccessibleGroupBox::state() const
+{
+ QAccessible::State st = QAccessibleWidget::state();
+ st.checkable = groupBox()->isCheckable();
+ st.checked = groupBox()->isChecked();
+ return st;
+}
+
+QAccessible::Role QAccessibleGroupBox::role() const
+{
+ return groupBox()->isCheckable() ? QAccessible::CheckBox : QAccessible::Grouping;
+}
+
+QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
+QAccessibleGroupBox::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
+{
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
+
+ if ((match & QAccessible::Labelled) && (!groupBox()->title().isEmpty())) {
+ const QList<QWidget*> kids = childWidgets(widget());
+ for (int i = 0; i < kids.count(); ++i) {
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(kids.at(i));
+ if (iface)
+ rels.append(qMakePair(iface, QAccessible::Relation(QAccessible::Labelled)));
+ }
+ }
+ return rels;
+}
+
+QStringList QAccessibleGroupBox::actionNames() const
+{
+ QStringList actions = QAccessibleWidget::actionNames();
+
+ if (groupBox()->isCheckable()) {
+ actions.prepend(QAccessibleActionInterface::toggleAction());
+ }
+ return actions;
+}
+
+void QAccessibleGroupBox::doAction(const QString &actionName)
+{
+ if (actionName == QAccessibleActionInterface::toggleAction())
+ groupBox()->setChecked(!groupBox()->isChecked());
+}
+
+QStringList QAccessibleGroupBox::keyBindingsForAction(const QString &) const
+{
+ return QStringList();
+}
+
+#endif
+
+#ifndef QT_NO_LINEEDIT
+/*!
+ \class QAccessibleLineEdit
+ \brief The QAccessibleLineEdit class implements the QAccessibleInterface for widgets with editable text
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Constructs a QAccessibleLineEdit object for \a w.
+ \a name is propagated to the QAccessibleWidget constructor.
+*/
+QAccessibleLineEdit::QAccessibleLineEdit(QWidget *w, const QString &name)
+: QAccessibleWidget(w, QAccessible::EditableText, name)
+{
+ addControllingSignal(QLatin1String("textChanged(const QString&)"));
+ addControllingSignal(QLatin1String("returnPressed()"));
+}
+
+/*! Returns the line edit. */
+QLineEdit *QAccessibleLineEdit::lineEdit() const
+{
+ return qobject_cast<QLineEdit*>(object());
+}
+
+QString QAccessibleLineEdit::text(QAccessible::Text t) const
+{
+ QString str;
+ switch (t) {
+ case QAccessible::Value:
+ if (lineEdit()->echoMode() == QLineEdit::Normal)
+ str = lineEdit()->text();
+ break;
+ default:
+ break;
+ }
+ if (str.isEmpty())
+ str = QAccessibleWidget::text(t);
+ return qt_accStripAmp(str);
+}
+
+void QAccessibleLineEdit::setText(QAccessible::Text t, const QString &text)
+{
+ if (t != QAccessible::Value) {
+ QAccessibleWidget::setText(t, text);
+ return;
+ }
+
+ QString newText = text;
+ if (lineEdit()->validator()) {
+ int pos = 0;
+ if (lineEdit()->validator()->validate(newText, pos) != QValidator::Acceptable)
+ return;
+ }
+ lineEdit()->setText(newText);
+}
+
+QAccessible::State QAccessibleLineEdit::state() const
+{
+ QAccessible::State state = QAccessibleWidget::state();
+
+ QLineEdit *l = lineEdit();
+ if (l->isReadOnly())
+ state.readOnly = true;
+ else
+ state.editable = true;
+
+ if (l->echoMode() != QLineEdit::Normal)
+ state.passwordEdit = true;
+ state.selectable = true;
+ if (l->hasSelectedText())
+ state.selected = true;
+
+ if (l->contextMenuPolicy() != Qt::NoContextMenu
+ && l->contextMenuPolicy() != Qt::PreventContextMenu)
+ state.hasPopup = true;
+
+ return state;
+}
+
+void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ if (t == QAccessible::EditableTextInterface)
+ return static_cast<QAccessibleEditableTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+
+void QAccessibleLineEdit::addSelection(int startOffset, int endOffset)
+{
+ setSelection(0, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::attributes(int offset, int *startOffset, int *endOffset) const
+{
+ // QLineEdit doesn't have text attributes
+ *startOffset = *endOffset = offset;
+ return QString();
+}
+
+int QAccessibleLineEdit::cursorPosition() const
+{
+ return lineEdit()->cursorPosition();
+}
+
+QRect QAccessibleLineEdit::characterRect(int offset) const
+{
+ int x = lineEdit()->d_func()->control->cursorToX(offset);
+ int y;
+ lineEdit()->getTextMargins(0, &y, 0, 0);
+ QFontMetrics fm(lineEdit()->font());
+ const QString ch = text(offset, offset + 1);
+ if (ch.isEmpty())
+ return QRect();
+ int w = fm.width(ch);
+ int h = fm.height();
+ QRect r(x, y, w, h);
+ r.moveTo(lineEdit()->mapToGlobal(r.topLeft()));
+ return r;
+}
+
+int QAccessibleLineEdit::selectionCount() const
+{
+ return lineEdit()->hasSelectedText() ? 1 : 0;
+}
+
+int QAccessibleLineEdit::offsetAtPoint(const QPoint &point) const
+{
+ QPoint p = lineEdit()->mapFromGlobal(point);
+
+ return lineEdit()->cursorPositionAt(p);
+}
+
+void QAccessibleLineEdit::selection(int selectionIndex, int *startOffset, int *endOffset) const
+{
+ *startOffset = *endOffset = 0;
+ if (selectionIndex != 0)
+ return;
+
+ *startOffset = lineEdit()->selectionStart();
+ *endOffset = *startOffset + lineEdit()->selectedText().count();
+}
+
+QString QAccessibleLineEdit::text(int startOffset, int endOffset) const
+{
+ if (startOffset > endOffset)
+ return QString();
+
+ if (lineEdit()->echoMode() != QLineEdit::Normal)
+ return QString();
+
+ return lineEdit()->text().mid(startOffset, endOffset - startOffset);
+}
+
+QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const
+{
+ if (lineEdit()->echoMode() != QLineEdit::Normal) {
+ *startOffset = *endOffset = -1;
+ return QString();
+ }
+ return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
+}
+
+void QAccessibleLineEdit::removeSelection(int selectionIndex)
+{
+ if (selectionIndex != 0)
+ return;
+
+ lineEdit()->deselect();
+}
+
+void QAccessibleLineEdit::setCursorPosition(int position)
+{
+ lineEdit()->setCursorPosition(position);
+}
+
+void QAccessibleLineEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
+{
+ if (selectionIndex != 0)
+ return;
+
+ lineEdit()->setSelection(startOffset, endOffset - startOffset);
+}
+
+int QAccessibleLineEdit::characterCount() const
+{
+ return lineEdit()->text().count();
+}
+
+void QAccessibleLineEdit::scrollToSubstring(int startIndex, int endIndex)
+{
+ lineEdit()->setCursorPosition(endIndex);
+ lineEdit()->setCursorPosition(startIndex);
+}
+
+void QAccessibleLineEdit::deleteText(int startOffset, int endOffset)
+{
+ lineEdit()->setText(lineEdit()->text().remove(startOffset, endOffset - startOffset));
+}
+
+void QAccessibleLineEdit::insertText(int offset, const QString &text)
+{
+ lineEdit()->setText(lineEdit()->text().insert(offset, text));
+}
+
+void QAccessibleLineEdit::replaceText(int startOffset, int endOffset, const QString &text)
+{
+ lineEdit()->setText(lineEdit()->text().replace(startOffset, endOffset - startOffset, text));
+}
+
+#endif // QT_NO_LINEEDIT
+
+#ifndef QT_NO_PROGRESSBAR
+QAccessibleProgressBar::QAccessibleProgressBar(QWidget *o)
+ : QAccessibleDisplay(o)
+{
+ Q_ASSERT(progressBar());
+}
+
+void *QAccessibleProgressBar::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::ValueInterface)
+ return static_cast<QAccessibleValueInterface*>(this);
+ return QAccessibleDisplay::interface_cast(t);
+}
+
+QVariant QAccessibleProgressBar::currentValue() const
+{
+ return progressBar()->value();
+}
+
+QVariant QAccessibleProgressBar::maximumValue() const
+{
+ return progressBar()->maximum();
+}
+
+QVariant QAccessibleProgressBar::minimumValue() const
+{
+ return progressBar()->minimum();
+}
+
+QVariant QAccessibleProgressBar::minimumStepSize() const
+{
+ // This is arbitrary since any value between min and max is valid.
+ // Some screen readers (orca use it to calculate how many digits to display though,
+ // so it makes sense to return a "sensible" value. Providing 100 increments seems ok.
+ return (progressBar()->maximum() - progressBar()->minimum()) / 100.0;
+}
+
+QProgressBar *QAccessibleProgressBar::progressBar() const
+{
+ return qobject_cast<QProgressBar *>(object());
+}
+#endif
+
+
+QAccessibleWindowContainer::QAccessibleWindowContainer(QWidget *w)
+ : QAccessibleWidget(w)
+{
+}
+
+int QAccessibleWindowContainer::childCount() const
+{
+ if (container()->containedWindow())
+ return 1;
+ return 0;
+}
+
+int QAccessibleWindowContainer::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (child->object() == container()->containedWindow())
+ return 0;
+ return -1;
+}
+
+QAccessibleInterface *QAccessibleWindowContainer::child(int i) const
+{
+ if (i == 0)
+ return QAccessible::queryAccessibleInterface(container()->containedWindow());
+ return 0;
+}
+
+QWindowContainer *QAccessibleWindowContainer::container() const
+{
+ return static_cast<QWindowContainer *>(widget());
+}
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
diff --git a/src/widgets/accessible/simplewidgets.h b/src/widgets/accessible/simplewidgets.h
new file mode 100644
index 0000000000..be19d8324f
--- /dev/null
+++ b/src/widgets/accessible/simplewidgets.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIMPLEWIDGETS_H
+#define SIMPLEWIDGETS_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtWidgets/qaccessiblewidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAbstractButton;
+class QLineEdit;
+class QToolButton;
+class QGroupBox;
+class QProgressBar;
+
+class QAccessibleButton : public QAccessibleWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(QAccessibleButton)
+public:
+ QAccessibleButton(QWidget *w, QAccessible::Role r);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &actionName) const Q_DECL_OVERRIDE;
+
+protected:
+ QAbstractButton *button() const;
+};
+
+#ifndef QT_NO_TOOLBUTTON
+class QAccessibleToolButton : public QAccessibleButton
+{
+public:
+ QAccessibleToolButton(QWidget *w, QAccessible::Role role);
+
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+
+ int childCount() const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE;
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ // QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+
+protected:
+ QToolButton *toolButton() const;
+
+ bool isSplitButton() const;
+};
+#endif // QT_NO_TOOLBUTTON
+
+class QAccessibleDisplay : public QAccessibleWidget, public QAccessibleImageInterface
+{
+public:
+ explicit QAccessibleDisplay(QWidget *w, QAccessible::Role role = QAccessible::StaticText);
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >relations(QAccessible::Relation match = QAccessible::AllRelations) const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleImageInterface
+ QString imageDescription() const Q_DECL_OVERRIDE;
+ QSize imageSize() const Q_DECL_OVERRIDE;
+ QPoint imagePosition() const Q_DECL_OVERRIDE;
+};
+
+#ifndef QT_NO_GROUPBOX
+class QAccessibleGroupBox : public QAccessibleWidget
+{
+public:
+ explicit QAccessibleGroupBox(QWidget *w);
+
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ QAccessible::Role role() const Q_DECL_OVERRIDE;
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+
+ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >relations(QAccessible::Relation match = QAccessible::AllRelations) const Q_DECL_OVERRIDE;
+
+ //QAccessibleActionInterface
+ QStringList actionNames() const Q_DECL_OVERRIDE;
+ void doAction(const QString &actionName) Q_DECL_OVERRIDE;
+ QStringList keyBindingsForAction(const QString &) const Q_DECL_OVERRIDE;
+
+private:
+ QGroupBox *groupBox() const;
+};
+#endif
+
+#ifndef QT_NO_LINEEDIT
+class QAccessibleLineEdit : public QAccessibleWidget, public QAccessibleTextInterface, public QAccessibleEditableTextInterface
+{
+public:
+ explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString());
+
+ QString text(QAccessible::Text t) const Q_DECL_OVERRIDE;
+ void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE;
+ QAccessible::State state() const Q_DECL_OVERRIDE;
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleTextInterface
+ void addSelection(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ QString attributes(int offset, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ int cursorPosition() const Q_DECL_OVERRIDE;
+ QRect characterRect(int offset) const Q_DECL_OVERRIDE;
+ int selectionCount() const Q_DECL_OVERRIDE;
+ int offsetAtPoint(const QPoint &point) const Q_DECL_OVERRIDE;
+ void selection(int selectionIndex, int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString text(int startOffset, int endOffset) const Q_DECL_OVERRIDE;
+ QString textBeforeOffset (int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset) const Q_DECL_OVERRIDE;
+ void removeSelection(int selectionIndex) Q_DECL_OVERRIDE;
+ void setCursorPosition(int position) Q_DECL_OVERRIDE;
+ void setSelection(int selectionIndex, int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ int characterCount() const Q_DECL_OVERRIDE;
+ void scrollToSubstring(int startIndex, int endIndex) Q_DECL_OVERRIDE;
+
+ // QAccessibleEditableTextInterface
+ void deleteText(int startOffset, int endOffset) Q_DECL_OVERRIDE;
+ void insertText(int offset, const QString &text) Q_DECL_OVERRIDE;
+ void replaceText(int startOffset, int endOffset, const QString &text) Q_DECL_OVERRIDE;
+protected:
+ QLineEdit *lineEdit() const;
+};
+#endif // QT_NO_LINEEDIT
+
+#ifndef QT_NO_PROGRESSBAR
+class QAccessibleProgressBar : public QAccessibleDisplay, public QAccessibleValueInterface
+{
+public:
+ explicit QAccessibleProgressBar(QWidget *o);
+ void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE;
+
+ // QAccessibleValueInterface
+ QVariant currentValue() const Q_DECL_OVERRIDE;
+ QVariant maximumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumValue() const Q_DECL_OVERRIDE;
+ QVariant minimumStepSize() const Q_DECL_OVERRIDE;
+ void setCurrentValue(const QVariant &) Q_DECL_OVERRIDE {}
+
+protected:
+ QProgressBar *progressBar() const;
+};
+#endif
+
+class QWindowContainer;
+class QAccessibleWindowContainer : public QAccessibleWidget
+{
+public:
+ QAccessibleWindowContainer(QWidget *w);
+ int childCount() const Q_DECL_OVERRIDE;
+ int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE;
+ QAccessibleInterface *child(int i) const Q_DECL_OVERRIDE;
+
+private:
+ QWindowContainer *container() const;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+#endif // SIMPLEWIDGETS_H
diff --git a/src/widgets/accessible/widgets.pro b/src/widgets/accessible/widgets.pro
new file mode 100644
index 0000000000..aff60d9781
--- /dev/null
+++ b/src/widgets/accessible/widgets.pro
@@ -0,0 +1,26 @@
+TARGET = qtaccessiblewidgets
+
+PLUGIN_TYPE = accessible
+PLUGIN_CLASS_NAME = AccessibleFactory
+load(qt_plugin)
+
+QT += core-private gui-private widgets-private
+
+QTDIR_build:REQUIRES += "contains(QT_CONFIG, accessibility)"
+
+SOURCES += main.cpp \
+ simplewidgets.cpp \
+ rangecontrols.cpp \
+ complexwidgets.cpp \
+ qaccessiblewidgets.cpp \
+ qaccessiblemenu.cpp \
+ itemviews.cpp
+
+HEADERS += qaccessiblewidgets.h \
+ simplewidgets.h \
+ rangecontrols.h \
+ complexwidgets.h \
+ qaccessiblemenu.h \
+ itemviews.h
+
+
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 9e221c1bf4..c053fdfb22 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -77,6 +77,7 @@
#endif
#include "private/qkeymapper_p.h"
+#include "private/qaccessiblewidgetfactory_p.h"
#include <qthread.h>
#include <private/qthread_p.h>
@@ -557,6 +558,11 @@ void QApplicationPrivate::construct()
qt_gui_eval_init(application_type);
#endif
+#ifndef QT_NO_ACCESSIBILITY
+ // factory for accessible interfaces for widgets shipped with Qt
+ QAccessible::installFactory(&qAccessibleFactory);
+#endif
+
#ifndef QT_NO_LIBRARY
if(load_testability) {
QLibrary testLib(QLatin1String("qttestability"));
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index 0b289c75ae..c2cf4b7dfe 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -8,9 +8,6 @@ DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
-MODULE_PLUGIN_TYPES += \
- accessible/libqtaccessiblewidgets.so
-
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf
load(qt_module)