File indexing completed on 2024-06-23 05:20:47
0001 /* 0002 Copyright (C) 2012, 2013 by Glad Deschrijver <glad.deschrijver@gmail.com> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public License as 0006 published by the Free Software Foundation; either version 2 of 0007 the License or (at your option) version 3 or any later version 0008 accepted by the membership of KDE e.V. (or its successor approved 0009 by the membership of KDE e.V.), which shall act as a proxy 0010 defined in Section 14 of version 3 of the license. 0011 0012 This program is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 GNU General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include "ShortcutHandler.h" 0022 0023 #ifndef QT_NO_SHORTCUT 0024 0025 #include <QAction> 0026 #include <QSettings> 0027 0028 #include "ShortcutConfigDialog.h" 0029 #include "ShortcutConfigWidget.h" 0030 #include "Common/SettingsCategoryGuard.h" 0031 #include "UiUtils/IconLoader.h" 0032 0033 namespace Gui 0034 { 0035 0036 ShortcutHandler *ShortcutHandler::self = 0; 0037 0038 ShortcutHandler::ShortcutHandler(QWidget *parent) 0039 : QObject(parent) 0040 , m_settings(0) 0041 , m_shortcutConfigAction(0) 0042 , m_shortcutConfigDialog(0) 0043 , m_shortcutConfigWidget(0) 0044 { 0045 Q_ASSERT_X(!self, "ShortcutHandler", "there should be only one shortcut handler object"); 0046 ShortcutHandler::self = this; 0047 m_exclusivityGroups.append(QStringList() << tr("Main Window")); 0048 } 0049 0050 ShortcutHandler::~ShortcutHandler() 0051 { 0052 if (m_shortcutConfigAction) 0053 delete m_shortcutConfigAction; 0054 if (m_shortcutConfigDialog) 0055 delete m_shortcutConfigDialog; 0056 if (m_shortcutConfigWidget) 0057 delete m_shortcutConfigWidget; 0058 m_actionDescriptions.clear(); 0059 } 0060 0061 void ShortcutHandler::setSettingsObject(QSettings *settings) 0062 { 0063 m_settings = settings; 0064 } 0065 0066 void ShortcutHandler::defineAction(const QString &actionName, const QString &iconName, const QString &text, const QString &defaultShortcut, const QString &parentId) 0067 { 0068 // m_actionDescriptions[actionName] = {iconName, text, defaultShortcut, parentId}; // C++11 only, constructor in ActionDescription is then not needed 0069 m_actionDescriptions[actionName] = ActionDescription(iconName, text, defaultShortcut, parentId); 0070 } 0071 0072 void ShortcutHandler::defineAction(const QString &actionName, const QString &iconName, const QString &text, const QKeySequence::StandardKey &key, const QString &parentId) 0073 { 0074 m_actionDescriptions[actionName] = ActionDescription(iconName, text, QKeySequence(key).toString(QKeySequence::PortableText), parentId); 0075 } 0076 0077 QAction *ShortcutHandler::createAction(const QString &actionName, QWidget *parent) 0078 { 0079 return createAction(actionName, 0, "", parent); 0080 } 0081 0082 QAction *ShortcutHandler::createAction(const QString &actionName, QObject *receiver, const char *member, QWidget *parent) 0083 { 0084 if (!m_actionDescriptions.contains(actionName)) 0085 return 0; 0086 0087 ActionDescription actionDescription = m_actionDescriptions[actionName]; 0088 QAction *action = new QAction(parent); 0089 action->setObjectName(actionName); 0090 if (!actionDescription.iconName.isEmpty()) { 0091 action->setIcon(UiUtils::loadIcon(actionDescription.iconName)); 0092 } 0093 action->setText(actionDescription.text); 0094 action->setShortcut(actionDescription.shortcut); 0095 if (receiver) 0096 connect(action, SIGNAL(triggered()), receiver, member); // new-signal-slot: this is a candidate for an overload to support type-safety 0097 m_actionDescriptions[actionName].action = action; 0098 return action; 0099 } 0100 0101 void ShortcutHandler::addExclusivityGroup(const QStringList &groups) 0102 { 0103 if (groups.contains(tr("Main Window"))) { 0104 m_exclusivityGroups.takeFirst(); 0105 m_exclusivityGroups.prepend(groups); 0106 } else { 0107 m_exclusivityGroups.append(groups); 0108 } 0109 0110 if (m_shortcutConfigDialog) 0111 m_shortcutConfigDialog->setExclusivityGroups(m_exclusivityGroups); 0112 if (m_shortcutConfigWidget) 0113 m_shortcutConfigWidget->setExclusivityGroups(m_exclusivityGroups); 0114 } 0115 0116 QSettings *ShortcutHandler::settingsObject() 0117 { 0118 return m_settings; 0119 } 0120 0121 QAction *ShortcutHandler::action(const QString &actionName) 0122 { 0123 if (!m_actionDescriptions.contains(actionName)) 0124 return 0; 0125 return m_actionDescriptions[actionName].action; 0126 } 0127 0128 /***************************************************************************/ 0129 0130 void ShortcutHandler::changeShortcuts(const QHash<QString, ActionDescription> &actionDescriptions) 0131 { 0132 for (QHash<QString, ActionDescription>::const_iterator it = actionDescriptions.constBegin(); it != actionDescriptions.constEnd(); ++it) { 0133 ActionDescription actionDescription = it.value(); 0134 QAction *action = m_actionDescriptions[it.key()].action; 0135 if (action) 0136 action->setShortcut(QKeySequence(actionDescription.shortcut)); 0137 } 0138 } 0139 0140 QAction *ShortcutHandler::shortcutConfigAction() 0141 { 0142 Q_ASSERT_X(!m_shortcutConfigWidget, "ShortcutHandler", "a shortcut configuration dialog and a shortcut configuration widget cannot exist at the same time in one application"); 0143 if (!m_shortcutConfigAction) { 0144 m_shortcutConfigAction = new QAction(UiUtils::loadIcon(QStringLiteral("configure-shortcuts")), tr("Configure S&hortcuts..."), qobject_cast<QWidget*>(parent())); 0145 connect(m_shortcutConfigAction.data(), &QAction::triggered, this, &ShortcutHandler::openShortcutConfigDialog); 0146 } 0147 return m_shortcutConfigAction; 0148 } 0149 0150 void ShortcutHandler::openShortcutConfigDialog() 0151 { 0152 if (!m_shortcutConfigDialog) { 0153 m_shortcutConfigDialog = new ShortcutConfigDialog(qobject_cast<QWidget*>(parent())); 0154 m_shortcutConfigDialog->setActionDescriptions(m_actionDescriptions); 0155 m_shortcutConfigDialog->setExclusivityGroups(m_exclusivityGroups); 0156 connect(m_shortcutConfigDialog.data(), &ShortcutConfigDialog::shortcutsChanged, this, &ShortcutHandler::changeShortcuts); 0157 } 0158 m_shortcutConfigDialog->exec(); 0159 } 0160 0161 /***************************************************************************/ 0162 0163 ShortcutConfigWidget *ShortcutHandler::configWidget() 0164 { 0165 Q_ASSERT_X(!m_shortcutConfigAction, "ShortcutHandler", "a shortcut configuration dialog and a shortcut configuration widget cannot exist at the same time in one application"); 0166 if (!m_shortcutConfigWidget) { 0167 m_shortcutConfigWidget = new ShortcutConfigWidget(qobject_cast<QWidget*>(parent())); 0168 m_shortcutConfigWidget->setActionDescriptions(m_actionDescriptions); 0169 m_shortcutConfigWidget->setExclusivityGroups(m_exclusivityGroups); 0170 connect(m_shortcutConfigWidget.data(), &ShortcutConfigWidget::shortcutsChanged, this, &ShortcutHandler::changeShortcuts); 0171 } 0172 return m_shortcutConfigWidget; 0173 } 0174 0175 void ShortcutHandler::accept() 0176 { 0177 m_shortcutConfigWidget->accept(); 0178 } 0179 0180 void ShortcutHandler::reject() 0181 { 0182 m_shortcutConfigWidget->reject(); 0183 } 0184 0185 /***************************************************************************/ 0186 0187 void ShortcutHandler::readSettings() 0188 { 0189 Q_ASSERT_X(m_settings, "ShortcutHandler", "a settings object should be set using setSettingsObject() prior to using readSettings()"); 0190 Common::SettingsCategoryGuard guard(m_settings, QStringLiteral("ShortcutHandler")); 0191 const int size = m_settings->beginReadArray(QStringLiteral("Shortcuts")); 0192 for (int i = 0; i < size; ++i) { 0193 m_settings->setArrayIndex(i); 0194 const QString actionName = m_settings->value(QStringLiteral("Action")).toString(); 0195 m_actionDescriptions[actionName].shortcut = m_settings->value(QStringLiteral("Shortcut")).toString(); 0196 0197 QAction *action = m_actionDescriptions[actionName].action; 0198 if (action) 0199 action->setShortcut(QKeySequence(m_settings->value(QStringLiteral("Shortcut")).toString())); 0200 } 0201 m_settings->endArray(); 0202 } 0203 0204 } // namespace Gui 0205 0206 #endif // QT_NO_SHORTCUT