diff -r 000000000000 -r 1918ee327afb src/plugins/accessible/widgets/qaccessiblemenu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/accessible/widgets/qaccessiblemenu.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaccessiblemenu.h" + +#include +#include +#include +#include + +#ifndef QT_NO_ACCESSIBILITY + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_MENU + +QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); +QString Q_GUI_EXPORT qt_accHotKey(const QString &text); + +QAccessibleMenu::QAccessibleMenu(QWidget *w) +: QAccessibleWidgetEx(w) +{ + Q_ASSERT(menu()); +} + +QMenu *QAccessibleMenu::menu() const +{ + return qobject_cast(object()); +} + +int QAccessibleMenu::childCount() const +{ + return menu()->actions().count(); +} + +QRect QAccessibleMenu::rect(int child) const +{ + if (!child || child > childCount()) + return QAccessibleWidgetEx::rect(child); + + QRect r = menu()->actionGeometry(menu()->actions()[child - 1]); + QPoint tlp = menu()->mapToGlobal(QPoint(0,0)); + + return QRect(tlp.x() + r.x(), tlp.y() + r.y(), r.width(), r.height()); +} + +int QAccessibleMenu::childAt(int x, int y) const +{ + QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y))); + if(act && act->isSeparator()) + act = 0; + return menu()->actions().indexOf(act) + 1; +} + +QString QAccessibleMenu::text(Text t, int child) const +{ + QString tx = QAccessibleWidgetEx::text(t, child); + if (tx.size()) + return tx; + + switch (t) { + case Name: + if (!child) + return menu()->windowTitle(); + return qt_accStripAmp(menu()->actions().at(child-1)->text()); + case Help: + return child ? menu()->actions().at(child-1)->whatsThis() : tx; +#ifndef QT_NO_SHORTCUT + case Accelerator: + return child ? static_cast(menu()->actions().at(child-1)->shortcut()) : tx; +#endif + default: + break; + } + return tx; +} + +QAccessible::Role QAccessibleMenu::role(int child) const +{ + if (!child) + return PopupMenu; + + QAction *action = menu()->actions()[child-1]; + if (action && action->isSeparator()) + return Separator; + return MenuItem; +} + +QAccessible::State QAccessibleMenu::state(int child) const +{ + State s = QAccessibleWidgetEx::state(child); + if (!child) + return s; + + QAction *action = menu()->actions()[child-1]; + if (!action) + return s; + + if (menu()->style()->styleHint(QStyle::SH_Menu_MouseTracking)) + s |= HotTracked; + if (action->isSeparator() || !action->isEnabled()) + s |= Unavailable; + if (action->isChecked()) + s |= Checked; + if (menu()->activeAction() == action) + s |= Focused; + + return s; +} + +QString QAccessibleMenu::actionText(int action, QAccessible::Text text, int child) const +{ + if (action == QAccessible::DefaultAction && child && text == QAccessible::Name) { + QAction *a = menu()->actions().value(child-1, 0); + if (!a || a->isSeparator()) + return QString(); + if (a->menu()) { + if (a->menu()->isVisible()) + return QMenu::tr("Close"); + return QMenu::tr("Open"); + } + return QMenu::tr("Execute"); + } + + return QAccessibleWidgetEx::actionText(action, text, child); +} + +bool QAccessibleMenu::doAction(int act, int child, const QVariantList &) +{ + if (!child || act != QAccessible::DefaultAction) + return false; + + QAction *action = menu()->actions().value(child-1, 0); + if (!action || !action->isEnabled()) + return false; + + if (action->menu() && action->menu()->isVisible()) + action->menu()->hide(); + else + menu()->setActiveAction(action); + return true; +} + +int QAccessibleMenu::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const +{ + int ret = -1; + if (entry < 0) { + *target = 0; + return ret; + } + + if (relation == Self || entry == 0) { + *target = new QAccessibleMenu(menu()); + return 0; + } + + switch (relation) { + case Child: + if (entry <= childCount()) { + *target = new QAccessibleMenuItem(menu(), menu()->actions().at( entry - 1 )); + ret = 0; + } + break; + case Ancestor: { + QAccessibleInterface *iface; + QWidget *parent = menu()->parentWidget(); + if (qobject_cast(parent) || qobject_cast(parent)) { + iface = new QAccessibleMenuItem(parent, menu()->menuAction()); + if (entry == 1) { + *target = iface; + ret = 0; + } else { + ret = iface->navigate(Ancestor, entry - 1, target); + delete iface; + } + } else { + return QAccessibleWidgetEx::navigate(relation, entry, target); + } + break;} + default: + return QAccessibleWidgetEx::navigate(relation, entry, target); + } + + + if (ret == -1) + *target = 0; + + return ret; + +} + +int QAccessibleMenu::indexOfChild( const QAccessibleInterface *child ) const +{ + int index = -1; + Role r = child->role(0); + if ((r == MenuItem || r == Separator) && menu()) { + index = menu()->actions().indexOf(qobject_cast(child->object())); + if (index != -1) + ++index; + } + return index; +} + +#ifndef QT_NO_MENUBAR +QAccessibleMenuBar::QAccessibleMenuBar(QWidget *w) +: QAccessibleWidgetEx(w) +{ + Q_ASSERT(menuBar()); +} + +QMenuBar *QAccessibleMenuBar::menuBar() const +{ + return qobject_cast(object()); +} + +int QAccessibleMenuBar::childCount() const +{ + return menuBar()->actions().count(); +} + +QRect QAccessibleMenuBar::rect(int child) const +{ + if (!child) + return QAccessibleWidgetEx::rect(child); + + QRect r = menuBar()->actionGeometry(menuBar()->actions()[child - 1]); + QPoint tlp = menuBar()->mapToGlobal(QPoint(0,0)); + return QRect(tlp.x() + r.x(), tlp.y() + r.y(), r.width(), r.height()); +} + +int QAccessibleMenuBar::childAt(int x, int y) const +{ + for (int i = childCount(); i >= 0; --i) { + if (rect(i).contains(x,y)) + return i; + } + return -1; +} + +int QAccessibleMenuBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const +{ + int ret = -1; + if (entry < 0) { + *target = 0; + return ret; + } + + if (relation == Self || entry == 0) { + *target = new QAccessibleMenuBar(menuBar()); + return 0; + } + + switch (relation) { + case Child: + if (entry <= childCount()) { + *target = new QAccessibleMenuItem(menuBar(), menuBar()->actions().at( entry - 1 )); + ret = 0; + } + break; + default: + return QAccessibleWidgetEx::navigate(relation, entry, target); + } + + + if (ret == -1) + *target = 0; + + return ret; +} + +int QAccessibleMenuBar::indexOfChild( const QAccessibleInterface *child ) const +{ + int index = -1; + Role r = child->role(0); + if ((r == MenuItem || r == Separator) && menuBar()) { + index = menuBar()->actions().indexOf(qobject_cast(child->object())); + if (index != -1) + ++index; + } + return index; +} + +QString QAccessibleMenuBar::text(Text t, int child) const +{ + QString str; + + if (child) { + if (QAction *action = menuBar()->actions().value(child - 1, 0)) { + switch (t) { + case Name: + return qt_accStripAmp(action->text()); + case Accelerator: + str = qt_accHotKey(action->text()); + break; + default: + break; + } + } + } + if (str.isEmpty()) + str = QAccessibleWidgetEx::text(t, child); + return str; +} + +QAccessible::Role QAccessibleMenuBar::role(int child) const +{ + if (!child) + return MenuBar; + + QAction *action = menuBar()->actions()[child-1]; + if (action && action->isSeparator()) + return Separator; + return MenuItem; +} + +QAccessible::State QAccessibleMenuBar::state(int child) const +{ + State s = QAccessibleWidgetEx::state(child); + if (!child) + return s; + + QAction *action = menuBar()->actions().value(child-1, 0); + if (!action) + return s; + + if (menuBar()->style()->styleHint(QStyle::SH_Menu_MouseTracking)) + s |= HotTracked; + if (action->isSeparator() || !action->isEnabled()) + s |= Unavailable; + if (menuBar()->activeAction() == action) + s |= Focused; + + return s; +} + +QString QAccessibleMenuBar::actionText(int action, QAccessible::Text text, int child) const +{ + if (action == QAccessible::DefaultAction && child && text == QAccessible::Name) { + QAction *a = menuBar()->actions().value(child-1, 0); + if (!a || a->isSeparator()) + return QString(); + if (a->menu()) { + if (a->menu()->isVisible()) + return QMenu::tr("Close"); + return QMenu::tr("Open"); + } + return QMenu::tr("Execute"); + } + + return QAccessibleWidgetEx::actionText(action, text, child); +} + +bool QAccessibleMenuBar::doAction(int act, int child, const QVariantList &) +{ + if (act != !child) + return false; + + QAction *action = menuBar()->actions().value(child-1, 0); + if (!action || !action->isEnabled()) + return false; + if (action->menu() && action->menu()->isVisible()) + action->menu()->hide(); + else + menuBar()->setActiveAction(action); + return true; +} + +#endif // QT_NO_MENUBAR + +QAccessibleMenuItem::QAccessibleMenuItem(QWidget *owner, QAction *action) : m_action(action), m_owner(owner) +{ +} + + +QAccessibleMenuItem::~QAccessibleMenuItem() +{} + +int QAccessibleMenuItem::childAt(int x, int y ) const +{ + for (int i = childCount(); i >= 0; --i) { + if (rect(i).contains(x,y)) + return i; + } + return -1; +} + +int QAccessibleMenuItem::childCount() const +{ + return m_action->menu() ? 1 : 0; +} + +QString QAccessibleMenuItem::actionText(int action, Text text, int child ) const +{ + if (text == Name && child == 0) { + switch (action) { + case Press: + case DefaultAction: + return QMenu::tr("Execute"); + break; + default: + break; + } + } + return QString(); +} + +bool QAccessibleMenuItem::doAction(int action, int child, const QVariantList & /*params = QVariantList()*/ ) +{ + if ((action == Press || action == DefaultAction) && child == 0) { + m_action->trigger(); + return true; + } + return false; +} + +int QAccessibleMenuItem::indexOfChild( const QAccessibleInterface * child ) const +{ + if (child->role(0) == PopupMenu && child->object() == m_action->menu()) + return 1; + + return -1; +} + +bool QAccessibleMenuItem::isValid() const +{ + return m_action ? true : false; +} + +int QAccessibleMenuItem::navigate(RelationFlag relation, int entry, QAccessibleInterface ** target ) const +{ + int ret = -1; + if (entry < 0) { + *target = 0; + return ret; + } + + if (relation == Self || entry == 0) { + *target = new QAccessibleMenuItem(owner(), action()); + return 0; + } + + switch (relation) { + case Child: + if (entry <= childCount()) { + *target = new QAccessibleMenu(action()->menu()); + ret = 0; + } + break; + + case Ancestor:{ + QWidget *parent = owner(); + QAccessibleInterface *ancestor = parent ? QAccessible::queryAccessibleInterface(parent) : 0; + if (ancestor) { + if (entry == 1) { + *target = ancestor; + ret = 0; + } else { + ret = ancestor->navigate(Ancestor, entry - 1, target); + delete ancestor; + } + } + break;} + case Up: + case Down:{ + QAccessibleInterface *parent = 0; + int ent = navigate(Ancestor, 1, &parent); + if (ent == 0) { + int index = parent->indexOfChild(this); + if (index != -1) { + index += (relation == Down ? +1 : -1); + ret = parent->navigate(Child, index, target); + } + } + delete parent; + break;} + case Sibling: { + QAccessibleInterface *parent = 0; + int ent = navigate(Ancestor, 1, &parent); + if (ent == 0) { + ret = parent->navigate(Child, entry, target); + } + delete parent; + break;} + default: + break; + + } + if (ret == -1) + *target = 0; + return ret; +} + +QObject *QAccessibleMenuItem::object() const +{ + return m_action; +} + +QRect QAccessibleMenuItem::rect (int child ) const +{ + QRect rect; + if (child == 0) { + QWidget *own = owner(); +#ifndef QT_NO_MENUBAR + if (QMenuBar *menuBar = qobject_cast(own)) { + rect = menuBar->actionGeometry(m_action); + QPoint globalPos = menuBar->mapToGlobal(QPoint(0,0)); + rect = rect.translated(globalPos); + } else +#endif // QT_NO_MENUBAR + if (QMenu *menu = qobject_cast(own)) { + rect = menu->actionGeometry(m_action); + QPoint globalPos = menu->mapToGlobal(QPoint(0,0)); + rect = rect.translated(globalPos); + } + } else if (child == 1) { + QMenu *menu = m_action->menu(); + if (menu) { + rect = menu->rect(); + QPoint globalPos = menu->mapToGlobal(QPoint(0,0)); + rect = rect.translated(globalPos); + } + } + return rect; +} + +QAccessible::Relation QAccessibleMenuItem::relationTo ( int child, const QAccessibleInterface * other, int otherChild ) const +{ + if (other->object() == owner()) { + return Child; + } + Q_UNUSED(child) + Q_UNUSED(other) + Q_UNUSED(otherChild) + // ### + return Unrelated; +} + +QAccessible::Role QAccessibleMenuItem::role(int /*child*/ ) const +{ + return m_action->isSeparator() ? Separator :MenuItem; +} + +void QAccessibleMenuItem::setText ( Text /*t*/, int /*child*/, const QString & /*text */) +{ + +} + +QAccessible::State QAccessibleMenuItem::state(int child ) const +{ + QAccessible::State s = Unavailable; + + if (child == 0) { + s = Normal; + QWidget *own = owner(); + + if (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false) { + s |= Invisible; + } + + if (QMenu *menu = qobject_cast(own)) { + if (menu->activeAction() == m_action) + s |= Focused; +#ifndef QT_NO_MENUBAR + } else if (QMenuBar *menuBar = qobject_cast(own)) { + if (menuBar->activeAction() == m_action) + s |= Focused; +#endif + } + if (own->style()->styleHint(QStyle::SH_Menu_MouseTracking)) + s |= HotTracked; + if (m_action->isSeparator() || !m_action->isEnabled()) + s |= Unavailable; + if (m_action->isChecked()) + s |= Checked; + } else if (child == 1) { + QMenu *menu = m_action->menu(); + if (menu) { + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(menu); + s = iface->state(0); + delete iface; + } + } + return s; +} + +QString QAccessibleMenuItem::text ( Text t, int child ) const +{ + QString str; + switch (t) { + case Name: + if (child == 0) { + str = m_action->text(); + } else if (child == 1) { + QMenu *m = m_action->menu(); + if (m) + str = m->title(); + } + str = qt_accStripAmp(str); + break; + case Accelerator: + if (child == 0) { +#ifndef QT_NO_SHORTCUT + QKeySequence key = m_action->shortcut(); + if (!key.isEmpty()) { + str = key.toString(); + } else +#endif + { + str = qt_accHotKey(m_action->text()); + } + } + break; + default: + break; + } + return str; +} + +int QAccessibleMenuItem::userActionCount ( int /*child*/ ) const +{ + return 0; +} + + +QAction *QAccessibleMenuItem::action() const +{ + return m_action; +} + +QWidget *QAccessibleMenuItem::owner() const +{ + return m_owner; +} + +#endif // QT_NO_MENU + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY +