Accessibility: add text update events

Change-Id: Iece9d100b3f5a379d7d8e29dea67a10d0c918c06
Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>
This commit is contained in:
Frederik Gladhorn 2012-01-30 18:52:46 +01:00 committed by Qt by Nokia
parent 478658fd41
commit 477c43260e
9 changed files with 347 additions and 36 deletions

View File

@ -268,16 +268,16 @@ QT_BEGIN_NAMESPACE
row's header, has been changed.
\value TableRowHeaderChanged A table row header has been changed.
\value TableSummaryChanged The summary of a table has been changed.
\value TextAttributeChanged
\value TextCaretMoved The caret has moved in an editable widget.
\omitvalue TextAttributeChanged
\omitvalue TextCaretMoved The caret has moved in an editable widget.
The caret represents the cursor position in an editable
widget with the input focus.
\value TextColumnChanged A text column has been changed.
\value TextInserted Text has been inserted into an editable widget.
\value TextRemoved Text has been removed from an editable widget.
\value TextSelectionChanged The selected text has changed in an editable widget.
\value TextUpdated The text has been update in an editable widget.
\value ValueChanged The QAccessible::Value of an object has changed.
\omitvalue TextInserted Text has been inserted into an editable widget.
\omitvalue TextRemoved Text has been removed from an editable widget.
\omitvalue TextSelectionChanged The selected text has changed in an editable widget.
\omitvalue TextUpdated The text has been update in an editable widget.
\omitvalue ValueChanged The QAccessible::Value of an object has changed.
\value VisibleDataChanged
The values for this enum are defined to be the same as those defined in the

View File

@ -145,7 +145,9 @@ public:
ParentChanged = 0x800F,
HelpChanged = 0x80A0,
DefaultActionChanged = 0x80B0,
AcceleratorChanged = 0x80C0
AcceleratorChanged = 0x80C0,
InvalidEvent
};
// 64 bit enums seem hard on some platforms (windows...)
@ -436,6 +438,15 @@ public:
: m_type(typ), m_object(obj), m_child(chld)
{
Q_ASSERT(obj);
// All events below have a subclass of QAccessibleEvent.
// Use the subclass, since it's expected that it's possible to cast to that.
Q_ASSERT(m_type != QAccessible::ValueChanged);
Q_ASSERT(m_type != QAccessible::StateChanged);
Q_ASSERT(m_type != QAccessible::TextCaretMoved);
Q_ASSERT(m_type != QAccessible::TextSelectionChanged);
Q_ASSERT(m_type != QAccessible::TextInserted);
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
}
virtual ~QAccessibleEvent()
@ -448,7 +459,6 @@ public:
QAccessibleInterface *accessibleInterface() const;
protected:
QAccessible::Event m_type;
QObject *m_object;
int m_child;
@ -458,8 +468,10 @@ class Q_GUI_EXPORT QAccessibleStateChangeEvent :public QAccessibleEvent
{
public:
inline QAccessibleStateChangeEvent(QAccessible::State state, QObject *obj, int chld = -1)
: QAccessibleEvent(QAccessible::StateChanged, obj, chld), m_changedStates(state)
{}
: QAccessibleEvent(QAccessible::InvalidEvent, obj, chld), m_changedStates(state)
{
m_type = QAccessible::StateChanged;
}
QAccessible::State changedStates() const {
return m_changedStates;
@ -469,6 +481,133 @@ protected:
QAccessible::State m_changedStates;
};
// Update the cursor and optionally the selection.
class Q_GUI_EXPORT QAccessibleTextCursorEvent : public QAccessibleEvent
{
public:
inline QAccessibleTextCursorEvent(int cursorPos, QObject *obj, int chld = -1)
: QAccessibleEvent(QAccessible::InvalidEvent, obj, chld)
, m_cursorPosition(cursorPos)
{
m_type = QAccessible::TextCaretMoved;
}
void setCursorPosition(int position) { m_cursorPosition = position; }
int cursorPosition() const { return m_cursorPosition; }
protected:
int m_cursorPosition;
};
// Updates the cursor position simultaneously. By default the cursor is set to the end of the selection.
class Q_GUI_EXPORT QAccessibleTextSelectionEvent : public QAccessibleTextCursorEvent
{
public:
inline QAccessibleTextSelectionEvent(int start, int end, QObject *obj, int chld = -1)
: QAccessibleTextCursorEvent((start == -1) ? 0 : end, obj, chld)
, m_selectionStart(start), m_selectionEnd(end)
{
m_type = QAccessible::TextSelectionChanged;
}
void setSelection(int start, int end) {
m_selectionStart = start;
m_selectionEnd = end;
}
int selectionStart() const { return m_selectionStart; }
int selectionEnd() const { return m_selectionEnd; }
protected:
int m_selectionStart;
int m_selectionEnd;
};
class Q_GUI_EXPORT QAccessibleTextInsertEvent : public QAccessibleTextCursorEvent
{
public:
inline QAccessibleTextInsertEvent(int position, const QString &text, QObject *obj, int chld = -1)
: QAccessibleTextCursorEvent(position + text.length(), obj, chld)
, m_position(position), m_text(text)
{
m_type = QAccessible::TextInserted;
}
QString textInserted() const {
return m_text;
}
int changePosition() const {
return m_position;
}
protected:
int m_position;
QString m_text;
};
class Q_GUI_EXPORT QAccessibleTextRemoveEvent : public QAccessibleTextCursorEvent
{
public:
inline QAccessibleTextRemoveEvent(int position, const QString &text, QObject *obj, int chld = -1)
: QAccessibleTextCursorEvent(position, obj, chld)
, m_position(position), m_text(text)
{
m_type = QAccessible::TextRemoved;
}
QString textRemoved() const {
return m_text;
}
int changePosition() const {
return m_position;
}
protected:
int m_position;
QString m_text;
};
class Q_GUI_EXPORT QAccessibleTextUpdateEvent : public QAccessibleTextCursorEvent
{
public:
inline QAccessibleTextUpdateEvent(int position, const QString &oldText, const QString &text, QObject *obj, int chld = -1)
: QAccessibleTextCursorEvent(position + text.length(), obj, chld)
, m_position(position), m_oldText(oldText), m_text(text)
{
m_type = QAccessible::TextUpdated;
}
QString textRemoved() const {
return m_oldText;
}
QString textInserted() const {
return m_text;
}
int changePosition() const {
return m_position;
}
protected:
int m_position;
QString m_oldText;
QString m_text;
};
class Q_GUI_EXPORT QAccessibleValueChangeEvent : public QAccessibleEvent
{
public:
inline QAccessibleValueChangeEvent(const QVariant &val, QObject *obj, int chld = -1)
: QAccessibleEvent(QAccessible::InvalidEvent, obj, chld)
, m_value(val)
{
m_type = QAccessible::ValueChanged;
}
void setValue(const QVariant & val) { m_value= val; }
QVariant value() const { return m_value; }
protected:
QVariant m_value;
};
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)

View File

@ -68,14 +68,51 @@ typedef QList<QAccessibleEvent*> EventList;
bool operator==(const QAccessibleEvent &l, const QAccessibleEvent &r)
{
if (l.type() != r.type() ||
l.object() != r.object() ||
l.child() != r.child())
if (l.type() != r.type()) {
// qDebug() << "QAccessibleEvent with wrong type: " << qAccessibleEventString(l.type()) << " and " << qAccessibleEventString(r.type());
return false;
}
if (l.object() != r.object() ||
l.child() != r.child()) {
// qDebug() << "QAccessibleEvent for wrong object: " << l.object() << " and " << r.object() << " child: " << l.child() << " and " << r.child();
return false;
}
if (l.type() == QAccessible::StateChanged) {
return static_cast<const QAccessibleStateChangeEvent*>(&l)->changedStates()
== static_cast<const QAccessibleStateChangeEvent*>(&r)->changedStates();
} else if (l.type() == QAccessible::TextCaretMoved) {
return static_cast<const QAccessibleTextCursorEvent*>(&l)->cursorPosition()
== static_cast<const QAccessibleTextCursorEvent*>(&r)->cursorPosition();
} else if (l.type() == QAccessible::TextSelectionChanged) {
const QAccessibleTextSelectionEvent *le = static_cast<const QAccessibleTextSelectionEvent*>(&l);
const QAccessibleTextSelectionEvent *re = static_cast<const QAccessibleTextSelectionEvent*>(&r);
return le->cursorPosition() == re->cursorPosition() &&
le->selectionStart() == re->selectionStart() &&
le->selectionEnd() == re->selectionEnd();
} else if (l.type() == QAccessible::TextInserted) {
const QAccessibleTextInsertEvent *le = static_cast<const QAccessibleTextInsertEvent*>(&l);
const QAccessibleTextInsertEvent *re = static_cast<const QAccessibleTextInsertEvent*>(&r);
return le->cursorPosition() == re->cursorPosition() &&
le->changePosition() == re->changePosition() &&
le->textInserted() == re->textInserted();
} else if (l.type() == QAccessible::TextRemoved) {
const QAccessibleTextRemoveEvent *le = static_cast<const QAccessibleTextRemoveEvent*>(&l);
const QAccessibleTextRemoveEvent *re = static_cast<const QAccessibleTextRemoveEvent*>(&r);
return le->cursorPosition() == re->cursorPosition() &&
le->changePosition() == re->changePosition() &&
le->textRemoved() == re->textRemoved();
} else if (l.type() == QAccessible::TextUpdated) {
const QAccessibleTextUpdateEvent *le = static_cast<const QAccessibleTextUpdateEvent*>(&l);
const QAccessibleTextUpdateEvent *re = static_cast<const QAccessibleTextUpdateEvent*>(&r);
return le->cursorPosition() == re->cursorPosition() &&
le->changePosition() == re->changePosition() &&
le->textInserted() == re->textInserted() &&
le->textRemoved() == re->textRemoved();
} else if (l.type() == QAccessible::ValueChanged) {
const QAccessibleValueChangeEvent *le = static_cast<const QAccessibleValueChangeEvent*>(&l);
const QAccessibleValueChangeEvent *re = static_cast<const QAccessibleValueChangeEvent*>(&r);
return le->value() == re->value();
}
return true;
}
@ -108,7 +145,7 @@ public:
return res;
}
static bool containsEvent(QAccessibleEvent *event) {
Q_FOREACH (QAccessibleEvent *ev, eventList()) {
Q_FOREACH (const QAccessibleEvent *ev, eventList()) {
if (*ev == *event)
return true;
}
@ -146,9 +183,34 @@ private:
}
static QAccessibleEvent *copyEvent(QAccessibleEvent *event)
{
if (event->type() == QAccessible::StateChanged)
return new QAccessibleStateChangeEvent(static_cast<const QAccessibleStateChangeEvent*>(event)->changedStates(),
if (event->type() == QAccessible::StateChanged) {
return new QAccessibleStateChangeEvent(static_cast<QAccessibleStateChangeEvent*>(event)->changedStates(),
event->object(), event->child());
} else if (event->type() == QAccessible::TextCaretMoved) {
return new QAccessibleTextCursorEvent(static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition(), event->object(), event->child());
} else if (event->type() == QAccessible::TextSelectionChanged) {
const QAccessibleTextSelectionEvent *original = static_cast<QAccessibleTextSelectionEvent*>(event);
QAccessibleTextSelectionEvent *ev = new QAccessibleTextSelectionEvent(original->selectionStart(), original->selectionEnd(), event->object(), event->child());
ev->setCursorPosition(original->cursorPosition());
return ev;
} else if (event->type() == QAccessible::TextInserted) {
const QAccessibleTextInsertEvent *original = static_cast<QAccessibleTextInsertEvent*>(event);
QAccessibleTextInsertEvent *ev = new QAccessibleTextInsertEvent(original->changePosition(), original->textInserted(), event->object(), event->child());
ev->setCursorPosition(original->cursorPosition());
return ev;
} else if (event->type() == QAccessible::TextRemoved) {
const QAccessibleTextRemoveEvent *original = static_cast<QAccessibleTextRemoveEvent*>(event);
QAccessibleTextRemoveEvent *ev = new QAccessibleTextRemoveEvent(original->changePosition(), original->textRemoved(), event->object(), event->child());
ev->setCursorPosition(original->cursorPosition());
return ev;
} else if (event->type() == QAccessible::TextUpdated) {
const QAccessibleTextUpdateEvent *original = static_cast<QAccessibleTextUpdateEvent*>(event);
QAccessibleTextUpdateEvent *ev = new QAccessibleTextUpdateEvent(original->changePosition(), original->textRemoved(), original->textInserted(), event->object(), event->child());
ev->setCursorPosition(original->cursorPosition());
return ev;
} else if (event->type() == QAccessible::ValueChanged) {
return new QAccessibleValueChangeEvent(static_cast<QAccessibleValueChangeEvent*>(event)->value(), event->object(), event->child());
}
return new QAccessibleEvent(event->type(), event->object(), event->child());
}

View File

@ -538,7 +538,7 @@ void QAbstractSlider::setValue(int value)
emit sliderMoved((d->position = value));
}
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::ValueChanged, this);
QAccessibleValueChangeEvent event(d->value, this);
QAccessible::updateAccessibility(&event);
#endif
sliderChange(SliderValueChange);

View File

@ -976,7 +976,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
}
}
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::ValueChanged, this);
QAccessibleValueChangeEvent event(d->value, this);
QAccessible::updateAccessibility(&event);
#endif
return;
@ -1596,7 +1596,7 @@ void QAbstractSpinBoxPrivate::updateState(bool up, bool fromKeyboard /* = false
buttonState = (up ? Up : Down) | (fromKeyboard ? Keyboard : Mouse);
q->stepBy(up ? 1 : -1);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::ValueChanged, q);
QAccessibleValueChangeEvent event(value, q);
QAccessible::updateAccessibility(&event);
#endif
}

View File

@ -144,8 +144,9 @@ void QLineEditPrivate::_q_selectionChanged()
emit q->selectionChanged();
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::TextSelectionChanged, q);
QAccessible::updateAccessibility(&event);
QAccessibleTextSelectionEvent ev(control->selectionStart(), control->selectionEnd(), q);
ev.setCursorPosition(control->cursorPosition());
QAccessible::updateAccessibility(&ev);
#endif
}

View File

@ -314,7 +314,7 @@ void QProgressBar::setValue(int value)
d->value = value;
emit valueChanged(value);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::ValueChanged, this);
QAccessibleValueChangeEvent event(value, this);
QAccessible::updateAccessibility(&event);
#endif
if (d->repaintRequired())

View File

@ -768,8 +768,19 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
#ifndef QT_NO_ACCESSIBILITY
if (changed) {
QAccessibleEvent event(QAccessible::TextUpdated, parent());
QAccessible::updateAccessibility(&event);
if (oldText.isEmpty()) {
QAccessibleTextInsertEvent event(0, txt, parent());
event.setCursorPosition(m_cursor);
QAccessible::updateAccessibility(&event);
} else if (txt.isEmpty()) {
QAccessibleTextRemoveEvent event(0, oldText, parent());
event.setCursorPosition(m_cursor);
QAccessible::updateAccessibility(&event);
} else {
QAccessibleTextUpdateEvent event(0, oldText, txt, parent());
event.setCursorPosition(m_cursor);
QAccessible::updateAccessibility(&event);
}
}
#endif
}
@ -816,6 +827,10 @@ void QWidgetLineControl::internalInsert(const QString &s)
addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
if (m_maskData) {
QString ms = maskString(m_cursor, s);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextInsertEvent insertEvent(m_cursor, ms, parent());
QAccessible::updateAccessibility(&insertEvent);
#endif
for (int i = 0; i < (int) ms.length(); ++i) {
addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
@ -824,9 +839,17 @@ void QWidgetLineControl::internalInsert(const QString &s)
m_cursor += ms.length();
m_cursor = nextMaskBlank(m_cursor);
m_textDirty = true;
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextCursorEvent event(m_cursor, parent());
QAccessible::updateAccessibility(&event);
#endif
} else {
int remaining = m_maxLength - m_text.length();
if (remaining != 0) {
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextInsertEvent insertEvent(m_cursor, s, parent());
QAccessible::updateAccessibility(&insertEvent);
#endif
m_text.insert(m_cursor, s.left(remaining));
for (int i = 0; i < (int) s.left(remaining).length(); ++i)
addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
@ -854,6 +877,10 @@ void QWidgetLineControl::internalDelete(bool wasBackspace)
addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
m_cursor, m_text.at(m_cursor), -1, -1));
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextRemoveEvent event(m_cursor, m_text.at(m_cursor), parent());
QAccessible::updateAccessibility(&event);
#endif
if (m_maskData) {
m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
@ -891,6 +918,10 @@ void QWidgetLineControl::removeSelectedText()
for (i = m_selend-1; i >= m_selstart; --i)
addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
}
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextRemoveEvent event(m_selstart, m_text.mid(m_selstart, m_selend - m_selstart), parent());
QAccessible::updateAccessibility(&event);
#endif
if (m_maskData) {
m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart));
for (int i = 0; i < m_selend - m_selstart; ++i)
@ -1369,8 +1400,11 @@ void QWidgetLineControl::emitCursorPositionChanged()
m_lastCursorPos = m_cursor;
cursorPositionChanged(oldLast, m_cursor);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(QAccessible::TextCaretMoved, parent());
QAccessible::updateAccessibility(&event);
// otherwise we send a selection update which includes the cursor
if (!hasSelectedText()) {
QAccessibleTextCursorEvent event(m_cursor, parent());
QAccessible::updateAccessibility(&event);
}
#endif
}
}

View File

@ -1475,7 +1475,7 @@ void tst_QAccessibility::spinBoxTest()
QTestAccessibility::clearEvents();
QTest::keyPress(spinBox, Qt::Key_Up);
QTest::qWait(200);
QAccessibleEvent expectedEvent(QAccessible::ValueChanged, spinBox);
QAccessibleValueChangeEvent expectedEvent(spinBox->value(), spinBox);
QVERIFY(QTestAccessibility::containsEvent(&expectedEvent));
delete spinBox;
QTestAccessibility::clearEvents();
@ -1695,8 +1695,10 @@ void tst_QAccessibility::mdiSubWindowTest()
void tst_QAccessibility::lineEditTest()
{
QWidget *toplevel = new QWidget;
{
QLineEdit *le = new QLineEdit;
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
QAIPtr iface(QAccessible::queryAccessibleInterface(le));
QVERIFY(iface);
le->show();
@ -1727,7 +1729,6 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(!(iface->state().passwordEdit));
QCOMPARE(iface->text(QAccessible::Value), secret);
QWidget *toplevel = new QWidget;
le->setParent(toplevel);
toplevel->show();
QApplication::processEvents();
@ -1754,20 +1755,23 @@ void tst_QAccessibility::lineEditTest()
iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
QCOMPARE(le->text(), QLatin1String("500"));
delete iface;
delete le;
delete le2;
QTestAccessibility::clearEvents();
}
// IA2
{
// Text interface to get the current text
QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde";
QLineEdit *le3 = new QLineEdit(cite, toplevel);
iface = QAccessible::queryAccessibleInterface(le3);
le3->show();
QAIPtr iface(QAccessible::queryAccessibleInterface(le3));
QAccessibleTextInterface* textIface = iface->textInterface();
le3->deselect();
QTestAccessibility::clearEvents();
le3->setCursorPosition(3);
QCOMPARE(textIface->cursorPosition(), 3);
QAccessibleEvent caretEvent(QAccessible::TextCaretMoved, le3);
QAccessibleTextCursorEvent caretEvent(3, le3);
QTRY_VERIFY(QTestAccessibility::containsEvent(&caretEvent));
QCOMPARE(textIface->selectionCount(), 0);
QTestAccessibility::clearEvents();
@ -1813,7 +1817,78 @@ void tst_QAccessibility::lineEditTest()
QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
delete iface;
QTestAccessibility::clearEvents();
}
{
// Test events: cursor movement, selection, text changes
QString text = "Hello, world";
QLineEdit *lineEdit = new QLineEdit(text, toplevel);
lineEdit->show();
QTestAccessibility::clearEvents();
// cursor
lineEdit->setCursorPosition(5);
QAccessibleTextCursorEvent cursorEvent(5, lineEdit);
QVERIFY_EVENT(&cursorEvent);
lineEdit->setCursorPosition(0);
cursorEvent.setCursorPosition(0);
QVERIFY_EVENT(&cursorEvent);
// selection
lineEdit->setSelection(2, 4);
QAccessibleTextSelectionEvent sel(2, 2+4, lineEdit);
QVERIFY_EVENT(&sel);
lineEdit->selectAll();
sel.setSelection(0, lineEdit->text().length());
sel.setCursorPosition(lineEdit->text().length());
QVERIFY_EVENT(&sel);
lineEdit->setSelection(10, -4);
QCOMPARE(lineEdit->cursorPosition(), 6);
QAccessibleTextSelectionEvent sel2(6, 10, lineEdit);
sel2.setCursorPosition(6);
QVERIFY_EVENT(&sel2);
lineEdit->deselect();
QAccessibleTextSelectionEvent sel3(-1, -1, lineEdit);
sel3.setCursorPosition(6);
QVERIFY_EVENT(&sel3);
// editing
lineEdit->clear();
// FIXME: improve redundant updates
QAccessibleTextRemoveEvent remove(0, text, lineEdit);
QVERIFY_EVENT(&remove);
QAccessibleTextSelectionEvent noSel(-1, -1, lineEdit);
QVERIFY_EVENT(&noSel);
QAccessibleTextCursorEvent cursor(0, lineEdit);
QVERIFY_EVENT(&cursor);
lineEdit->setText("foo");
qDebug() << QTestAccessibility::events();
cursorEvent.setCursorPosition(3);
QVERIFY_EVENT(&cursorEvent);
QAccessibleTextInsertEvent e(0, "foo", lineEdit);
QVERIFY(QTestAccessibility::containsEvent(&e));
lineEdit->setText("bar");
QAccessibleTextUpdateEvent update(0, "foo", "bar", lineEdit);
QVERIFY(QTestAccessibility::containsEvent(&update));
// QTestEventList keys;
// keys.addKeyClick('D');
// keys.addKeyClick('E');
// keys.addKeyClick(Qt::Key_Left);
// keys.addKeyClick(Qt::Key_Left);
// keys.addKeyClick('C');
// keys.addKeyClick('O');
// keys.simulate(lineEdit);
// FIXME: Test key press events...
}
delete toplevel;
QTestAccessibility::clearEvents();
}