From eaee2bd0d048367f6bd331fdb4a177004848d77e Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 5 Feb 2014 11:44:42 +0100 Subject: Accessibility: Use factory function instead of plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies deployment and makes instantiating accessible interfaces faster since no plugin needs to be loaded. [ChangeLog][QtWidgets] Accessibility for widgets is now included in the widget library instead of being a separate plugin. For static builds this means that libqtaccessiblewidgets is no longer required. Task-number: QTBUG-32888 Change-Id: Ie7347898868fd67c1fc568f0d251cbd2ef71e041 Reviewed-by: Jan Arve Sæther --- src/widgets/accessible/qaccessiblemenu.cpp | 377 +++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 src/widgets/accessible/qaccessiblemenu.cpp (limited to 'src/widgets/accessible/qaccessiblemenu.cpp') diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp new file mode 100644 index 0000000000..a6877404eb --- /dev/null +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaccessiblemenu.h" + +#include +#include +#include +#include + +#ifndef QT_NO_ACCESSIBILITY + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_MENU + +QString qt_accStripAmp(const QString &text); +QString qt_accHotKey(const QString &text); + +QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action) +{ + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(action); + if (!iface) { + iface = new QAccessibleMenuItem(menu, action); + QAccessible::registerAccessibleInterface(iface); + } + return iface; +} + +QAccessibleMenu::QAccessibleMenu(QWidget *w) +: QAccessibleWidget(w) +{ + Q_ASSERT(menu()); +} + +QMenu *QAccessibleMenu::menu() const +{ + return qobject_cast(object()); +} + +int QAccessibleMenu::childCount() const +{ + return menu()->actions().count(); +} + +QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const +{ + QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y))); + if(act && act->isSeparator()) + act = 0; + return act ? getOrCreateMenu(menu(), act) : 0; +} + +QString QAccessibleMenu::text(QAccessible::Text t) const +{ + QString tx = QAccessibleWidget::text(t); + if (!tx.isEmpty()) + return tx; + + if (t == QAccessible::Name) + return menu()->windowTitle(); + return tx; +} + +QAccessible::Role QAccessibleMenu::role() const +{ + return QAccessible::PopupMenu; +} + +QAccessibleInterface *QAccessibleMenu::child(int index) const +{ + if (index < childCount()) + return getOrCreateMenu(menu(), menu()->actions().at(index)); + return 0; +} + +QAccessibleInterface *QAccessibleMenu::parent() const +{ + if (QAction *menuAction = menu()->menuAction()) { + QList parentCandidates; + parentCandidates << menu()->parentWidget(); + parentCandidates << menuAction->associatedWidgets(); + foreach (QWidget *w, parentCandidates) { + if (qobject_cast(w) || qobject_cast(w)) { + if (w->actions().indexOf(menuAction) != -1) + return getOrCreateMenu(w, menuAction); + } + } + } + return QAccessibleWidget::parent(); +} + +int QAccessibleMenu::indexOfChild( const QAccessibleInterface *child) const +{ + QAccessible::Role r = child->role(); + if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menu()) { + return menu()->actions().indexOf(qobject_cast(child->object())); + } + return -1; +} + +#ifndef QT_NO_MENUBAR +QAccessibleMenuBar::QAccessibleMenuBar(QWidget *w) + : QAccessibleWidget(w, QAccessible::MenuBar) +{ + Q_ASSERT(menuBar()); +} + +QMenuBar *QAccessibleMenuBar::menuBar() const +{ + return qobject_cast(object()); +} + +int QAccessibleMenuBar::childCount() const +{ + return menuBar()->actions().count(); +} + +QAccessibleInterface *QAccessibleMenuBar::child(int index) const +{ + if (index < childCount()) { + return getOrCreateMenu(menuBar(), menuBar()->actions().at(index)); + } + return 0; +} + +int QAccessibleMenuBar::indexOfChild(const QAccessibleInterface *child) const +{ + QAccessible::Role r = child->role(); + if ((r == QAccessible::MenuItem || r == QAccessible::Separator) && menuBar()) { + return menuBar()->actions().indexOf(qobject_cast(child->object())); + } + return -1; +} + +#endif // QT_NO_MENUBAR + +QAccessibleMenuItem::QAccessibleMenuItem(QWidget *owner, QAction *action) +: m_action(action), m_owner(owner) +{ +} + +QAccessibleMenuItem::~QAccessibleMenuItem() +{} + +QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const +{ + for (int i = childCount() - 1; i >= 0; --i) { + QAccessibleInterface *childInterface = child(i); + if (childInterface->rect().contains(x,y)) { + return childInterface; + } + } + return 0; +} + +int QAccessibleMenuItem::childCount() const +{ + return m_action->menu() ? 1 : 0; +} + +int QAccessibleMenuItem::indexOfChild(const QAccessibleInterface * child) const +{ + if (child && child->role() == QAccessible::PopupMenu && child->object() == m_action->menu()) + return 0; + return -1; +} + +bool QAccessibleMenuItem::isValid() const +{ + return m_action && m_owner ? true : false; +} + +QAccessibleInterface *QAccessibleMenuItem::parent() const +{ + return QAccessible::queryAccessibleInterface(owner()); +} + +QAccessibleInterface *QAccessibleMenuItem::child(int index) const +{ + if (index == 0 && action()->menu()) + return QAccessible::queryAccessibleInterface(action()->menu()); + return 0; +} + +void *QAccessibleMenuItem::interface_cast(QAccessible::InterfaceType t) +{ + if (t == QAccessible::ActionInterface) + return static_cast(this); + return 0; +} + +QObject *QAccessibleMenuItem::object() const +{ + return m_action; +} + +QRect QAccessibleMenuItem::rect() const +{ + QRect rect; + 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); + } + return rect; +} + +QAccessible::Role QAccessibleMenuItem::role() const +{ + return m_action->isSeparator() ? QAccessible::Separator : QAccessible::MenuItem; +} + +void QAccessibleMenuItem::setText(QAccessible::Text /*t*/, const QString & /*text */) +{ +} + +QAccessible::State QAccessibleMenuItem::state() const +{ + QAccessible::State s; + QWidget *own = owner(); + + if (own && (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false)) { + s.invisible = true; + } + + if (QMenu *menu = qobject_cast(own)) { + if (menu->activeAction() == m_action) + s.focused = true; +#ifndef QT_NO_MENUBAR + } else if (QMenuBar *menuBar = qobject_cast(own)) { + if (menuBar->activeAction() == m_action) + s.focused = true; +#endif + } + if (own && own->style()->styleHint(QStyle::SH_Menu_MouseTracking)) + s.hotTracked = true; + if (m_action->isSeparator() || !m_action->isEnabled()) + s.disabled = true; + if (m_action->isChecked()) + s.checked = true; + + return s; +} + +QString QAccessibleMenuItem::text(QAccessible::Text t) const +{ + QString str; + switch (t) { + case QAccessible::Name: + str = m_action->text(); + str = qt_accStripAmp(str); + break; + case QAccessible::Accelerator: { +#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; +} + +QStringList QAccessibleMenuItem::actionNames() const +{ + QStringList actions; + if (!m_action || m_action->isSeparator()) + return actions; + + if (m_action->menu()) { + actions << showMenuAction(); + } else { + actions << pressAction(); + } + return actions; +} + +void QAccessibleMenuItem::doAction(const QString &actionName) +{ + if (!m_action->isEnabled()) + return; + + if (actionName == pressAction()) { + m_action->trigger(); + } else if (actionName == showMenuAction()) { + if (QMenuBar *bar = qobject_cast(owner())) { + if (m_action->menu() && m_action->menu()->isVisible()) { + m_action->menu()->hide(); + } else { + bar->setActiveAction(m_action); + } + } else if (QMenu *menu = qobject_cast(owner())){ + if (m_action->menu() && m_action->menu()->isVisible()) { + m_action->menu()->hide(); + } else { + menu->setActiveAction(m_action); + } + } + } +} + +QStringList QAccessibleMenuItem::keyBindingsForAction(const QString &) const +{ + return QStringList(); +} + + +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 + -- cgit v1.2.3