summaryrefslogtreecommitdiffstats
path: root/src/plugins/accessible/widgets/qaccessiblemenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/accessible/widgets/qaccessiblemenu.cpp')
-rw-r--r--src/plugins/accessible/widgets/qaccessiblemenu.cpp678
1 files changed, 678 insertions, 0 deletions
diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/plugins/accessible/widgets/qaccessiblemenu.cpp
new file mode 100644
index 0000000000..6d8a358d5c
--- /dev/null
+++ b/src/plugins/accessible/widgets/qaccessiblemenu.cpp
@@ -0,0 +1,678 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 <qmenu.h>
+#include <qmenubar.h>
+#include <QtGui/QAction>
+#include <qstyle.h>
+
+#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<QMenu*>(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<QString>(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<QMenu*>(parent) || qobject_cast<QMenuBar*>(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<QAction*>(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<QMenuBar*>(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<QAction*>(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<QMenuBar*>(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<QMenu*>(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<QMenu*>(own)) {
+ if (menu->activeAction() == m_action)
+ s |= Focused;
+#ifndef QT_NO_MENUBAR
+ } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(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
+