Files
cantata/support/shortcuthandler.cpp
Craig Drummond 9533f12881 Update (c) year
2015-08-13 21:12:34 +01:00

169 lines
5.6 KiB
C++

/*
* Cantata
*
* Copyright (c) 2011-2015 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "shortcuthandler.h"
#include <QMenu>
#include <QMenuBar>
#include <QEvent>
#include <QKeyEvent>
ShortcutHandler::ShortcutHandler(QObject *parent)
: QObject(parent)
, altDown(false)
{
}
ShortcutHandler::~ShortcutHandler()
{
}
bool ShortcutHandler::hasSeenAlt(const QWidget *widget) const
{
if (widget && !widget->isEnabled()) {
return false;
}
if (qobject_cast<const QMenu *>(widget)) {
return openMenus.count() && openMenus.last()==widget;
} else {
return openMenus.isEmpty() && seenAlt.contains(static_cast<QWidget *>(widget->window()));
}
}
bool ShortcutHandler::showShortcut(const QWidget *widget) const
{
return altDown && hasSeenAlt(widget);
}
void ShortcutHandler::widgetDestroyed(QObject *o)
{
updated.remove(static_cast<QWidget *>(o));
openMenus.removeAll(static_cast<QWidget *>(o));
}
void ShortcutHandler::updateWidget(QWidget *w)
{
if (!updated.contains(w)) {
updated.insert(w);
w->update();
connect(w, SIGNAL(destroyed(QObject *)), this, SLOT(widgetDestroyed(QObject *)));
}
}
bool ShortcutHandler::eventFilter(QObject *o, QEvent *e)
{
if (!o->isWidgetType()) {
return QObject::eventFilter(o, e);
}
QWidget *widget = qobject_cast<QWidget*>(o);
switch(e->type()) {
case QEvent::KeyPress:
if (Qt::Key_Alt==static_cast<QKeyEvent *>(e)->key()) {
altDown = true;
if (qobject_cast<QMenu *>(widget)) {
seenAlt.insert(widget);
updateWidget(widget);
if (widget->parentWidget() && widget->parentWidget()->window()) {
seenAlt.insert(widget->parentWidget()->window());
}
} else {
widget = widget->window();
seenAlt.insert(widget);
QList<QWidget *> l = widget->findChildren<QWidget*>();
for (int pos=0 ; pos < l.size() ; ++pos) {
QWidget *w = l.at(pos);
if (!(w->isWindow() || !w->isVisible())) { // || w->style()->styleHint(QStyle::SH_UnderlineShortcut, 0, w)))
updateWidget(w);
}
}
QList<QMenuBar *> m = widget->findChildren<QMenuBar*>();
for (int i = 0; i < m.size(); ++i) {
updateWidget(m.at(i));
}
}
}
break;
case QEvent::WindowDeactivate:
case QEvent::KeyRelease:
if (QEvent::WindowDeactivate==e->type() || Qt::Key_Alt==static_cast<QKeyEvent*>(e)->key()) {
altDown = false;
QSet<QWidget *>::ConstIterator it(updated.constBegin());
QSet<QWidget *>::ConstIterator end(updated.constEnd());
for (; it!=end; ++it) {
(*it)->update();
}
if (!updated.contains(widget)) {
widget->update();
}
seenAlt.clear();
updated.clear();
}
break;
case QEvent::Show:
if (qobject_cast<QMenu *>(widget)) {
QWidget *prev=openMenus.count() ? openMenus.last() : 0L;
openMenus.append(widget);
if(altDown && prev) {
prev->update();
}
connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(widgetDestroyed(QObject *)));
}
break;
case QEvent::Hide:
if (qobject_cast<QMenu *>(widget)) {
seenAlt.remove(widget);
updated.remove(widget);
openMenus.removeAll(widget);
if (altDown) {
if (openMenus.count()) {
openMenus.last()->update();
} else if(widget->parentWidget() && widget->parentWidget()->window()) {
widget->parentWidget()->window()->update();
}
}
}
break;
case QEvent::Close:
// Reset widget when closing
seenAlt.remove(widget);
updated.remove(widget);
seenAlt.remove(widget->window());
openMenus.removeAll(widget);
if (altDown) {
if(openMenus.count()) {
openMenus.last()->update();
} else if(widget->parentWidget() && widget->parentWidget()->window()) {
widget->parentWidget()->window()->update();
}
}
break;
default:
break;
}
return QObject::eventFilter(o, e);
}