diff options
-rw-r--r-- | src/plugins/accessible/widgets/qaccessiblewidgets.cpp | 228 | ||||
-rw-r--r-- | src/plugins/accessible/widgets/qaccessiblewidgets.h | 23 | ||||
-rw-r--r-- | src/widgets/widgets/qdockwidget.cpp | 10 | ||||
-rw-r--r-- | tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 133 |
4 files changed, 144 insertions, 250 deletions
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index cbb3092b1d..79a5c82fe0 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -558,37 +558,56 @@ QWidget *QAccessibleCalendarWidget::navigationBar() const #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()); } -QAccessibleInterface *QAccessibleDockWidget::child(int index) const +int QAccessibleDockWidget::childCount() const { - if (index == 0) { - return new QAccessibleTitleBar(dockWidget()); - } else if (index == 1 && dockWidget()->widget()) { - return QAccessible::queryAccessibleInterface(dockWidget()->widget()); + if (dockWidget()->titleBarWidget()) { + return dockWidget()->widget() ? 2 : 1; } - return 0; + return dockWidgetLayout()->count(); } -int QAccessibleDockWidget::childCount() const +QAccessibleInterface *QAccessibleDockWidget::child(int index) const { - return dockWidget()->widget() ? 2 : 1; + 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) { - if (child->role() == QAccessible::TitleBar) { - return 0; - } else { - return 1; // FIXME - } + if (!child || !child->object() || child->object()->parent() != object()) + return -1; + + if (dockWidget()->titleBarWidget() == child->object()) { + return dockWidget()->widget() ? 1 : 0; } - return -1; + + return dockWidgetLayout()->indexOf(qobject_cast<QWidget*>(child->object())); } QRect QAccessibleDockWidget::rect() const @@ -610,190 +629,13 @@ QDockWidget *QAccessibleDockWidget::dockWidget() const return static_cast<QDockWidget *>(object()); } -//// -// QAccessibleTitleBar -//// -QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget) - : m_dockWidget(widget) -{ - -} - -QAccessibleInterface *QAccessibleTitleBar::parent() const -{ - return new QAccessibleDockWidget(dockWidget()); -} - -QAccessibleInterface *QAccessibleTitleBar::child(int index) const -{ - if (index >= 0) { - QDockWidgetLayout *layout = dockWidgetLayout(); - int role; - int currentIndex = 0; - for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) { - QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role); - if (!w || !w->isVisible()) - continue; - if (currentIndex == index) - return QAccessible::queryAccessibleInterface(w); - ++currentIndex; - } - } - return 0; -} - -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(QAccessible::Text t) const +QString QAccessibleDockWidget::text(QAccessible::Text t) const { if (t == QAccessible::Name || t == QAccessible::Value) { return qt_accStripAmp(dockWidget()->windowTitle()); } return QString(); } - -QAccessible::State QAccessibleTitleBar::state() const -{ - QAccessible::State state; - - QDockWidget *w = dockWidget(); - if (w->testAttribute(Qt::WA_WState_Visible) == false) - state.invisible = true; - if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow()) - state.focusable = true; - if (w->hasFocus()) - state.focused = true; - if (!w->isEnabled()) - state.disabled = true; - - return state; -} - -QRect QAccessibleTitleBar::rect() const -{ - bool mapToGlobal = true; - QRect rect; - - 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(); - } - - if (rect.isNull()) - return rect; - - if (mapToGlobal) - rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft())); - return rect; -} - -QAccessibleInterface *QAccessibleTitleBar::childAt(int x, int y) const -{ - for (int i = 0; i < childCount(); ++i) { - QAccessibleInterface *childIface = child(i); - if (childIface->rect().contains(x,y)) { - return childIface; - } - } - return 0; -} - -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; -//} - -QAccessible::Role QAccessibleTitleBar::role() const -{ - return QAccessible::TitleBar; -} - -void QAccessibleTitleBar::setText(QAccessible::Text /*t*/, const QString &/*text*/) -{ -} - -bool QAccessibleTitleBar::isValid() const -{ - return dockWidget(); -} - #endif // QT_NO_DOCKWIDGET #ifndef QT_NO_CURSOR diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.h b/src/plugins/accessible/widgets/qaccessiblewidgets.h index 3e982e82d6..3f50010685 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.h +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.h @@ -283,31 +283,10 @@ public: int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE; int childCount() const Q_DECL_OVERRIDE; QRect rect () const Q_DECL_OVERRIDE; - - QDockWidget *dockWidget() const; -}; - -class QAccessibleTitleBar : public QAccessibleInterface -{ -public: - explicit QAccessibleTitleBar(QDockWidget *widget); - - QAccessibleInterface *parent() const Q_DECL_OVERRIDE; - QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE; - int indexOfChild(const QAccessibleInterface *child) const Q_DECL_OVERRIDE; - int childCount() const Q_DECL_OVERRIDE; - QAccessibleInterface *childAt(int x, int y) const Q_DECL_OVERRIDE; - void setText(QAccessible::Text t, const QString &text) Q_DECL_OVERRIDE; QString text(QAccessible::Text t) const Q_DECL_OVERRIDE; - QAccessible::Role role() const Q_DECL_OVERRIDE; - QRect rect () const Q_DECL_OVERRIDE; - QAccessible::State state() const Q_DECL_OVERRIDE; - QObject *object() const Q_DECL_OVERRIDE; - bool isValid() const Q_DECL_OVERRIDE; - - QPointer<QDockWidget> m_dockWidget; QDockWidget *dockWidget() const; +protected: QDockWidgetLayout *dockWidgetLayout() const; }; diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index a9b21cbc81..8b151e65bd 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -674,12 +674,18 @@ void QDockWidgetPrivate::updateButtons() = qobject_cast<QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton)); button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q)); button->setVisible(canFloat && !hideButtons); - +#ifndef QT_NO_ACCESSIBILITY + button->setAccessibleName(QDockWidget::tr("Float")); + button->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget")); +#endif button = qobject_cast <QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::CloseButton)); button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q)); button->setVisible(canClose && !hideButtons); - +#ifndef QT_NO_ACCESSIBILITY + button->setAccessibleName(QDockWidget::tr("Close")); + button->setAccessibleDescription(QDockWidget::tr("Closes the dock widget")); +#endif q->setAttribute(Qt::WA_ContentsPropagated, (canFloat || canClose) && !hideButtons); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 092995c0aa..c4a0d9c76c 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -3056,60 +3056,127 @@ void tst_QAccessibility::dockWidgetTest() mw->setMenuBar(mb); QDockWidget *dock1 = new QDockWidget(mw); + dock1->setWindowTitle("Dock 1"); mw->addDockWidget(Qt::LeftDockWidgetArea, dock1); QPushButton *pb1 = new QPushButton(tr("Push me"), dock1); dock1->setWidget(pb1); QDockWidget *dock2 = new QDockWidget(mw); + dock2->setWindowTitle("Dock 2"); mw->addDockWidget(Qt::BottomDockWidgetArea, dock2); QPushButton *pb2 = new QPushButton(tr("Push me"), dock2); dock2->setWidget(pb2); + dock2->setFeatures(QDockWidget::DockWidgetClosable); mw->resize(600,400); mw->show(); -#if defined(Q_OS_UNIX) - QCoreApplication::processEvents(); - QTest::qWait(100); -#endif + QTest::qWaitForWindowExposed(mw); QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw); // 4 children: menu bar, dock1, dock2, and central widget QCOMPARE(accMainWindow->childCount(), 4); QAccessibleInterface *accDock1 = 0; + QAccessibleInterface *accDock2 = 0; for (int i = 0; i < 4; ++i) { - accDock1 = accMainWindow->child(i); - if (accMainWindow->role() == QAccessible::Window) { - if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) { - break; - } - } + QAccessibleInterface *child = accMainWindow->child(i); + if (child && child->object() == dock1) + accDock1 = child; + if (child && child->object() == dock2) + accDock2 = child; } + + // Dock widgets consist of + // 0 contents + // 1 close button + // 2 float button QVERIFY(accDock1); QCOMPARE(accDock1->role(), QAccessible::Window); + QCOMPARE(accDock1->text(QAccessible::Name), dock1->windowTitle()); + QCOMPARE(accDock1->childCount(), 3); + + QAccessibleInterface *dock1Widget = accDock1->child(0); + QCOMPARE(dock1Widget->role(), QAccessible::Button); + QCOMPARE(dock1Widget->text(QAccessible::Name), pb1->text()); + +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "Dock Widget geometry on Mac seems broken.", Continue); +#endif + QVERIFY(accDock1->rect().contains(dock1Widget->rect())); + QCOMPARE(accDock1->indexOfChild(dock1Widget), 0); + QCOMPARE(dock1Widget->parent()->object(), dock1); + + QAccessibleInterface *dock1Close = accDock1->child(1); + QCOMPARE(dock1Close->role(), QAccessible::Button); + QCOMPARE(dock1Close->text(QAccessible::Name), QDockWidget::tr("Close")); + QVERIFY(accDock1->rect().contains(dock1Close->rect())); + QCOMPARE(accDock1->indexOfChild(dock1Close), 1); + QCOMPARE(dock1Close->parent()->object(), dock1); + + QAccessibleInterface *dock1Float = accDock1->child(2); + QCOMPARE(dock1Float->role(), QAccessible::Button); + QCOMPARE(dock1Float->text(QAccessible::Name), QDockWidget::tr("Float")); + QVERIFY(accDock1->rect().contains(dock1Float->rect())); + QCOMPARE(accDock1->indexOfChild(dock1Float), 2); + QVERIFY(!dock1Float->state().invisible); + + QVERIFY(accDock2); + QCOMPARE(accDock2->role(), QAccessible::Window); + QCOMPARE(accDock2->text(QAccessible::Name), dock2->windowTitle()); + QCOMPARE(accDock2->childCount(), 3); + + QAccessibleInterface *dock2Widget = accDock2->child(0); + QCOMPARE(dock2Widget->role(), QAccessible::Button); + QCOMPARE(dock2Widget->text(QAccessible::Name), pb1->text()); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "Dock Widget geometry on Mac seems broken.", Continue); +#endif + QVERIFY(accDock2->rect().contains(dock2Widget->rect())); + QCOMPARE(accDock2->indexOfChild(dock2Widget), 0); + + QAccessibleInterface *dock2Close = accDock2->child(1); + QCOMPARE(dock2Close->role(), QAccessible::Button); + QCOMPARE(dock2Close->text(QAccessible::Name), QDockWidget::tr("Close")); + QVERIFY(accDock2->rect().contains(dock2Close->rect())); + QCOMPARE(accDock2->indexOfChild(dock2Close), 1); + QVERIFY(!dock2Close->state().invisible); + + QAccessibleInterface *dock2Float = accDock2->child(2); + QCOMPARE(dock2Float->role(), QAccessible::Button); + QCOMPARE(dock2Float->text(QAccessible::Name), QDockWidget::tr("Float")); + QCOMPARE(accDock2->indexOfChild(dock2Float), 2); + QVERIFY(dock2Float->state().invisible); + + QPoint buttonPoint = pb2->mapToGlobal(QPoint(pb2->width()/2, pb2->height()/2)); + QAccessibleInterface *childAt = accDock2->childAt(buttonPoint.x(), buttonPoint.y()); + QVERIFY(childAt); + QVERIFY(childAt->object() == pb2); + + QWidget *close1 = qobject_cast<QWidget*>(dock1Close->object()); + QPoint close1ButtonPoint = close1->mapToGlobal(QPoint(close1->width()/2, close1->height()/2)); + QAccessibleInterface *childAt2 = accDock1->childAt(close1ButtonPoint.x(), close1ButtonPoint.y()); + QVERIFY(childAt2); + QVERIFY(childAt2->object() == close1); + + // custom title bar widget + QDockWidget *dock3 = new QDockWidget(mw); + dock3->setWindowTitle("Dock 3"); + mw->addDockWidget(Qt::LeftDockWidgetArea, dock3); + QPushButton *pb3 = new QPushButton(tr("Push me"), dock3); + dock3->setWidget(pb3); + QLabel *titleLabel = new QLabel("I am a title widget"); + dock3->setTitleBarWidget(titleLabel); + + QAccessibleInterface *accDock3 = accMainWindow->child(4); + QVERIFY(accDock3); + QCOMPARE(accDock3->role(), QAccessible::Window); + QCOMPARE(accDock3->text(QAccessible::Name), dock3->windowTitle()); + QCOMPARE(accDock3->childCount(), 2); + QAccessibleInterface *titleWidget = accDock3->child(1); + QVERIFY(titleWidget); + QCOMPARE(titleWidget->text(QAccessible::Name), titleLabel->text()); + QAccessibleInterface *dock3Widget = accDock3->child(0); + QCOMPARE(dock3Widget->text(QAccessible::Name), pb3->text()); - QAccessibleInterface *dock1TitleBar = accDock1->child(0); - QCOMPARE(dock1TitleBar->role(), QAccessible::TitleBar); - QVERIFY(accDock1->rect().contains(dock1TitleBar->rect())); - - QPoint globalPos = dock1->mapToGlobal(QPoint(0,0)); - globalPos.rx()+=5; //### query style - globalPos.ry()+=5; - QAccessibleInterface *childAt = accDock1->childAt(globalPos.x(), globalPos.y()); //### - QCOMPARE(childAt->role(), QAccessible::TitleBar); - int index = accDock1->indexOfChild(childAt); - QAccessibleInterface *accTitleBar = accDock1->child(index); - - QCOMPARE(accTitleBar->role(), QAccessible::TitleBar); - QCOMPARE(accDock1->indexOfChild(accTitleBar), 0); - QAccessibleInterface *acc; - acc = accTitleBar->parent(); - QVERIFY(acc); - QCOMPARE(acc->role(), QAccessible::Window); - - delete pb1; - delete pb2; - delete dock1; - delete dock2; delete mw; QTestAccessibility::clearEvents(); #endif // QT_NO_DOCKWIDGET |