/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** 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 The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qaccessiblemenu_p.h" #if QT_CONFIG(menu) #include #endif #if QT_CONFIG(menubar) #include #endif #include #include #include #ifndef QT_NO_ACCESSIBILITY QT_BEGIN_NAMESPACE #if QT_CONFIG(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 = nullptr; return act ? getOrCreateMenu(menu(), act) : nullptr; } 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 nullptr; } QAccessibleInterface *QAccessibleMenu::parent() const { if (QAction *menuAction = menu()->menuAction()) { const QList parentCandidates = QList() << menu()->parentWidget() << menuAction->associatedWidgets(); for (QWidget *w : parentCandidates) { if (qobject_cast(w) #if QT_CONFIG(menubar) || qobject_cast(w) #endif ) { 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; } #if QT_CONFIG(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 nullptr; } 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_CONFIG(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 nullptr; } 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; } 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 nullptr; } void *QAccessibleMenuItem::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::ActionInterface) return static_cast(this); return nullptr; } QObject *QAccessibleMenuItem::object() const { return m_action; } /*! \reimp */ QWindow *QAccessibleMenuItem::window() const { return m_owner.isNull() ? nullptr : qt_widget_private(m_owner.data())->windowHandle(QWidgetPrivate::WindowHandleMode::Closest); } QRect QAccessibleMenuItem::rect() const { QRect rect; QWidget *own = owner(); #if QT_CONFIG(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_CONFIG(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; #if QT_CONFIG(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; if (m_action->isCheckable()) s.checkable = true; return s; } QString QAccessibleMenuItem::text(QAccessible::Text t) const { QString str; switch (t) { case QAccessible::Name: str = qt_accStripAmp(m_action->text()); 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 QT_CONFIG(menubar) if (QMenuBar *bar = qobject_cast(owner())) { if (m_action->menu() && m_action->menu()->isVisible()) { m_action->menu()->hide(); } else { bar->setActiveAction(m_action); } } else #endif 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_CONFIG(menu) QT_END_NAMESPACE #endif // QT_NO_ACCESSIBILITY