source: smplayer/trunk/src/shortcutgetter.cpp@ 188

Last change on this file since 188 was 188, checked in by Silvan Scherrer, 8 years ago

SMPlayer: update trunk to version 17.1.0

  • Property svn:eol-style set to LF
File size: 12.7 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2017 Ricardo Villalba <rvm@users.sourceforge.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 Note: The ShortcutGetter class is taken from the source code of Edyuk
19 (http://www.edyuk.org/), from file 3rdparty/qcumber/qshortcutdialog.cpp
20
21 Copyright (C) 2006 FullMetalCoder
22 License: GPL
23
24 I modified it to support multiple shortcuts and some other few changes.
25*/
26
27
28/****************************************************************************
29**
30** Copyright (C) 2006 FullMetalCoder
31**
32** This file is part of the Edyuk project (beta version)
33**
34** This file may be used under the terms of the GNU General Public License
35** version 2 as published by the Free Software Foundation and appearing in the
36** file GPL.txt included in the packaging of this file.
37**
38** Notes : Parts of the project are derivative work of Trolltech's QSA library
39** or Trolltech's Qt4 framework but, unless notified, every single line of code
40** is the work of the Edyuk team or a contributor.
41**
42** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
43** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
44**
45****************************************************************************/
46
47
48#include "shortcutgetter.h"
49#include "images.h"
50
51#include <QLayout>
52#include <QHash>
53#include <QLabel>
54#include <QString>
55#include <QShortcut>
56#include <QLineEdit>
57#include <QKeyEvent>
58#include <QPushButton>
59#include <QDialogButtonBox>
60
61#if 1
62
63static QHash<int, const char*> keyMap;
64
65static void initKeyMap()
66{
67 if ( !keyMap.isEmpty() )
68 return;
69
70 /*
71 I'm a bit unsure about these one...
72 */
73 keyMap[Qt::Key_Escape] = "Escape";
74 keyMap[Qt::Key_Return] = "Return";
75 keyMap[Qt::Key_Enter] = "Enter";
76 keyMap[Qt::Key_Insert] = "Ins";
77 keyMap[Qt::Key_Delete] = "Delete";
78 keyMap[Qt::Key_Home] = "Home";
79 keyMap[Qt::Key_End] = "End";
80 keyMap[Qt::Key_Left] = "Left";
81 keyMap[Qt::Key_Up] = "Up";
82 keyMap[Qt::Key_Right] = "Right";
83 keyMap[Qt::Key_Down] = "Down";
84 keyMap[Qt::Key_PageUp] = "PgUp";
85 keyMap[Qt::Key_PageDown] = "PgDown";
86 keyMap[Qt::Key_CapsLock] = "CapsLock";
87 keyMap[Qt::Key_NumLock] = "NumLock";
88 keyMap[Qt::Key_ScrollLock] = "ScrollLock";
89
90 /*
91 These one are quite sure...
92 */
93 keyMap[Qt::Key_F1] = "F1";
94 keyMap[Qt::Key_F2] = "F2";
95 keyMap[Qt::Key_F3] = "F3";
96 keyMap[Qt::Key_F4] = "F4";
97 keyMap[Qt::Key_F5] = "F5";
98 keyMap[Qt::Key_F6] = "F6";
99 keyMap[Qt::Key_F7] = "F7";
100 keyMap[Qt::Key_F8] = "F8";
101 keyMap[Qt::Key_F9] = "F9";
102 keyMap[Qt::Key_F10] = "F10";
103 keyMap[Qt::Key_F11] = "F11";
104 keyMap[Qt::Key_F12] = "F12";
105 keyMap[Qt::Key_F13] = "F13";
106 keyMap[Qt::Key_F14] = "F14";
107 keyMap[Qt::Key_F15] = "F15";
108 keyMap[Qt::Key_F16] = "F16";
109 keyMap[Qt::Key_F17] = "F17";
110 keyMap[Qt::Key_F18] = "F18";
111 keyMap[Qt::Key_F19] = "F19";
112 keyMap[Qt::Key_F20] = "F20";
113 keyMap[Qt::Key_F21] = "F21";
114 keyMap[Qt::Key_F22] = "F22";
115 keyMap[Qt::Key_F23] = "F23";
116 keyMap[Qt::Key_F24] = "F24";
117 keyMap[Qt::Key_F25] = "F25";
118 keyMap[Qt::Key_F26] = "F26";
119 keyMap[Qt::Key_F27] = "F27";
120 keyMap[Qt::Key_F28] = "F28";
121 keyMap[Qt::Key_F29] = "F29";
122 keyMap[Qt::Key_F30] = "F30";
123 keyMap[Qt::Key_F31] = "F31";
124 keyMap[Qt::Key_F32] = "F32";
125 keyMap[Qt::Key_F33] = "F33";
126 keyMap[Qt::Key_F34] = "F34";
127 keyMap[Qt::Key_F35] = "F35";
128
129 keyMap[Qt::Key_Exclam] = "!";
130 keyMap[Qt::Key_QuoteDbl] = "\"";
131 keyMap[Qt::Key_NumberSign] = "-";
132 keyMap[Qt::Key_Dollar] = "$";
133 keyMap[Qt::Key_Percent] = "%";
134 keyMap[Qt::Key_Ampersand] = "&amp;";
135 keyMap[Qt::Key_Apostrophe] = "\'";
136 keyMap[Qt::Key_ParenLeft] = "(";
137 keyMap[Qt::Key_ParenRight] = ")";
138 keyMap[Qt::Key_Asterisk] = "*";
139 keyMap[Qt::Key_Plus] = "+";
140 keyMap[Qt::Key_Comma] = ",";
141 keyMap[Qt::Key_Minus] = "-";
142 keyMap[Qt::Key_Period] = "Period";
143 keyMap[Qt::Key_Slash] = "/";
144
145 keyMap[Qt::Key_0] = "0";
146 keyMap[Qt::Key_1] = "1";
147 keyMap[Qt::Key_2] = "2";
148 keyMap[Qt::Key_3] = "3";
149 keyMap[Qt::Key_4] = "4";
150 keyMap[Qt::Key_5] = "5";
151 keyMap[Qt::Key_6] = "6";
152 keyMap[Qt::Key_7] = "7";
153 keyMap[Qt::Key_8] = "8";
154 keyMap[Qt::Key_9] = "9";
155
156 keyMap[Qt::Key_Colon] = ":";
157 keyMap[Qt::Key_Semicolon] = ";";
158 keyMap[Qt::Key_Less] = "<";
159 keyMap[Qt::Key_Equal] = "=";
160 keyMap[Qt::Key_Greater] = ">";
161 keyMap[Qt::Key_Question] = "?";
162 keyMap[Qt::Key_At] = "@";
163
164 keyMap[Qt::Key_A] = "A";
165 keyMap[Qt::Key_B] = "B";
166 keyMap[Qt::Key_C] = "C";
167 keyMap[Qt::Key_D] = "D";
168 keyMap[Qt::Key_E] = "E";
169 keyMap[Qt::Key_F] = "F";
170 keyMap[Qt::Key_G] = "G";
171 keyMap[Qt::Key_H] = "H";
172 keyMap[Qt::Key_I] = "I";
173 keyMap[Qt::Key_J] = "J";
174 keyMap[Qt::Key_K] = "K";
175 keyMap[Qt::Key_L] = "L";
176 keyMap[Qt::Key_M] = "M";
177 keyMap[Qt::Key_N] = "N";
178 keyMap[Qt::Key_O] = "O";
179 keyMap[Qt::Key_P] = "P";
180 keyMap[Qt::Key_Q] = "Q";
181 keyMap[Qt::Key_R] = "R";
182 keyMap[Qt::Key_S] = "S";
183 keyMap[Qt::Key_T] = "T";
184 keyMap[Qt::Key_U] = "U";
185 keyMap[Qt::Key_V] = "V";
186 keyMap[Qt::Key_W] = "W";
187 keyMap[Qt::Key_X] = "X";
188 keyMap[Qt::Key_Y] = "Y";
189 keyMap[Qt::Key_Z] = "Z";
190
191 keyMap[Qt::Key_BracketLeft] = "[";
192 keyMap[Qt::Key_Backslash] = "\\";
193 keyMap[Qt::Key_BracketRight] = "]";
194
195 keyMap[Qt::Key_Underscore] = "_";
196 keyMap[Qt::Key_BraceLeft] = "{";
197 keyMap[Qt::Key_Bar] = "|";
198 keyMap[Qt::Key_BraceRight] = "}";
199 keyMap[Qt::Key_AsciiTilde] = "~";
200
201 // Added by rvm:
202 keyMap[Qt::Key_Space] = "Space";
203 keyMap[Qt::Key_Backspace] = "Backspace";
204 keyMap[Qt::Key_MediaPlay] = "Media Play";
205 keyMap[Qt::Key_MediaStop] = "Media Stop";
206 keyMap[Qt::Key_MediaPrevious] = "Media Previous";
207 keyMap[Qt::Key_MediaNext] = "Media Next";
208 keyMap[Qt::Key_MediaRecord] = "Media Record";
209 keyMap[Qt::Key_MediaLast] = "Media Last"; // doesn't work?
210 keyMap[Qt::Key_VolumeUp] = "Volume Up";
211 keyMap[Qt::Key_VolumeDown] = "Volume Down";
212 keyMap[Qt::Key_VolumeMute] = "Volume Mute";
213 keyMap[Qt::Key_Back] = "Back";
214 keyMap[Qt::Key_Forward] = "Forward";
215 keyMap[Qt::Key_Stop] = "Stop";
216}
217
218static QString keyToString(int k)
219{
220 if ( k == Qt::Key_Shift || k == Qt::Key_Control || k == Qt::Key_Meta ||
221 k == Qt::Key_Alt || k == Qt::Key_AltGr )
222 return QString::null;
223
224 initKeyMap();
225
226 return keyMap[k];
227}
228
229#else
230
231static QString keyToString(int k)
232{
233 if ( k == Qt::Key_Shift || k == Qt::Key_Control || k == Qt::Key_Meta ||
234 k == Qt::Key_Alt || k == Qt::Key_AltGr )
235 return QString::null;
236
237 return QKeySequence(k).toString();
238}
239
240#endif
241
242static QStringList modToString(Qt::KeyboardModifiers k)
243{
244 //qDebug("modToString: k: %x", (int) k);
245
246 QStringList l;
247
248 if ( k & Qt::ShiftModifier )
249 l << "Shift";
250 if ( k & Qt::ControlModifier )
251 l << "Ctrl";
252 if ( k & Qt::AltModifier )
253 l << "Alt";
254 if ( k & Qt::MetaModifier )
255 l << "Meta";
256 if ( k & Qt::GroupSwitchModifier )
257 ;
258 if ( k & Qt::KeypadModifier )
259 ;
260
261 return l;
262}
263
264
265ShortcutGetter::ShortcutGetter(QWidget *parent) : QDialog(parent)
266{
267 setWindowTitle(tr("Modify shortcut"));
268
269 QVBoxLayout *vbox = new QVBoxLayout(this);
270 vbox->setMargin(2);
271 vbox->setSpacing(4);
272
273 // List and buttons added by rvm
274 list = new QListWidget(this);
275 connect(list, SIGNAL(currentRowChanged(int)), this, SLOT(rowChanged(int)));
276 vbox->addWidget(list);
277
278 QHBoxLayout *hbox = new QHBoxLayout;
279 addItem = new QPushButton(Images::icon("plus"), "", this);
280 addItem->setToolTip(tr("Add shortcut"));
281 connect(addItem, SIGNAL(clicked()), this, SLOT(addItemClicked()));
282
283 removeItem = new QPushButton(Images::icon("minus"), "", this);
284 removeItem->setToolTip(tr("Remove shortcut"));
285 connect(removeItem, SIGNAL(clicked()), this, SLOT(removeItemClicked()));
286
287 hbox->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding));
288 hbox->addWidget(addItem);
289 hbox->addWidget(removeItem);
290
291 vbox->addLayout(hbox);
292
293 QLabel *l = new QLabel(this);
294 l->setText(tr("Press the key combination you want to assign"));
295 vbox->addWidget(l);
296
297 leKey = new QLineEdit(this);
298 connect(leKey, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &)));
299
300 leKey->installEventFilter(this);
301 vbox->addWidget(leKey);
302
303 // Change by rvm: use a QDialogButtonBox instead of QPushButtons
304 // and add a clear button
305 setCaptureKeyboard(true);
306 QDialogButtonBox * buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok |
307 QDialogButtonBox::Cancel |
308 QDialogButtonBox::Reset );
309 QPushButton * clearbutton = buttonbox->button(QDialogButtonBox::Reset);
310 clearbutton->setText( tr("Clear") );
311
312 QPushButton * captureButton = new QPushButton(tr("Capture"), this);
313 captureButton->setToolTip( tr("Capture keystrokes") );
314 captureButton->setCheckable( captureKeyboard() );
315 captureButton->setChecked( captureKeyboard() );
316 connect(captureButton, SIGNAL(toggled(bool)),
317 this, SLOT(setCaptureKeyboard(bool)));
318
319
320 buttonbox->addButton(captureButton, QDialogButtonBox::ActionRole);
321
322 connect( buttonbox, SIGNAL(accepted()), this, SLOT(accept()) );
323 connect( buttonbox, SIGNAL(rejected()), this, SLOT(reject()) );
324 connect( clearbutton, SIGNAL(clicked()), leKey, SLOT(clear()) );
325 vbox->addWidget(buttonbox);
326}
327
328void ShortcutGetter::setCaptureKeyboard(bool b) {
329 capture = b;
330 leKey->setReadOnly(b);
331 leKey->setFocus();
332}
333
334// Added by rvm
335void ShortcutGetter::rowChanged(int row) {
336 QString s = list->item(row)->text();
337 leKey->setText(s);
338 leKey->setFocus();
339}
340
341// Added by rvm
342void ShortcutGetter::textChanged(const QString & text) {
343 list->item(list->currentRow())->setText(text);
344}
345
346// Added by rvm
347void ShortcutGetter::addItemClicked() {
348 qDebug("ShortcutGetter::addItemClicked");
349 list->addItem("");
350 list->setCurrentRow( list->count()-1 ); // Select last item
351}
352
353// Added by rvm
354void ShortcutGetter::removeItemClicked() {
355 qDebug("ShortcutGetter::removeItemClicked");
356 if (list->count() > 1) {
357 QListWidgetItem * i = list->takeItem( list->currentRow() );
358 if (i) delete i;
359 } else {
360 list->setCurrentRow(0);
361 leKey->setText("");
362 }
363}
364
365QString ShortcutGetter::exec(const QString& s)
366{
367 // Added by rvm
368 QStringList shortcuts = s.split(", ");
369 QString shortcut;
370 foreach(shortcut, shortcuts) {
371 list->addItem(shortcut.trimmed());
372 }
373 list->setCurrentRow(0);
374
375 bStop = false;
376
377 if (QDialog::exec() == QDialog::Accepted) {
378 // Added by rvm
379 QStringList l;
380 for (int n = 0; n < list->count(); n++) {
381 QString shortcut = list->item(n)->text();
382 if (!shortcut.isEmpty()) {
383 //qDebug("ShortcutGetter::exec: shortcut: '%s'", shortcut.toUtf8().constData());
384 l << shortcut;
385 }
386 }
387 QString res = l.join(", ");
388 if (res.isNull()) res = "";
389 return res;
390 }
391
392 return QString();
393}
394
395bool ShortcutGetter::event(QEvent *e)
396{
397 if (!capture) return QDialog::event(e);
398
399 QString key;
400 QStringList mods;
401 QKeyEvent *k = static_cast<QKeyEvent*>(e);
402
403 switch ( e->type() )
404 {
405 case QEvent::KeyPress :
406
407 if ( bStop )
408 {
409 lKeys.clear();
410 bStop = false;
411 }
412
413 key = keyToString(k->key());
414 mods = modToString(k->modifiers());
415
416 //qDebug("event: key.count: %d, mods.count: %d", key.count(), mods.count());
417
418 if ( key.count() || mods.count() )
419 {
420
421 if ( key.count() && !lKeys.contains(key) )
422 lKeys << key;
423
424 foreach ( key, mods )
425 if ( !lKeys.contains(key) )
426 lKeys << key;
427
428 } else {
429 key = k->text();
430
431 if ( !lKeys.contains(key) )
432 lKeys << key;
433 }
434
435 setText();
436 break;
437
438 case QEvent::KeyRelease :
439
440 bStop = true;
441 break;
442
443 /*
444 case QEvent::ShortcutOverride :
445 leKey->setText("Shortcut override");
446 break;
447 */
448
449 default:
450 return QDialog::event(e);
451 break;
452 }
453
454 return true;
455}
456
457bool ShortcutGetter::eventFilter(QObject *o, QEvent *e)
458{
459 if (!capture) return QDialog::eventFilter(o, e);
460
461 if ( e->type() == QEvent::KeyPress ||
462 e->type() ==QEvent::KeyRelease )
463 return event(e);
464 else
465 return QDialog::eventFilter(o, e);
466}
467
468void ShortcutGetter::setText()
469{
470 QStringList seq;
471
472 if ( lKeys.contains("Shift") )
473 seq << "Shift";
474
475 if ( lKeys.contains("Ctrl") )
476 seq << "Ctrl";
477
478 if ( lKeys.contains("Alt") )
479 seq << "Alt";
480
481 if ( lKeys.contains("Meta") )
482 seq << "Meta";
483
484 foreach ( QString s, lKeys ) {
485 //qDebug("setText: s: '%s'", s.toUtf8().data());
486 if ( s != "Shift" && s != "Ctrl"
487 && s != "Alt" && s != "Meta" )
488 seq << s;
489 }
490
491 leKey->setText(seq.join("+"));
492 //leKey->selectAll();
493}
494
495#include "moc_shortcutgetter.cpp"
Note: See TracBrowser for help on using the repository browser.