katie/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
Ivailo Monev b4b5590881 make it build with QT_NO_CAST_FROM_ASCII and QT_NO_CAST_TO_ASCII
at least the important components, tools, etc. the tests and the utilities
have not been fully tested and fixed yet not has this been tested on
platform other than Linux yet

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2016-06-15 02:32:57 +00:00

1940 lines
56 KiB
C++

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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 "qtextedit_p.h"
#include "qtextdocument.h"
#include "qtextobject.h"
#include "qplaintextedit.h"
#include "qscrollbar.h"
#include "qdebug.h"
#include <QApplication>
#include <QStackedWidget>
#include <QToolBox>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QWorkspace>
#include <QDialogButtonBox>
#include <limits.h>
#include <QRubberBand>
#include <QTextBrowser>
#include <QCalendarWidget>
#include <QAbstractItemView>
#include <QDockWidget>
#include <QMainWindow>
#include <QAbstractButton>
#include <qdockwidget_p.h>
#include <QtGui/QFocusFrame>
#ifndef QT_NO_ACCESSIBILITY
QT_BEGIN_NAMESPACE
using namespace QAccessible2;
QString Q_GUI_EXPORT qt_accStripAmp(const QString &text);
QString Q_GUI_EXPORT qt_accHotKey(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;
}
static inline int distance(QWidget *source, QWidget *target,
QAccessible::RelationFlag relation)
{
if (!source || !target)
return -1;
int returnValue = -1;
switch (relation) {
case QAccessible::Up:
if (target->y() <= source->y())
returnValue = source->y() - target->y();
break;
case QAccessible::Down:
if (target->y() >= source->y() + source->height())
returnValue = target->y() - (source->y() + source->height());
break;
case QAccessible::Right:
if (target->x() >= source->x() + source->width())
returnValue = target->x() - (source->x() + source->width());
break;
case QAccessible::Left:
if (target->x() <= source->x())
returnValue = source->x() - target->x();
break;
default:
break;
}
return returnValue;
}
static inline QWidget *mdiAreaNavigate(QWidget *area,
QAccessible::RelationFlag relation, int entry)
{
#if defined(QT_NO_MDIAREA) && defined(QT_NO_WORKSPACE)
Q_UNUSED(area);
#endif
#ifndef QT_NO_MDIAREA
const QMdiArea *mdiArea = qobject_cast<QMdiArea *>(area);
#endif
#ifndef QT_NO_WORKSPACE
const QWorkspace *workspace = qobject_cast<QWorkspace *>(area);
#endif
if (true
#ifndef QT_NO_MDIAREA
&& !mdiArea
#endif
#ifndef QT_NO_WORKSPACE
&& !workspace
#endif
)
return 0;
QWidgetList windows;
#ifndef QT_NO_MDIAREA
if (mdiArea) {
foreach (QMdiSubWindow *window, mdiArea->subWindowList())
windows.append(window);
} else
#endif
{
#ifndef QT_NO_WORKSPACE
foreach (QWidget *window, workspace->windowList())
windows.append(window->parentWidget());
#endif
}
if (windows.isEmpty() || entry < 1 || entry > windows.count())
return 0;
QWidget *source = windows.at(entry - 1);
QMap<int, QWidget *> candidates;
foreach (QWidget *window, windows) {
if (source == window)
continue;
int candidateDistance = distance(source, window, relation);
if (candidateDistance >= 0)
candidates.insert(candidateDistance, window);
}
int minimumDistance = INT_MAX;
QWidget *target = 0;
foreach (QWidget *candidate, candidates) {
switch (relation) {
case QAccessible::Up:
case QAccessible::Down:
if (qAbs(candidate->x() - source->x()) < minimumDistance) {
target = candidate;
minimumDistance = qAbs(candidate->x() - source->x());
}
break;
case QAccessible::Left:
case QAccessible::Right:
if (qAbs(candidate->y() - source->y()) < minimumDistance) {
target = candidate;
minimumDistance = qAbs(candidate->y() - source->y());
}
break;
default:
break;
}
if (minimumDistance == 0)
break;
}
#ifndef QT_NO_WORKSPACE
if (workspace) {
foreach (QWidget *widget, workspace->windowList()) {
if (widget->parentWidget() == target)
target = widget;
}
}
#endif
return target;
}
#ifndef QT_NO_TEXTEDIT
/*!
\class QAccessibleTextEdit
\brief The QAccessibleTextEdit class implements the QAccessibleInterface for richtext editors.
\internal
*/
static QTextBlock qTextBlockAt(const QTextDocument *doc, int pos)
{
Q_ASSERT(pos >= 0);
QTextBlock block = doc->begin();
int i = 0;
while (block.isValid() && i < pos) {
block = block.next();
++i;
}
return block;
}
static int qTextBlockPosition(QTextBlock block)
{
int child = 0;
while (block.isValid()) {
block = block.previous();
++child;
}
return child;
}
QAccessiblePlainTextEdit::QAccessiblePlainTextEdit(QWidget* o)
:QAccessibleTextWidget(o)
{
}
QPlainTextEdit* QAccessiblePlainTextEdit::plainTextEdit() const
{
return static_cast<QPlainTextEdit *>(widget());
}
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);
}
int QAccessiblePlainTextEdit::childCount() const
{
return 0;
}
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);
}
/*!
\fn QAccessibleTextEdit::QAccessibleTextEdit(QWidget* widget)
Constructs a QAccessibleTextEdit object for a \a widget.
*/
QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
: QAccessibleTextWidget(o, EditableText)
{
Q_ASSERT(widget()->inherits("QTextEdit"));
childOffset = QAccessibleWidget::childCount();
}
/*! 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;
}
QRect QAccessibleTextEdit::rect(int child) const
{
if (child <= childOffset)
return QAccessibleWidget::rect(child);
QTextEdit *edit = textEdit();
QTextBlock block = qTextBlockAt(edit->document(), child - childOffset - 1);
if (!block.isValid())
return QRect();
QRect rect = edit->document()->documentLayout()->blockBoundingRect(block).toRect();
rect.translate(-edit->horizontalScrollBar()->value(), -edit->verticalScrollBar()->value());
rect = edit->viewport()->rect().intersected(rect);
if (rect.isEmpty())
return QRect();
return rect.translated(edit->viewport()->mapToGlobal(QPoint(0, 0)));
}
int QAccessibleTextEdit::childAt(int x, int y) const
{
QTextEdit *edit = textEdit();
if (!edit->isVisible())
return -1;
QPoint point = edit->viewport()->mapFromGlobal(QPoint(x, y));
QTextBlock block = edit->cursorForPosition(point).block();
if (block.isValid())
return qTextBlockPosition(block) + childOffset;
return QAccessibleWidget::childAt(x, y);
}
/*! \reimp */
QString QAccessibleTextEdit::text(Text t, int child) const
{
if (t == Value) {
if (child > childOffset)
return qTextBlockAt(textEdit()->document(), child - childOffset - 1).text();
if (!child)
return textEdit()->toPlainText();
}
return QAccessibleWidget::text(t, child);
}
/*! \reimp */
void QAccessibleTextEdit::setText(Text t, int child, const QString &text)
{
if (t != Value || (child > 0 && child <= childOffset)) {
QAccessibleWidget::setText(t, child, text);
return;
}
if (textEdit()->isReadOnly())
return;
if (!child) {
textEdit()->setText(text);
return;
}
QTextBlock block = qTextBlockAt(textEdit()->document(), child - childOffset - 1);
if (!block.isValid())
return;
QTextCursor cursor(block);
cursor.select(QTextCursor::BlockUnderCursor);
cursor.insertText(text);
}
/*! \reimp */
QAccessible::Role QAccessibleTextEdit::role(int child) const
{
if (child > childOffset)
return EditableText;
return QAccessibleWidget::role(child);
}
QVariant QAccessibleTextEdit::invokeMethod(QAccessible::Method method, int child,
const QVariantList &params)
{
if (child)
return QVariant();
switch (method) {
case ListSupportedMethods: {
QSet<QAccessible::Method> set;
set << ListSupportedMethods << SetCursorPosition << GetCursorPosition;
return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >(
QAccessibleWidget::invokeMethod(method, child, params)));
}
case SetCursorPosition:
setCursorPosition(params.value(0).toInt());
return true;
case GetCursorPosition:
return textEdit()->textCursor().position();
default:
return QAccessibleWidget::invokeMethod(method, child, params);
}
}
int QAccessibleTextEdit::childCount() const
{
return childOffset + textEdit()->document()->blockCount();
}
#endif // QT_NO_TEXTEDIT
#ifndef QT_NO_STACKEDWIDGET
// ======================= QAccessibleStackedWidget ======================
QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
: QAccessibleWidget(widget, LayeredPane)
{
Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
}
QVariant QAccessibleStackedWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
int QAccessibleStackedWidget::childAt(int x, int y) const
{
if (!stackedWidget()->isVisible())
return -1;
QWidget *currentWidget = stackedWidget()->currentWidget();
if (!currentWidget)
return -1;
QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
if (currentWidget->rect().contains(position))
return 1;
return -1;
}
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());
int index = stackedWidget()->indexOf(widget);
if (index >= 0) // one based counting of children
return index + 1;
return -1;
}
int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
QObject *targetObject = 0;
switch (relation) {
case Child:
if (entry < 1 || entry > stackedWidget()->count())
return -1;
targetObject = stackedWidget()->widget(entry-1);
break;
default:
return QAccessibleWidget::navigate(relation, entry, target);
}
*target = QAccessible::queryAccessibleInterface(targetObject);
return *target ? 0 : -1;
}
QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
{
return static_cast<QStackedWidget *>(object());
}
#endif // QT_NO_STACKEDWIDGET
#ifndef QT_NO_TOOLBOX
// ======================= QAccessibleToolBox ======================
QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
: QAccessibleWidget(widget, LayeredPane)
{
Q_ASSERT(qobject_cast<QToolBox *>(widget));
}
QString QAccessibleToolBox::text(Text textType, int child) const
{
if (textType != Value || child <= 0 || child > toolBox()->count())
return QAccessibleWidget::text(textType, child);
return toolBox()->itemText(child - 1);
}
void QAccessibleToolBox::setText(Text textType, int child, const QString &text)
{
if (textType != Value || child <= 0 || child > toolBox()->count()) {
QAccessibleWidget::setText(textType, child, text);
return;
}
toolBox()->setItemText(child - 1, text);
}
QAccessible::State QAccessibleToolBox::state(int child) const
{
QWidget *childWidget = toolBox()->widget(child - 1);
if (!childWidget)
return QAccessibleWidget::state(child);
QAccessible::State childState = QAccessible::Normal;
if (toolBox()->currentWidget() == childWidget)
childState |= QAccessible::Expanded;
else
childState |= QAccessible::Collapsed;
return childState;
}
QVariant QAccessibleToolBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
int QAccessibleToolBox::childCount() const
{
return toolBox()->count();
}
int QAccessibleToolBox::indexOfChild(const QAccessibleInterface *child) const
{
if (!child)
return -1;
QWidget *childWidget = qobject_cast<QWidget *>(child->object());
if (!childWidget)
return -1;
int index = toolBox()->indexOf(childWidget);
if (index != -1)
++index;
return index;
}
int QAccessibleToolBox::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
if (entry <= 0 || entry > toolBox()->count())
return QAccessibleWidget::navigate(relation, entry, target);
int index = -1;
if (relation == QAccessible::Up)
index = entry - 2;
else if (relation == QAccessible::Down)
index = entry;
*target = QAccessible::queryAccessibleInterface(toolBox()->widget(index));
return *target ? 0: -1;
}
QToolBox * QAccessibleToolBox::toolBox() const
{
return static_cast<QToolBox *>(object());
}
#endif // QT_NO_TOOLBOX
// ======================= QAccessibleMdiArea ======================
#ifndef QT_NO_MDIAREA
QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
: QAccessibleWidget(widget, LayeredPane)
{
Q_ASSERT(qobject_cast<QMdiArea *>(widget));
}
QAccessible::State QAccessibleMdiArea::state(int child) const
{
if (child < 0)
return QAccessibleWidget::state(child);
if (child == 0)
return QAccessible::Normal;
QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
if (subWindows.isEmpty() || child > subWindows.count())
return QAccessibleWidget::state(child);
if (subWindows.at(child - 1) == mdiArea()->activeSubWindow())
return QAccessible::Focused;
return QAccessible::Normal;
}
QVariant QAccessibleMdiArea::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
int QAccessibleMdiArea::childCount() const
{
return mdiArea()->subWindowList().count();
}
int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
{
if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
return -1;
if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
int index = mdiArea()->subWindowList().indexOf(window);
if (index != -1)
return ++index;
}
return -1;
}
int QAccessibleMdiArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
QWidget *targetObject = 0;
QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
switch (relation) {
case Child:
if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
return -1;
targetObject = subWindows.at(entry - 1);
break;
case Up:
case Down:
case Left:
case Right:
targetObject = mdiAreaNavigate(mdiArea(), relation, entry);
break;
default:
return QAccessibleWidget::navigate(relation, entry, target);
}
*target = QAccessible::queryAccessibleInterface(targetObject);
return *target ? 0: -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(Text textType, int child) const
{
if (textType == QAccessible::Name && (child == 0 || child == 1)) {
QString title = mdiSubWindow()->windowTitle();
title.replace(QLatin1String("[*]"), QLatin1String(""));
return title;
}
return QAccessibleWidget::text(textType, child);
}
void QAccessibleMdiSubWindow::setText(Text textType, int child, const QString &text)
{
if (textType == QAccessible::Name && (child == 0 || child == 1))
mdiSubWindow()->setWindowTitle(text);
else
QAccessibleWidget::setText(textType, child, text);
}
QAccessible::State QAccessibleMdiSubWindow::state(int child) const
{
if (child != 0 || !mdiSubWindow()->parent())
return QAccessibleWidget::state(child);
QAccessible::State state = QAccessible::Normal | QAccessible::Focusable;
if (!mdiSubWindow()->isMaximized())
state |= (QAccessible::Movable | QAccessible::Sizeable);
if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
|| QApplication::focusWidget() == mdiSubWindow())
state |= QAccessible::Focused;
if (!mdiSubWindow()->isVisible())
state |= QAccessible::Invisible;
if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
state |= QAccessible::Offscreen;
if (!mdiSubWindow()->isEnabled())
state |= QAccessible::Unavailable;
return state;
}
QVariant QAccessibleMdiSubWindow::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
int QAccessibleMdiSubWindow::childCount() const
{
if (mdiSubWindow()->widget())
return 1;
return 0;
}
int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
{
if (child && child->object() && child->object() == mdiSubWindow()->widget())
return 1;
return -1;
}
int QAccessibleMdiSubWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
if (!mdiSubWindow()->parent())
return QAccessibleWidget::navigate(relation, entry, target);
QWidget *targetObject = 0;
QMdiSubWindow *source = mdiSubWindow();
switch (relation) {
case Child:
if (entry != 1 || !source->widget())
return -1;
targetObject = source->widget();
break;
case Up:
case Down:
case Left:
case Right: {
if (entry != 0)
break;
QWidget *parent = source->parentWidget();
while (parent && !parent->inherits("QMdiArea"))
parent = parent->parentWidget();
QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parent);
if (!mdiArea)
break;
int index = mdiArea->subWindowList().indexOf(source);
if (index == -1)
break;
if (QWidget *dest = mdiAreaNavigate(mdiArea, relation, index + 1)) {
*target = QAccessible::queryAccessibleInterface(dest);
return *target ? 0 : -1;
}
break;
}
default:
return QAccessibleWidget::navigate(relation, entry, target);
}
*target = QAccessible::queryAccessibleInterface(targetObject);
return *target ? 0: -1;
}
QRect QAccessibleMdiSubWindow::rect(int child) const
{
if (mdiSubWindow()->isHidden())
return QRect();
if (!mdiSubWindow()->parent())
return QAccessibleWidget::rect(child);
const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
if (child == 0)
return QRect(pos, mdiSubWindow()->size());
if (child == 1 && mdiSubWindow()->widget()) {
if (mdiSubWindow()->widget()->isHidden())
return QRect();
const QRect contentsRect = mdiSubWindow()->contentsRect();
return QRect(pos.x() + contentsRect.x(), pos.y() + contentsRect.y(),
contentsRect.width(), contentsRect.height());
}
return QRect();
}
int QAccessibleMdiSubWindow::childAt(int x, int y) const
{
if (!mdiSubWindow()->isVisible())
return -1;
if (!mdiSubWindow()->parent())
return QAccessibleWidget::childAt(x, y);
const QRect globalGeometry = rect(0);
if (!globalGeometry.isValid())
return -1;
const QRect globalChildGeometry = rect(1);
if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
return 1;
if (globalGeometry.contains(QPoint(x, y)))
return 0;
return -1;
}
QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
{
return static_cast<QMdiSubWindow *>(object());
}
#endif // QT_NO_MDIAREA
// ======================= QAccessibleWorkspace ======================
#ifndef QT_NO_WORKSPACE
QAccessibleWorkspace::QAccessibleWorkspace(QWidget *widget)
: QAccessibleWidget(widget, LayeredPane)
{
Q_ASSERT(qobject_cast<QWorkspace *>(widget));
}
QAccessible::State QAccessibleWorkspace::state(int child) const
{
if (child < 0)
return QAccessibleWidget::state(child);
if (child == 0)
return QAccessible::Normal;
QWidgetList subWindows = workspace()->windowList();
if (subWindows.isEmpty() || child > subWindows.count())
return QAccessibleWidget::state(child);
if (subWindows.at(child - 1) == workspace()->activeWindow())
return QAccessible::Focused;
return QAccessible::Normal;
}
QVariant QAccessibleWorkspace::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
int QAccessibleWorkspace::childCount() const
{
return workspace()->windowList().count();
}
int QAccessibleWorkspace::indexOfChild(const QAccessibleInterface *child) const
{
if (!child || !child->object() || workspace()->windowList().isEmpty())
return -1;
if (QWidget *window = qobject_cast<QWidget *>(child->object())) {
int index = workspace()->windowList().indexOf(window);
if (index != -1)
return ++index;
}
return -1;
}
int QAccessibleWorkspace::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
QWidget *targetObject = 0;
QWidgetList subWindows = workspace()->windowList();
switch (relation) {
case Child:
if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
return -1;
targetObject = subWindows.at(entry - 1);
break;
case Up:
case Down:
case Left:
case Right:
targetObject = mdiAreaNavigate(workspace(), relation, entry);
break;
default:
return QAccessibleWidget::navigate(relation, entry, target);
}
*target = QAccessible::queryAccessibleInterface(targetObject);
return *target ? 0: -1;
}
QWorkspace *QAccessibleWorkspace::workspace() const
{
return static_cast<QWorkspace *>(object());
}
#endif
#ifndef QT_NO_DIALOGBUTTONBOX
// ======================= QAccessibleDialogButtonBox ======================
QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
: QAccessibleWidget(widget, Grouping)
{
Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
}
QVariant QAccessibleDialogButtonBox::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
#endif // QT_NO_DIALOGBUTTONBOX
#ifndef QT_NO_TEXTBROWSER
QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
: QAccessibleTextEdit(widget)
{
Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
}
QAccessible::Role QAccessibleTextBrowser::role(int child) const
{
if (child != 0)
return QAccessibleTextEdit::role(child);
return QAccessible::StaticText;
}
#endif // QT_NO_TEXTBROWSER
#ifndef QT_NO_CALENDARWIDGET
// ===================== QAccessibleCalendarWidget ========================
QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
: QAccessibleWidget(widget, Table)
{
Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
}
QVariant QAccessibleCalendarWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
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();
return 1;
}
int QAccessibleCalendarWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
{
*target = 0;
if (entry <= 0 || entry > childCount())
return QAccessibleWidget::navigate(relation, entry, target);
QWidget *targetWidget = 0;
switch (relation) {
case Child:
if (childCount() == 1) {
targetWidget = calendarView();
} else {
if (entry == 1)
targetWidget = navigationBar();
else
targetWidget = calendarView();
}
break;
case Up:
if (entry == 2)
targetWidget = navigationBar();
break;
case Down:
if (entry == 1 && childCount() == 2)
targetWidget = calendarView();
break;
default:
return QAccessibleWidget::navigate(relation, entry, target);
}
*target = queryAccessibleInterface(targetWidget);
return *target ? 0: -1;
}
QRect QAccessibleCalendarWidget::rect(int child) const
{
if (!calendarWidget()->isVisible() || child > childCount())
return QRect();
if (child == 0)
return QAccessibleWidget::rect(child);
QWidget *childWidget = 0;
if (childCount() == 2)
childWidget = child == 1 ? navigationBar() : calendarView();
else
childWidget = calendarView();
return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
}
int QAccessibleCalendarWidget::childAt(int x, int y) const
{
const QPoint globalTargetPos = QPoint(x, y);
if (!rect(0).contains(globalTargetPos))
return -1;
if (rect(1).contains(globalTargetPos))
return 1;
if (rect(2).contains(globalTargetPos))
return 2;
return 0;
}
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
QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
: QAccessibleWidget(widget, Window)
{
}
int QAccessibleDockWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
{
if (relation == Child) {
if (entry == 1) {
*iface = new QAccessibleTitleBar(dockWidget());
return 0;
} else if (entry == 2) {
if (dockWidget()->widget())
*iface = QAccessible::queryAccessibleInterface(dockWidget()->widget());
return 0;
}
*iface = 0;
return -1;
}
return QAccessibleWidget::navigate(relation, entry, iface);
}
int QAccessibleDockWidget::childAt(int x, int y) const
{
for (int i = childCount(); i >= 0; --i) {
if (rect(i).contains(x,y))
return i;
}
return -1;
}
int QAccessibleDockWidget::childCount() const
{
return dockWidget()->widget() ? 2 : 1;
}
int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
{
if (child) {
if (child->role(0) == TitleBar) {
return 1;
} else {
return 2; //###
}
}
return -1;
}
QAccessible::Role QAccessibleDockWidget::role(int child) const
{
switch (child) {
case 0:
return Window;
case 1:
return TitleBar;
case 2:
//###
break;
default:
break;
}
return NoRole;
}
QAccessible::State QAccessibleDockWidget::state(int child) const
{
//### mark tabified widgets as invisible
return QAccessibleWidget::state(child);
}
QRect QAccessibleDockWidget::rect (int child ) const
{
QRect rect;
bool mapToGlobal = true;
if (child == 0) {
if (dockWidget()->isFloating()) {
rect = dockWidget()->frameGeometry();
mapToGlobal = false;
} else {
rect = dockWidget()->rect();
}
}else if (child == 1) {
QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
rect = layout->titleArea();
}else if (child == 2) {
if (dockWidget()->widget())
rect = dockWidget()->widget()->geometry();
}
if (rect.isNull())
return rect;
if (mapToGlobal)
rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
return rect;
}
QVariant QAccessibleDockWidget::invokeMethod(QAccessible::Method, int, const QVariantList &)
{
return QVariant();
}
QDockWidget *QAccessibleDockWidget::dockWidget() const
{
return static_cast<QDockWidget *>(object());
}
////
// QAccessibleTitleBar
////
QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget)
: m_dockWidget(widget)
{
}
int QAccessibleTitleBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
{
if (entry == 0 || relation == Self) {
*iface = new QAccessibleTitleBar(dockWidget());
return 0;
}
switch (relation) {
case Child:
case FocusChild:
if (entry >= 1) {
QDockWidgetLayout *layout = dockWidgetLayout();
int index = 1;
int role;
for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
if (!w->isVisible())
continue;
if (index == entry)
break;
++index;
}
*iface = 0;
return role > QDockWidgetLayout::FloatButton ? -1 : index;
}
break;
case Ancestor:
{
QAccessibleDockWidget *target = new QAccessibleDockWidget(dockWidget());
int index;
if (entry == 1) {
*iface = target;
return 0;
}
index = target->navigate(Ancestor, entry - 1, iface);
delete target;
return index;
break;}
case Sibling:
return navigate(Child, entry, iface);
break;
default:
break;
}
*iface = 0;
return -1;
}
QAccessible::Relation QAccessibleTitleBar::relationTo(int /*child*/, const QAccessibleInterface * /*other*/, int /*otherChild*/) const
{
return Unrelated; //###
}
int QAccessibleTitleBar::indexOfChild(const QAccessibleInterface * /*child*/) const
{
return -1;
}
int QAccessibleTitleBar::childCount() const
{
QDockWidgetLayout *layout = dockWidgetLayout();
int count = 0;
for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
if (w && w->isVisible())
++count;
}
return count;
}
QString QAccessibleTitleBar::text(Text t, int child) const
{
if (!child) {
if (t == Name || t == Value) {
return qt_accStripAmp(dockWidget()->windowTitle());
}
}
return QString();
}
QAccessible::State QAccessibleTitleBar::state(int child) const
{
QAccessible::State state = Normal;
if (child) {
QDockWidgetLayout *layout = dockWidgetLayout();
QAbstractButton *b = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
if (b) {
if (b->isDown())
state |= Pressed;
}
} else {
QDockWidget *w = dockWidget();
if (w->testAttribute(Qt::WA_WState_Visible) == false)
state |= Invisible;
if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
state |= Focusable;
if (w->hasFocus())
state |= Focused;
if (!w->isEnabled())
state |= Unavailable;
}
return state;
}
QRect QAccessibleTitleBar::rect(int child) const
{
bool mapToGlobal = true;
QRect rect;
if (child == 0) {
if (dockWidget()->isFloating()) {
rect = dockWidget()->frameGeometry();
if (dockWidget()->widget()) {
QPoint globalPos = dockWidget()->mapToGlobal(dockWidget()->widget()->rect().topLeft());
globalPos.ry()--;
rect.setBottom(globalPos.y());
mapToGlobal = false;
}
} else {
QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
rect = layout->titleArea();
}
}else if (child >= 1 && child <= childCount()) {
QDockWidgetLayout *layout = dockWidgetLayout();
int index = 1;
for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
if (!w || !w->isVisible())
continue;
if (index == child) {
rect = w->geometry();
break;
}
++index;
}
}
if (rect.isNull())
return rect;
if (mapToGlobal)
rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
return rect;
}
int QAccessibleTitleBar::childAt(int x, int y) const
{
for (int i = childCount(); i >= 0; --i) {
if (rect(i).contains(x,y))
return i;
}
return -1;
}
QObject *QAccessibleTitleBar::object() const
{
return 0;
}
QDockWidgetLayout *QAccessibleTitleBar::dockWidgetLayout() const
{
return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
}
QDockWidget *QAccessibleTitleBar::dockWidget() const
{
return m_dockWidget;
}
QString QAccessibleTitleBar::actionText(int action, Text t, int child) const
{
QString str;
if (child >= 1 && child <= childCount()) {
if (t == Name) {
switch (action) {
case Press:
case DefaultAction:
if (child == QDockWidgetLayout::CloseButton) {
str = QDockWidget::tr("Close");
} else if (child == QDockWidgetLayout::FloatButton) {
str = dockWidget()->isFloating() ? QDockWidget::tr("Dock")
: QDockWidget::tr("Float");
}
break;
default:
break;
}
}
}
return str;
}
bool QAccessibleTitleBar::doAction(int action, int child, const QVariantList& /*params*/)
{
if (!child || !dockWidget()->isEnabled())
return false;
switch (action) {
case DefaultAction:
case Press: {
QDockWidgetLayout *layout = dockWidgetLayout();
QAbstractButton *btn = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
if (btn)
btn->animateClick();
return true;
break;}
default:
break;
}
return false;
}
int QAccessibleTitleBar::userActionCount (int /*child*/) const
{
return 0;
}
QAccessible::Role QAccessibleTitleBar::role(int child) const
{
switch (child) {
case 0:
return TitleBar;
break;
default:
if (child >= 1 && child <= childCount())
return PushButton;
break;
}
return NoRole;
}
void QAccessibleTitleBar::setText(Text /*t*/, int /*child*/, const QString &/*text*/)
{
}
bool QAccessibleTitleBar::isValid() const
{
return dockWidget();
}
#endif // QT_NO_DOCKWIDGET
QAccessibleTextWidget::QAccessibleTextWidget(QWidget* o, QAccessible::Role r, const QString& name):
QAccessibleWidget(o, r, name)
{
}
void QAccessibleTextWidget::setAttributes(int startOffset, int endOffset, const QString& attributes)
{
//TODO: not implemented
Q_UNUSED(startOffset);
Q_UNUSED(endOffset);
Q_UNUSED(attributes);
}
QRect QAccessibleTextWidget::characterRect(int offset, CoordinateType coordType)
{
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);
qreal w = 0;
if ((relativeOffset - line.textStart())< line.textLength()) {
w = line.cursorToX(relativeOffset + 1) - x;
} else {
// If the width of a character is not known, IAccessible2 tells to return the width of a default character
int averageCharWidth = QFontMetrics(textCursor().charFormat().font()).averageCharWidth();
if (block.blockFormat().layoutDirection() == Qt::RightToLeft)
averageCharWidth *= -1;
r.setWidth(averageCharWidth);
}
int height = line.height();
// make sure that height does not include leading. (only ascent + descent + 1)
if (line.leadingIncluded())
height -= qRound(line.leading());
r = QRect(layoutPosition.x() + x, layoutPosition.y() + line.y(),
w, height);
if (coordType == RelativeToScreen) {
r.moveTo(viewport()->mapToGlobal(r.topLeft()));
}
r.translate(-scrollBarPosition());
}
return r;
}
int QAccessibleTextWidget::offsetAtPoint(const QPoint &point, CoordinateType coordType)
{
QPoint p = point;
if (coordType == RelativeToScreen)
p = viewport()->mapFromGlobal(p);
p += scrollBarPosition();
return textDocument()->documentLayout()->hitTest(p, Qt::ExactHit);
}
int QAccessibleTextWidget::selectionCount()
{
return textCursor().hasSelection() ? 1 : 0;
}
QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *endOffset)
{
/* 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(QLatin1Char('\\'), QLatin1String("\\\\"));
family = family.replace(QLatin1Char(':'), QLatin1String("\\:"));
family = family.replace(QLatin1Char(','), QLatin1String("\\,"));
family = family.replace(QLatin1Char('='), QLatin1String("\\="));
family = family.replace(QLatin1Char(';'), QLatin1String("\\;"));
family = family.replace(QLatin1Char('\"'), QLatin1String("\\\""));
attrs[QLatin1String("font-family")] = QLatin1Char('"') + family + QLatin1Char('"');
}
int fontSize = int(charFormat.fontPointSize());
if (fontSize)
attrs[QLatin1String("font-size")] = QString::number(fontSize).append(QLatin1String("pt"));
//Different weight values are not handled
attrs[QLatin1String("font-weight")] = (charFormat.fontWeight() > QFont::Normal) ? QLatin1String("bold") : QLatin1String("normal");
QFont::Style style = charFormat.font().style();
attrs[QLatin1String("font-style")] = (style == QFont::StyleItalic) ? QLatin1String("italic") : ((style == QFont::StyleOblique) ? QLatin1String("oblique"): QLatin1String("normal"));
attrs[QLatin1String("text-underline-style")] = charFormat.font().underline() ? QLatin1String("solid") : QLatin1String("none");
QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment();
attrs[QLatin1String("text-position")] = (alignment == QTextCharFormat::AlignSubScript) ? QLatin1String("sub") : ((alignment == QTextCharFormat::AlignSuperScript) ? QLatin1String("super") : QLatin1String("baseline") );
QBrush background = charFormat.background();
QString rgbString = QString::fromLatin1("rgb(%1,%2,%3)").arg(background.color().red()).arg(background.color().green()).arg(background.color().blue());
if (background.style() == Qt::SolidPattern) {
attrs[QLatin1String("background-color")] = rgbString;
}
QBrush foreground = charFormat.foreground();
if (foreground.style() == Qt::SolidPattern) {
attrs[QLatin1String("color")] = rgbString;
}
switch (blockFormat.alignment() & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | Qt::AlignJustify)) {
case Qt::AlignLeft:
attrs[QLatin1String("text-align")] = QLatin1String("left");
break;
case Qt::AlignRight:
attrs[QLatin1String("text-align")] = QLatin1String("right");
break;
case Qt::AlignHCenter:
attrs[QLatin1String("text-align")] = QLatin1String("center");
break;
case Qt::AlignJustify:
attrs[QLatin1String("text-align")] = QLatin1String("left");
break;
}
QString result;
foreach (const QString &attributeName, attrs.keys()) {
result.append(attributeName).append(QLatin1Char(':')).append(attrs[attributeName]).append(QLatin1Char(';'));
}
return result;
}
int QAccessibleTextWidget::cursorPosition()
{
return textCursor().position();
}
void QAccessibleTextWidget::selection(int selectionIndex, int *startOffset, int *endOffset)
{
*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)
{
QTextCursor cursor = textCursor();
cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
return cursor.selectedText();
}
QPoint QAccessibleTextWidget::scrollBarPosition() const
{
return QPoint(0, 0);
}
QPair< int, int > QAccessibleTextWidget::getBoundaries(int offset, BoundaryType boundaryType)
{
if (offset >= characterCount())
return QPair<int, int>(characterCount(), characterCount());
if (offset < 0)
return QPair<int, int>(0, 0);
QTextCursor cursor = textCursor();
QPair<int, int> result;
cursor.setPosition(offset);
switch (boundaryType) {
case CharBoundary:
result.first = cursor.position();
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
result.second = cursor.position();
break;
case WordBoundary:
cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
result.first = cursor.position();
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
result.second = cursor.position();
break;
case SentenceBoundary:
// TODO - what's a sentence?
case LineBoundary:
cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
result.first = cursor.position();
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
result.second = cursor.position();
break;
case ParagraphBoundary:
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
result.first = cursor.position();
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
result.second = cursor.position();
break;
case NoBoundary:
result.first = 0;
result.second = characterCount();
break;
default:
qDebug("QAccessibleTextWidget::getBoundaries: Unknown boundary type %d", boundaryType);
result.first = -1;
result.second = -1;
}
return result;
}
QString QAccessibleTextWidget::textBeforeOffset (int offset, BoundaryType boundaryType,
int *startOffset, int *endOffset)
{
Q_ASSERT(startOffset);
Q_ASSERT(endOffset);
QPair<int, int> boundaries = getBoundaries(offset, boundaryType);
boundaries = getBoundaries(boundaries.first - 1, boundaryType);
*startOffset = boundaries.first;
*endOffset = boundaries.second;
return text(boundaries.first, boundaries.second);
}
QString QAccessibleTextWidget::textAfterOffset (int offset, BoundaryType boundaryType,
int *startOffset, int *endOffset)
{
Q_ASSERT(startOffset);
Q_ASSERT(endOffset);
QPair<int, int> boundaries = getBoundaries(offset, boundaryType);
boundaries = getBoundaries(boundaries.second, boundaryType);
*startOffset = boundaries.first;
*endOffset = boundaries.second;
return text(boundaries.first, boundaries.second);
}
QString QAccessibleTextWidget::textAtOffset(int offset, BoundaryType boundaryType,
int *startOffset, int *endOffset)
{
Q_ASSERT(startOffset);
Q_ASSERT(endOffset);
QPair<int, int> boundaries = getBoundaries(offset, 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()
{
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);
}
void QAccessibleTextWidget::copyText(int startOffset, int endOffset)
{
#ifndef QT_NO_CLIPBOARD
QString text = this->text(startOffset, endOffset);
QApplication::clipboard()->setText(text);
#endif
}
void QAccessibleTextWidget::cutText(int startOffset, int endOffset)
{
#ifndef QT_NO_CLIPBOARD
QString text = this->text(startOffset, endOffset);
QApplication::clipboard()->setText(text);
deleteText(startOffset, endOffset);
#endif
}
void QAccessibleTextWidget::pasteText(int offset)
{
#ifndef QT_NO_CLIPBOARD
QString text = QApplication::clipboard()->text();
insertText(offset, text);
#endif
}
#ifndef QT_NO_TEXTEDIT
void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
{
QTextEdit *edit = textEdit();
QTextCursor cursor(edit->document());
cursor.setPosition(startIndex);
QRect r = edit->cursorRect(cursor);
cursor.setPosition(endIndex);
r.setBottomRight(edit->cursorRect(cursor).bottomRight());
r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
r.y() + edit->verticalScrollBar()->value());
// E V I L, but ensureVisible is not public
if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
qWarning("AccessibleTextEdit::scrollToSubstring failed!");
}
void QAccessibleTextEdit::copyText(int startOffset, int endOffset)
{
#ifndef QT_NO_CLIPBOARD
QTextCursor previousCursor = textEdit()->textCursor();
QTextCursor cursor = textCursorForRange(startOffset, endOffset);
if (!cursor.hasSelection())
return;
textEdit()->setTextCursor(cursor);
textEdit()->copy();
textEdit()->setTextCursor(previousCursor);
#endif
}
void QAccessibleTextEdit::cutText(int startOffset, int endOffset)
{
#ifndef QT_NO_CLIPBOARD
QTextCursor cursor = textCursorForRange(startOffset, endOffset);
if (!cursor.hasSelection())
return;
textEdit()->setTextCursor(cursor);
textEdit()->cut();
#endif
}
void QAccessibleTextEdit::pasteText(int offset)
{
QTextEdit *edit = textEdit();
QTextCursor oldCursor = edit->textCursor();
QTextCursor newCursor = oldCursor;
newCursor.setPosition(offset);
edit->setTextCursor(newCursor);
#ifndef QT_NO_CLIPBOARD
edit->paste();
#endif
edit->setTextCursor(oldCursor);
}
void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes)
{
// TODO
Q_UNUSED(startOffset);
Q_UNUSED(endOffset);
Q_UNUSED(attributes);
}
#endif // QT_NO_TEXTEDIT
#ifndef QT_NO_MAINWINDOW
QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
: QAccessibleWidget(widget, Window) { }
QVariant QAccessibleMainWindow::invokeMethod(QAccessible::Method /*method*/, int /*child*/, const QVariantList & /*params*/)
{
return QVariant();
}
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);
int childIndex = kids.indexOf(static_cast<QWidget*>(iface->object()));
return childIndex == -1 ? -1 : ++childIndex;
}
int QAccessibleMainWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
{
if (relation == Child && entry >= 1) {
QList<QWidget*> kids = childWidgets(mainWindow(), true);
if (entry <= kids.count()) {
*iface = QAccessible::queryAccessibleInterface(kids.at(entry - 1));
return *iface ? 0 : -1;
}
}
return QAccessibleWidget::navigate(relation, entry, iface);
}
int QAccessibleMainWindow::childAt(int x, int y) const
{
QWidget *w = widget();
if (!w->isVisible())
return -1;
QPoint gp = w->mapToGlobal(QPoint(0, 0));
if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
return -1;
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 i + 1;
}
}
return 0;
}
QMainWindow *QAccessibleMainWindow::mainWindow() const
{
return qobject_cast<QMainWindow *>(object());
}
#endif //QT_NO_MAINWINDOW
QT_END_NAMESPACE
#endif // QT_NO_ACCESSIBILITY