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 }