diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-06-27 13:23:01 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-08-19 14:23:13 +0200 |
commit | 41f496cb7f63da012f73bfe7904c225e91d300da (patch) | |
tree | 1d2d6514ee86e2fd6a4d596450478f679178eeaf /src | |
parent | cf621f1b9e472d394bcab922d0a1a205bc539b02 (diff) |
Accessibility: QSpinBox should not have any children
On both iOS and Android it is very confusing to be able to move the focus to both, the line edit and the outer frame that is the spin box.
For Linux this fixes an issue that orca would not read the value correctly after pressing the up/down buttons.
Task-number: QTBUG-39861
Task-number: QTBUG-39442
Change-Id: I73c50c91e9021324c52d168d537afd0ea719a48f
Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/widgets/accessible/qaccessiblewidget.cpp | 3 | ||||
-rw-r--r-- | src/widgets/accessible/qaccessiblewidgetfactory.cpp | 5 | ||||
-rw-r--r-- | src/widgets/accessible/rangecontrols.cpp | 118 | ||||
-rw-r--r-- | src/widgets/accessible/rangecontrols.h | 38 | ||||
-rw-r--r-- | src/widgets/accessible/simplewidgets.h | 1 | ||||
-rw-r--r-- | src/widgets/widgets/qabstractspinbox.cpp | 1 | ||||
-rw-r--r-- | src/widgets/widgets/qabstractspinbox.h | 1 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgetlinecontrol.cpp | 18 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgetlinecontrol_p.h | 17 |
9 files changed, 188 insertions, 14 deletions
diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 48f99f4d35..89fc988329 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -70,7 +70,8 @@ static QList<QWidget*> childWidgets(const QWidget *widget) #if !defined(QT_NO_MENU) && !qobject_cast<QMenu*>(w) #endif - && w->objectName() != QLatin1String("qt_rubberband")) + && w->objectName() != QLatin1String("qt_rubberband") + && w->objectName() != QLatin1String("qt_spinbox_lineedit")) widgets.append(w); } return widgets; diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp index 3d123cc9ab..fb81a4aaeb 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory.cpp +++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp @@ -66,7 +66,10 @@ QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *obje if (false) { #ifndef QT_NO_LINEEDIT } else if (classname == QLatin1String("QLineEdit")) { - iface = new QAccessibleLineEdit(widget); + if (widget->objectName() == QLatin1String("qt_spinbox_lineedit")) + iface = 0; + else + iface = new QAccessibleLineEdit(widget); #endif #ifndef QT_NO_COMBOBOX } else if (classname == QLatin1String("QComboBox")) { diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp index d4dc74ea69..e16b99c25e 100644 --- a/src/widgets/accessible/rangecontrols.cpp +++ b/src/widgets/accessible/rangecontrols.cpp @@ -51,20 +51,28 @@ #include <qglobal.h> #include <QDoubleSpinBox> #include <QDial> +#include <QtWidgets/qlineedit.h> #include <qmath.h> #include <private/qmath_p.h> +#include "simplewidgets.h" // let spinbox use line edit's interface + QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY #ifndef QT_NO_SPINBOX QAccessibleAbstractSpinBox::QAccessibleAbstractSpinBox(QWidget *w) -: QAccessibleWidget(w, QAccessible::SpinBox) +: QAccessibleWidget(w, QAccessible::SpinBox), lineEdit(Q_NULLPTR) { Q_ASSERT(abstractSpinBox()); } +QAccessibleAbstractSpinBox::~QAccessibleAbstractSpinBox() +{ + delete lineEdit; +} + /*! Returns the underlying QAbstractSpinBox. */ @@ -73,6 +81,14 @@ QAbstractSpinBox *QAccessibleAbstractSpinBox::abstractSpinBox() const return qobject_cast<QAbstractSpinBox*>(object()); } +QAccessibleInterface *QAccessibleAbstractSpinBox::lineEditIface() const +{ + // QAccessibleLineEdit is only used to forward the text functions + if (!lineEdit) + lineEdit = new QAccessibleLineEdit(abstractSpinBox()->lineEdit()); + return lineEdit; +} + QString QAccessibleAbstractSpinBox::text(QAccessible::Text t) const { if (t == QAccessible::Value) @@ -84,6 +100,10 @@ void *QAccessibleAbstractSpinBox::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::ValueInterface) return static_cast<QAccessibleValueInterface*>(this); + if (t == QAccessible::TextInterface) + return static_cast<QAccessibleTextInterface*>(this); + if (t == QAccessible::EditableTextInterface) + return static_cast<QAccessibleEditableTextInterface*>(this); return QAccessibleWidget::interface_cast(t); } @@ -112,6 +132,102 @@ QVariant QAccessibleAbstractSpinBox::minimumStepSize() const return abstractSpinBox()->property("stepSize"); } +void QAccessibleAbstractSpinBox::addSelection(int startOffset, int endOffset) +{ + lineEditIface()->textInterface()->addSelection(startOffset, endOffset); +} + +QString QAccessibleAbstractSpinBox::attributes(int offset, int *startOffset, int *endOffset) const +{ + return lineEditIface()->textInterface()->attributes(offset, startOffset, endOffset); +} + +int QAccessibleAbstractSpinBox::cursorPosition() const +{ + return lineEditIface()->textInterface()->cursorPosition(); +} + +QRect QAccessibleAbstractSpinBox::characterRect(int offset) const +{ + return lineEditIface()->textInterface()->characterRect(offset); +} + +int QAccessibleAbstractSpinBox::selectionCount() const +{ + return lineEditIface()->textInterface()->selectionCount(); +} + +int QAccessibleAbstractSpinBox::offsetAtPoint(const QPoint &point) const +{ + return lineEditIface()->textInterface()->offsetAtPoint(point); +} + +void QAccessibleAbstractSpinBox::selection(int selectionIndex, int *startOffset, int *endOffset) const +{ + lineEditIface()->textInterface()->selection(selectionIndex, startOffset, endOffset); +} + +QString QAccessibleAbstractSpinBox::text(int startOffset, int endOffset) const +{ + return lineEditIface()->textInterface()->text(startOffset, endOffset); +} + +QString QAccessibleAbstractSpinBox::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const +{ + return lineEditIface()->textInterface()->textBeforeOffset(offset, boundaryType, startOffset, endOffset); +} + +QString QAccessibleAbstractSpinBox::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const +{ + return lineEditIface()->textInterface()->textAfterOffset(offset, boundaryType, startOffset, endOffset); +} + +QString QAccessibleAbstractSpinBox::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const +{ + return lineEditIface()->textInterface()->textAtOffset(offset, boundaryType, startOffset, endOffset); +} + +void QAccessibleAbstractSpinBox::removeSelection(int selectionIndex) +{ + lineEditIface()->textInterface()->removeSelection(selectionIndex); +} + +void QAccessibleAbstractSpinBox::setCursorPosition(int position) +{ + lineEditIface()->textInterface()->setCursorPosition(position); +} + +void QAccessibleAbstractSpinBox::setSelection(int selectionIndex, int startOffset, int endOffset) +{ + lineEditIface()->textInterface()->setSelection(selectionIndex, startOffset, endOffset); +} + +int QAccessibleAbstractSpinBox::characterCount() const +{ + return lineEditIface()->textInterface()->characterCount(); +} + +void QAccessibleAbstractSpinBox::scrollToSubstring(int startIndex, int endIndex) +{ + lineEditIface()->textInterface()->scrollToSubstring(startIndex, endIndex); +} + +void QAccessibleAbstractSpinBox::deleteText(int startOffset, int endOffset) +{ + lineEditIface()->editableTextInterface()->deleteText(startOffset, endOffset); +} + +void QAccessibleAbstractSpinBox::insertText(int offset, const QString &text) +{ + lineEditIface()->editableTextInterface()->insertText(offset, text); +} + +void QAccessibleAbstractSpinBox::replaceText(int startOffset, int endOffset, const QString &text) +{ + lineEditIface()->editableTextInterface()->replaceText(startOffset, endOffset, text); +} + + /*! \class QAccessibleSpinBox \brief The QAccessibleSpinBox class implements the QAccessibleInterface for spinbox widgets. diff --git a/src/widgets/accessible/rangecontrols.h b/src/widgets/accessible/rangecontrols.h index 98cef46c5c..158e1cfcc0 100644 --- a/src/widgets/accessible/rangecontrols.h +++ b/src/widgets/accessible/rangecontrols.h @@ -55,12 +55,18 @@ class QSlider; class QSpinBox; class QDoubleSpinBox; class QDial; +class QAccessibleLineEdit; #ifndef QT_NO_SPINBOX -class QAccessibleAbstractSpinBox: public QAccessibleWidget, public QAccessibleValueInterface // TODO, public QAccessibleActionInterface +class QAccessibleAbstractSpinBox: + public QAccessibleWidget, + public QAccessibleValueInterface, + public QAccessibleTextInterface, + public QAccessibleEditableTextInterface { public: explicit QAccessibleAbstractSpinBox(QWidget *w); + virtual ~QAccessibleAbstractSpinBox(); QString text(QAccessible::Text t) const Q_DECL_OVERRIDE; void *interface_cast(QAccessible::InterfaceType t) Q_DECL_OVERRIDE; @@ -72,10 +78,37 @@ public: QVariant minimumValue() const Q_DECL_OVERRIDE; QVariant minimumStepSize() const Q_DECL_OVERRIDE; - // FIXME Action interface + // 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 *endOffset, int *startOffset) 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: QAbstractSpinBox *abstractSpinBox() const; + QAccessibleInterface *lineEditIface() const; +private: + mutable QAccessibleLineEdit *lineEdit; }; class QAccessibleSpinBox : public QAccessibleAbstractSpinBox @@ -94,6 +127,7 @@ public: QString text(QAccessible::Text t) const Q_DECL_OVERRIDE; + using QAccessibleAbstractSpinBox::text; protected: QDoubleSpinBox *doubleSpinBox() const; }; diff --git a/src/widgets/accessible/simplewidgets.h b/src/widgets/accessible/simplewidgets.h index e4ce6150e2..7dce0b3589 100644 --- a/src/widgets/accessible/simplewidgets.h +++ b/src/widgets/accessible/simplewidgets.h @@ -174,6 +174,7 @@ public: void replaceText(int startOffset, int endOffset, const QString &text) Q_DECL_OVERRIDE; protected: QLineEdit *lineEdit() const; + friend class QAccessibleAbstractSpinBox; }; #endif // QT_NO_LINEEDIT diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 43f5d6fd31..4aed153932 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -699,6 +699,7 @@ void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit) } d->updateEditFieldGeometry(); d->edit->setContextMenuPolicy(Qt::NoContextMenu); + d->edit->d_func()->control->setAccessibleObject(this); if (isVisible()) d->edit->show(); diff --git a/src/widgets/widgets/qabstractspinbox.h b/src/widgets/widgets/qabstractspinbox.h index 7989000cc8..5009e4151f 100644 --- a/src/widgets/widgets/qabstractspinbox.h +++ b/src/widgets/widgets/qabstractspinbox.h @@ -170,6 +170,7 @@ private: Q_DECLARE_PRIVATE(QAbstractSpinBox) Q_DISABLE_COPY(QAbstractSpinBox) + friend class QAccessibleAbstractSpinBox; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractSpinBox::StepEnabled) diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index b927004773..2743e4cbbf 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -737,15 +737,15 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite #ifndef QT_NO_ACCESSIBILITY if (changed) { if (oldText.isEmpty()) { - QAccessibleTextInsertEvent event(parent(), 0, txt); + QAccessibleTextInsertEvent event(accessibleObject(), 0, txt); event.setCursorPosition(m_cursor); QAccessible::updateAccessibility(&event); } else if (txt.isEmpty()) { - QAccessibleTextRemoveEvent event(parent(), 0, oldText); + QAccessibleTextRemoveEvent event(accessibleObject(), 0, oldText); event.setCursorPosition(m_cursor); QAccessible::updateAccessibility(&event); } else { - QAccessibleTextUpdateEvent event(parent(), 0, oldText, txt); + QAccessibleTextUpdateEvent event(accessibleObject(), 0, oldText, txt); event.setCursorPosition(m_cursor); QAccessible::updateAccessibility(&event); } @@ -803,7 +803,7 @@ void QWidgetLineControl::internalInsert(const QString &s) if (m_maskData) { QString ms = maskString(m_cursor, s); #ifndef QT_NO_ACCESSIBILITY - QAccessibleTextInsertEvent insertEvent(parent(), m_cursor, ms); + QAccessibleTextInsertEvent insertEvent(accessibleObject(), m_cursor, ms); QAccessible::updateAccessibility(&insertEvent); #endif for (int i = 0; i < (int) ms.length(); ++i) { @@ -815,14 +815,14 @@ void QWidgetLineControl::internalInsert(const QString &s) m_cursor = nextMaskBlank(m_cursor); m_textDirty = true; #ifndef QT_NO_ACCESSIBILITY - QAccessibleTextCursorEvent event(parent(), m_cursor); + QAccessibleTextCursorEvent event(accessibleObject(), m_cursor); QAccessible::updateAccessibility(&event); #endif } else { int remaining = m_maxLength - m_text.length(); if (remaining != 0) { #ifndef QT_NO_ACCESSIBILITY - QAccessibleTextInsertEvent insertEvent(parent(), m_cursor, s); + QAccessibleTextInsertEvent insertEvent(accessibleObject(), m_cursor, s); QAccessible::updateAccessibility(&insertEvent); #endif m_text.insert(m_cursor, s.left(remaining)); @@ -853,7 +853,7 @@ void QWidgetLineControl::internalDelete(bool wasBackspace) 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(parent(), m_cursor, m_text.at(m_cursor)); + QAccessibleTextRemoveEvent event(accessibleObject(), m_cursor, m_text.at(m_cursor)); QAccessible::updateAccessibility(&event); #endif if (m_maskData) { @@ -894,7 +894,7 @@ void QWidgetLineControl::removeSelectedText() addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); } #ifndef QT_NO_ACCESSIBILITY - QAccessibleTextRemoveEvent event(parent(), m_selstart, m_text.mid(m_selstart, m_selend - m_selstart)); + QAccessibleTextRemoveEvent event(accessibleObject(), m_selstart, m_text.mid(m_selstart, m_selend - m_selstart)); QAccessible::updateAccessibility(&event); #endif if (m_maskData) { @@ -1384,7 +1384,7 @@ void QWidgetLineControl::emitCursorPositionChanged() #ifndef QT_NO_ACCESSIBILITY // otherwise we send a selection update which includes the cursor if (!hasSelectedText()) { - QAccessibleTextCursorEvent event(parent(), m_cursor); + QAccessibleTextCursorEvent event(accessibleObject(), m_cursor); QAccessible::updateAccessibility(&event); } #endif diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index ba73e9e25e..153067bd59 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -99,6 +99,7 @@ public: , m_passwordMaskDelayOverride(-1) #endif , m_keyboardScheme(0) + , m_accessibleObject(0) { init(txt); } @@ -108,6 +109,19 @@ public: delete [] m_maskData; } + void setAccessibleObject(QObject *object) + { + Q_ASSERT(object); + m_accessibleObject = object; + } + + QObject *accessibleObject() + { + if (m_accessibleObject) + return m_accessibleObject; + return parent(); + } + int nextMaskBlank(int pos) { int c = findInMask(pos, true, false); @@ -532,6 +546,9 @@ private Q_SLOTS: private: int m_keyboardScheme; + + // accessibility events are sent for this object + QObject *m_accessibleObject; }; QT_END_NAMESPACE |