File indexing completed on 2024-04-28 05:47:26

0001 /*****************************************************************************
0002  *   Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 
0023 #include "shortcuthandler.h"
0024 
0025 #include <qtcurve-utils/utils.h>
0026 #include <qtcurve-utils/qtutils.h>
0027 
0028 #include <QWidget>
0029 #include <QMenu>
0030 #include <QMenuBar>
0031 #include <QEvent>
0032 #include <QKeyEvent>
0033 
0034 namespace QtCurve {
0035 
0036 ShortcutHandler::ShortcutHandler(QObject *parent) :
0037     QObject(parent), m_altDown(false)
0038 {
0039 }
0040 
0041 ShortcutHandler::~ShortcutHandler()
0042 {
0043 }
0044 
0045 bool ShortcutHandler::hasSeenAlt(const QWidget *widget) const
0046 {
0047     if(widget && !widget->isEnabled())
0048         return false;
0049 
0050     if(qobject_cast<const QMenu*>(widget))
0051         return m_openMenus.count() && m_openMenus.last()==widget;
0052 //     {
0053 //         const QWidget *w=widget;
0054 //
0055 //         while(w)
0056 //         {
0057 //             if(m_seenAlt.contains((QWidget *)w))
0058 //                 return true;
0059 //             w=w->parentWidget();
0060 //         }
0061 //     }
0062     else
0063         return m_openMenus.isEmpty() && m_seenAlt.contains((QWidget*)(widget->window()));
0064 
0065     return false;
0066 }
0067 
0068 bool ShortcutHandler::showShortcut(const QWidget *widget) const
0069 {
0070     return m_altDown && hasSeenAlt(widget);
0071 }
0072 
0073 void ShortcutHandler::widgetDestroyed(QObject *o)
0074 {
0075     m_updated.remove(static_cast<QWidget *>(o));
0076     m_openMenus.removeAll(static_cast<QWidget *>(o));
0077 }
0078 
0079 void ShortcutHandler::updateWidget(QWidget *w)
0080 {
0081     if (!m_updated.contains(w)) {
0082         m_updated.insert(w);
0083         w->update();
0084         connect(qtcSlot(w, destroyed),
0085                 qtcSlot(this, widgetDestroyed));
0086     }
0087 }
0088 
0089 bool ShortcutHandler::eventFilter(QObject *o, QEvent *e)
0090 {
0091     if (!o->isWidgetType())
0092         return QObject::eventFilter(o, e);
0093 
0094     QWidget *widget = static_cast<QWidget*>(o);
0095     switch(e->type())
0096     {
0097     case QEvent::KeyPress:
0098         if (Qt::Key_Alt==static_cast<QKeyEvent *>(e)->key())
0099         {
0100             m_altDown = true;
0101             if(qobject_cast<QMenu *>(widget))
0102             {
0103                 m_seenAlt.insert(widget);
0104                 updateWidget(widget);
0105                 if(widget->parentWidget() && widget->parentWidget()->window())
0106                     m_seenAlt.insert(widget->parentWidget()->window());
0107             }
0108             else
0109             {
0110                 widget = widget->window();
0111                 m_seenAlt.insert(widget);
0112                 QList<QWidget*> l = widget->findChildren<QWidget*>();
0113                 for (int pos = 0;pos < l.size();++pos) {
0114                     QWidget *w = l.at(pos);
0115                     if (!(w->isWindow() || !w->isVisible())) // || w->style()->styleHint(QStyle::SH_UnderlineShortcut, 0, w)))
0116                         updateWidget(w);
0117                 }
0118 
0119                 QList<QMenuBar*> m = widget->findChildren<QMenuBar*>();
0120                 for (int i = 0;i < m.size();++i) {
0121                     updateWidget(m.at(i));
0122                 }
0123             }
0124         }
0125         break;
0126     case QEvent::WindowDeactivate:
0127     case QEvent::KeyRelease:
0128         if (QEvent::WindowDeactivate == e->type() ||
0129             static_cast<QKeyEvent*>(e)->key() == Qt::Key_Alt) {
0130             m_altDown = false;
0131             for (QWidget *widget: const_(m_updated)) {
0132                 widget->update();
0133             }
0134             if (!m_updated.contains(widget))
0135                 widget->update();
0136             m_seenAlt.clear();
0137             m_updated.clear();
0138         }
0139         break;
0140     case QEvent::Show:
0141         if(qobject_cast<QMenu *>(widget))
0142         {
0143             QWidget *prev=m_openMenus.count() ? m_openMenus.last() : 0L;
0144             m_openMenus.append(widget);
0145             if(m_altDown && prev)
0146                 prev->update();
0147             connect(qtcSlot(widget, destroyed),
0148                     qtcSlot(this, widgetDestroyed));
0149         }
0150         break;
0151     case QEvent::Hide:
0152         if(qobject_cast<QMenu *>(widget))
0153         {
0154             m_seenAlt.remove(widget);
0155             m_updated.remove(widget);
0156             m_openMenus.removeAll(widget);
0157             if(m_altDown)
0158             {
0159                 if(m_openMenus.count())
0160                     m_openMenus.last()->update();
0161                 else if(widget->parentWidget() && widget->parentWidget()->window())
0162                     widget->parentWidget()->window()->update();
0163             }
0164         }
0165         break;
0166     case QEvent::Close:
0167         // Reset widget when closing
0168         m_seenAlt.remove(widget);
0169         m_updated.remove(widget);
0170         m_seenAlt.remove(widget->window());
0171         m_openMenus.removeAll(widget);
0172         if(m_altDown)
0173         {
0174             if(m_openMenus.count())
0175                 m_openMenus.last()->update();
0176             else if(widget->parentWidget() && widget->parentWidget()->window())
0177                 widget->parentWidget()->window()->update();
0178         }
0179         break;
0180     default:
0181         break;
0182     }
0183     return QObject::eventFilter(o, e);
0184 }
0185 
0186 }