keydialog.cpp 7.42 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * Copyright (C) 2003 Stefan Asserhall <stefan.asserhall@telia.com>
 * Copyright (C) 2007, 2008 Michael Pyne <mpyne@kde.org>
 *
 * 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.  If not, see <http://www.gnu.org/licenses/>.
 */
17 18

#include "keydialog.h"
19
#include "actioncollection.h"
20

Michael Pyne's avatar
Michael Pyne committed
21 22 23 24
#include <KConfig>
#include <KShortcutsEditor>
#include <KConfigGroup>
#include <KSharedConfig>
Michael Pyne's avatar
Michael Pyne committed
25
#include <KGlobalAccel>
Michael Pyne's avatar
Michael Pyne committed
26
#include <KLocalizedString>
Laurent Montel's avatar
Laurent Montel committed
27

Michael Pyne's avatar
Michael Pyne committed
28 29 30
#include <QAction>
#include <QKeySequence>
#include <QList>
31
#include <QHBoxLayout>
32
#include <QVBoxLayout>
33
#include <QTimer>
34
#include <QDialogButtonBox>
35 36
#include <QButtonGroup>
#include <QRadioButton>
37
#include <QPushButton>
38
#include <QGroupBox>
39
#include <QString>
40 41

// Table of shortcut keys for each action, key group and three or four button modifier
Scott Wheeler's avatar
Scott Wheeler committed
42

43 44
struct KeyDialog::KeyInfo {
    QString action;
Michael Pyne's avatar
Michael Pyne committed
45
    QKeySequence shortcut[3];
46 47
};

48
const KeyDialog::KeyInfo KeyDialog::keyInfo[] = {
49
    { "playPause",
Michael Pyne's avatar
Michael Pyne committed
50 51 52
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_P),
        QKeySequence(Qt::Key_MediaPlay) } },
53
    { "stop",
Michael Pyne's avatar
Michael Pyne committed
54 55 56
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_S),
        QKeySequence(Qt::Key_MediaStop) } },
57
    { "back",
Michael Pyne's avatar
Michael Pyne committed
58 59 60
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_Left),
        QKeySequence(Qt::Key_MediaPrevious) } },
61
    { "forward",
Michael Pyne's avatar
Michael Pyne committed
62 63 64
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_Right),
        QKeySequence(Qt::Key_MediaNext) } },
65
    { "forwardAlbum",
Michael Pyne's avatar
Michael Pyne committed
66 67 68
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_Up),
        QKeySequence(Qt::CTRL+Qt::Key_MediaNext) } },
69
    { "seekBack",
Michael Pyne's avatar
Michael Pyne committed
70 71 72
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::ALT+Qt::Key_Left),
        QKeySequence(Qt::SHIFT+Qt::Key_MediaPrevious) } },
73
    { "seekForward",
Michael Pyne's avatar
Michael Pyne committed
74 75 76
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::ALT+Qt::Key_Right),
        QKeySequence(Qt::SHIFT+Qt::Key_MediaNext) } },
77
    { "volumeUp",
Michael Pyne's avatar
Michael Pyne committed
78 79 80
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::SHIFT+Qt::Key_Up),
        QKeySequence(Qt::Key_VolumeUp) } },
81
    { "volumeDown",
Michael Pyne's avatar
Michael Pyne committed
82 83 84
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::SHIFT+Qt::Key_Down),
        QKeySequence(Qt::Key_VolumeDown) } },
85
    { "mute",
Michael Pyne's avatar
Michael Pyne committed
86 87 88
      { QKeySequence(),
        QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_M),
        QKeySequence(Qt::Key_VolumeMute) } },
89
    { "showHide",
Michael Pyne's avatar
Michael Pyne committed
90 91 92
      { QKeySequence(),
        QKeySequence(),
        QKeySequence() } }
93 94
};

95
const uint KeyDialog::keyInfoCount = sizeof(KeyDialog::keyInfo) / sizeof(KeyDialog::keyInfo[0]);
96

97
KeyDialog::KeyDialog(KActionCollection *actionCollection, QWidget *parent)
98 99
  : QDialog(parent)
  , m_actionCollection(actionCollection)
100
{
101
    setWindowTitle(i18n("Configure Shortcuts"));
102

103
    // Read key group from configuration
Scott Wheeler's avatar
Scott Wheeler committed
104

105
    KConfigGroup config(KSharedConfig::openConfig(), "Shortcuts");
106
    int selectedButton = config.readEntry("GlobalKeys", int(StandardKeys));
107

108
    // Create widgets for key chooser
Scott Wheeler's avatar
Scott Wheeler committed
109

110
    auto vboxLayout = new QVBoxLayout(this);
111

112 113
    m_pKeyChooser = new KShortcutsEditor(actionCollection, this);
    vboxLayout->addWidget(m_pKeyChooser);
114

115
    // Create buttons to select key group
Scott Wheeler's avatar
Scott Wheeler committed
116

117 118 119
    QGroupBox *buttonBox = new QGroupBox(i18n("Global Shortcuts"), this);
    vboxLayout->addWidget(buttonBox);

120
    m_group = new QButtonGroup(buttonBox);
121
    QHBoxLayout *buttonLayout = new QHBoxLayout(buttonBox);
122 123 124 125

    QRadioButton *radioButton = new QRadioButton(i18n("&No keys"), buttonBox);
    m_group->addButton(radioButton, NoKeys);
    buttonLayout->addWidget(radioButton);
126

127 128 129 130 131 132 133
    radioButton = new QRadioButton(i18n("&Standard keys"), buttonBox);
    m_group->addButton(radioButton, StandardKeys);
    buttonLayout->addWidget(radioButton);

    radioButton = new QRadioButton(i18n("&Multimedia keys"), buttonBox);
    m_group->addButton(radioButton, MultimediaKeys);
    buttonLayout->addWidget(radioButton);
134

135
    connect(m_group, SIGNAL(buttonClicked(int)), SLOT(slotKeys(int)));
136
    buttonBox->setWhatsThis(
137
        i18n("Here you can select the keys used as global shortcuts to control the player"));
138

139
    m_group->button(selectedButton)->setChecked(true);
Scott Wheeler's avatar
Scott Wheeler committed
140

141 142 143 144
    auto dlgButtonBox = new QDialogButtonBox(
            QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults,
            this);
    vboxLayout->addWidget(dlgButtonBox);
145

146 147 148 149 150 151
    connect(dlgButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
    connect(dlgButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
    connect(dlgButtonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked,
            this,                                                    &KeyDialog::slotDefault);

    resize(400, 500); // TODO: Make it bigger!
152 153 154 155 156
}

int KeyDialog::configure()
{
    // Show the dialog and save configuration if accepted
Scott Wheeler's avatar
Scott Wheeler committed
157

158 159
    int retcode = exec();
    if(retcode == Accepted) {
160
        KConfigGroup config(KSharedConfig::openConfig(), "Shortcuts");
161 162

        config.writeEntry("GlobalKeys", m_group->checkedId());
163
        KSharedConfig::openConfig()->sync();
164

165
        m_pKeyChooser->save();
166
    }
167

168 169 170 171 172 173
    return retcode;
}

void KeyDialog::slotKeys(int group)
{
    // Set modifier keys according to key group and modifier keys
Scott Wheeler's avatar
Scott Wheeler committed
174

Michael Pyne's avatar
Michael Pyne committed
175 176
    auto globalAccel = KGlobalAccel::self();

177
    for(uint i = 0; i < keyInfoCount; i++) {
Michael Pyne's avatar
Michael Pyne committed
178
        QAction *a = ActionCollection::action<QAction>(keyInfo[i].action);
179 180

        if(a) {
Michael Pyne's avatar
Michael Pyne committed
181 182 183 184 185 186 187 188
            if (group == 0) {
                globalAccel->removeAllShortcuts(a);
            }
            else {
                QKeySequence shortcut(keyInfo[i].shortcut[group]);
                QList<QKeySequence> shortcutList{shortcut};
                globalAccel->setShortcut(a, shortcutList, KGlobalAccel::NoAutoloading);
            }
189
        }
190
    }
191

192 193 194
    // Update the key chooser widget.
    // TODO: When widget is fixed to note the update remove this bit so that
    // we don't drop user changes for no reason.
Scott Wheeler's avatar
Scott Wheeler committed
195

196 197
    m_pKeyChooser->clearCollections();
    m_pKeyChooser->addCollection(m_actionCollection);
198 199 200 201 202
}

void KeyDialog::slotDefault()
{
    // Select default keys - standard key group
Scott Wheeler's avatar
Scott Wheeler committed
203

204
    m_group->button(StandardKeys)->setChecked(true);
205
    slotKeys(StandardKeys);
206 207 208
    m_pKeyChooser->allDefault();
}

209
void KeyDialog::setupActionShortcut(const QString &actionName)
210 211
{
    // Find and insert a standard key
Michael Pyne's avatar
Michael Pyne committed
212
    QKeySequence shortcut = QKeySequence();
Scott Wheeler's avatar
Scott Wheeler committed
213

214
    // Find out what type is selected so we know what keys to setup.
215
    KConfigGroup config(KSharedConfig::openConfig(), "Shortcuts");
216 217
    int selectedKeys = config.readEntry("GlobalKeys", int(StandardKeys));

Scott Wheeler's avatar
Scott Wheeler committed
218
    for(uint i = 0; i < keyInfoCount; i++) {
219
        if(keyInfo[i].action == actionName) {
220
            shortcut = keyInfo[i].shortcut[selectedKeys];
221 222
            break;
        }
Scott Wheeler's avatar
Scott Wheeler committed
223
    }
224

Laurent Montel's avatar
Laurent Montel committed
225
    if(shortcut.isEmpty())
226 227
        return; // We have no shortcut to set.

Michael Pyne's avatar
Michael Pyne committed
228 229 230 231
    QAction *a = ActionCollection::action<QAction>(actionName);
    if(a) {
        KGlobalAccel::setGlobalShortcut(a, shortcut);
    }
232
}
233

234
// vim: set et sw=4 tw=0 sta: