1 /* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
2  * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
3 
4 #include "hotkeyedit.hh"
5 #include <QKeyEvent>
6 
7 #ifdef Q_OS_WIN
8 #include <windows.h>
9 #endif
10 
HotKeyEdit(QWidget * parent)11 HotKeyEdit::HotKeyEdit( QWidget * parent ):
12   QLineEdit( parent ),
13   currentModifiers( 0 ), currentKey1( 0 ), currentKey2( 0 ),
14   continuingCombo( false )
15 {
16   renderCurrentValue();
17   installEventFilter( this );
18 }
19 
setHotKey(Config::HotKey const & hk)20 void HotKeyEdit::setHotKey( Config::HotKey const & hk )
21 {
22   currentModifiers = hk.modifiers;
23   currentKey1 = hk.key1;
24   currentKey2 = hk.key2;
25 
26   renderCurrentValue();
27 }
28 
getHotKey() const29 Config::HotKey HotKeyEdit::getHotKey() const
30 {
31   Config::HotKey hk;
32 
33   hk.modifiers = currentModifiers;
34   hk.key1 = currentKey1;
35   hk.key2 = currentKey2;
36 
37   return hk;
38 }
39 
renderCurrentValue()40 void HotKeyEdit::renderCurrentValue()
41 {
42   QString result;
43 
44   if ( currentKey1 )
45   {
46     result = QKeySequence( currentKey1 | currentModifiers ).toString( QKeySequence::NativeText );
47 
48     if ( currentKey2 )
49      result += "+" + QKeySequence( currentKey2 ).toString( QKeySequence::NativeText );
50   }
51 
52   setText( result );
53 }
54 
keyPressEvent(QKeyEvent * event)55 void HotKeyEdit::keyPressEvent( QKeyEvent * event )
56 {
57   int key = event->key();
58   Qt::KeyboardModifiers modifiers = event->modifiers() & ~Qt::KeypadModifier;
59 
60 #ifdef Q_OS_WIN
61   if( objectName() == "mainWindowHotkey" || objectName() == "clipboardHotkey" )
62   {
63     int newkey = VkeyToQTkey( event->nativeVirtualKey() );
64     if( newkey )
65       key = newkey;
66   }
67 #endif
68 
69   switch( key )
70   {
71     case 0:
72     case Qt::Key_unknown:
73     case Qt::Key_Shift:
74     case Qt::Key_Control:
75     case Qt::Key_Meta:
76     case Qt::Key_Alt:
77     case Qt::Key_AltGr:
78       continuingCombo = false;
79       QLineEdit::keyPressEvent( event );
80     break;
81 
82     default:
83     {
84       if ( !modifiers &&
85            ( ( key == Qt::Key_Backspace ) || ( key == Qt::Key_Delete  ) ) )
86       {
87         // Delete current combo
88         currentKey1 = 0;
89         currentKey2 = 0;
90         currentModifiers = 0;
91         continuingCombo = false;
92       }
93       else
94       if ( !continuingCombo )
95       {
96         if ( modifiers || event->text().isEmpty() ) // Don't allow plain letters
97         {
98           currentKey2 = 0;
99           currentKey1 = key;
100           currentModifiers = modifiers;
101           continuingCombo = true;
102         }
103       }
104       else
105       {
106         currentKey2 = key;
107         continuingCombo = false;
108       }
109 
110       renderCurrentValue();
111     }
112     break;
113   }
114 }
115 
keyReleaseEvent(QKeyEvent * event)116 void HotKeyEdit::keyReleaseEvent( QKeyEvent * event )
117 {
118   switch( event->key() )
119   {
120     case 0:
121     case Qt::Key_unknown:
122     case Qt::Key_Shift:
123     case Qt::Key_Control:
124     case Qt::Key_Meta:
125     case Qt::Key_Alt:
126     case Qt::Key_AltGr:
127       continuingCombo = false;
128     break;
129   }
130 
131   QLineEdit::keyReleaseEvent( event );
132 }
133 
eventFilter(QObject *,QEvent * event)134 bool HotKeyEdit::eventFilter( QObject *, QEvent * event )
135 {
136   if( event->type() == QEvent::ShortcutOverride )
137   {
138     event->accept();
139     return true;
140   }
141   return false;
142 }
143 
144 #ifdef Q_OS_WIN
145 
VkeyToQTkey(quint32 vkey)146 int HotKeyEdit::VkeyToQTkey( quint32 vkey )
147 {
148   if ( vkey >= Qt::Key_A && vkey <= Qt::Key_Z)
149     return vkey;
150 
151   switch( vkey )
152   {
153     case VK_NUMPAD0:     return Qt::Key_0;
154     case VK_NUMPAD1:     return Qt::Key_1;
155     case VK_NUMPAD2:     return Qt::Key_2;
156     case VK_NUMPAD3:     return Qt::Key_3;
157     case VK_NUMPAD4:     return Qt::Key_4;
158     case VK_NUMPAD5:     return Qt::Key_5;
159     case VK_NUMPAD6:     return Qt::Key_6;
160     case VK_NUMPAD7:     return Qt::Key_7;
161     case VK_NUMPAD8:     return Qt::Key_8;
162     case VK_NUMPAD9:     return Qt::Key_9;
163     case VK_DIVIDE:      return Qt::Key_Slash;
164     case VK_MULTIPLY:    return Qt::Key_Asterisk;
165     case VK_SUBTRACT:    return Qt::Key_Minus;
166     case VK_ADD:         return Qt::Key_Plus;
167     case VK_DECIMAL:     return Qt::Key_Period;
168     case VK_F1:          return Qt::Key_F1;
169     case VK_F2:          return Qt::Key_F2;
170     case VK_F3:          return Qt::Key_F3;
171     case VK_F4:          return Qt::Key_F4;
172     case VK_F5:          return Qt::Key_F5;
173     case VK_F6:          return Qt::Key_F6;
174     case VK_F7:          return Qt::Key_F7;
175     case VK_F8:          return Qt::Key_F8;
176     case VK_F9:          return Qt::Key_F9;
177     case VK_F10:         return Qt::Key_F10;
178     case VK_F11:         return Qt::Key_F11;
179     case VK_F12:         return Qt::Key_F12;
180     case VK_F13:         return Qt::Key_F13;
181     case VK_F14:         return Qt::Key_F14;
182     case VK_F15:         return Qt::Key_F15;
183     case VK_F16:         return Qt::Key_F16;
184     case VK_F17:         return Qt::Key_F17;
185     case VK_F18:         return Qt::Key_F18;
186     case VK_F19:         return Qt::Key_F19;
187     case VK_F20:         return Qt::Key_F20;
188     case VK_F21:         return Qt::Key_F21;
189     case VK_F22:         return Qt::Key_F22;
190     case VK_F23:         return Qt::Key_F23;
191     case VK_F24:         return Qt::Key_F24;
192     case 0x30:           return Qt::Key_ParenRight;
193     case 0x31:           return Qt::Key_Exclam;
194     case 0x32:           return Qt::Key_At;
195     case 0x33:           return Qt::Key_NumberSign;
196     case 0x34:           return Qt::Key_Dollar;
197     case 0x35:           return Qt::Key_Percent;
198     case 0x36:           return Qt::Key_AsciiCircum;
199     case 0x37:           return Qt::Key_Ampersand;
200     case 0x38:           return Qt::Key_copyright;
201     case 0x39:           return Qt::Key_ParenLeft;
202     case VK_OEM_MINUS:   return Qt::Key_Underscore;
203     case VK_OEM_PLUS:    return Qt::Key_Equal;
204     case VK_OEM_1:       return Qt::Key_Semicolon;
205     case VK_OEM_2:       return Qt::Key_Question;
206     case VK_OEM_3:       return Qt::Key_QuoteLeft;
207     case VK_OEM_4:       return Qt::Key_BracketLeft;
208     case VK_OEM_5:       return Qt::Key_Backslash;
209     case VK_OEM_6:       return Qt::Key_BracketRight;
210     case VK_OEM_7:       return Qt::Key_Apostrophe;
211     case VK_OEM_COMMA:   return Qt::Key_Less;
212     case VK_OEM_PERIOD:  return Qt::Key_Greater;
213 
214     default:;
215   }
216 
217   return 0;
218 }
219 
220 #endif
221