|
1 /*! |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Dialpad keypad |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <QtGui> |
|
19 #include <hbinstance.h> |
|
20 #include <hbinputkeymapfactory.h> |
|
21 #include <hbinputkeymap.h> |
|
22 #include <hbinpututils.h> |
|
23 #include <hbinputsettingproxy.h> |
|
24 #include <hbinputlanguage.h> |
|
25 #include <hbapplication.h> |
|
26 #include <hblineedit.h> |
|
27 |
|
28 #include "dialpadkeypad.h" |
|
29 #include "dialpadbuttonstyle.h" |
|
30 #include "dialpadbutton.h" |
|
31 #include "dialpadinputfield.h" |
|
32 |
|
33 static const int DialpadRowCount = 5; |
|
34 static const int DialpadColumnCount = 3; |
|
35 |
|
36 static const int DialpadButtonToKeyCodeTable[DialpadButtonCount] = |
|
37 { |
|
38 Qt::Key_1, Qt::Key_2, Qt::Key_3, |
|
39 Qt::Key_4, Qt::Key_5, Qt::Key_6, |
|
40 Qt::Key_7, Qt::Key_8, Qt::Key_9, |
|
41 Qt::Key_Asterisk, Qt::Key_0, Qt::Key_NumberSign, |
|
42 Qt::Key_Yes |
|
43 // Qt::Key_BackSpace is in input field |
|
44 }; |
|
45 |
|
46 DialpadKeypad::DialpadKeypad( |
|
47 DialpadInputField& inputField, |
|
48 QGraphicsItem* parent) : |
|
49 HbWidget(parent), mInputField(inputField), |
|
50 mLongPressDuration(0) |
|
51 { |
|
52 // create signal mappers |
|
53 mKeyPressedSignalMapper = new QSignalMapper(this); |
|
54 connect(mKeyPressedSignalMapper,SIGNAL(mapped(int)), |
|
55 SLOT(handleKeyPressed(int))); |
|
56 mKeyClickedSignalMapper = new QSignalMapper(this); |
|
57 connect(mKeyClickedSignalMapper,SIGNAL(mapped(int)), |
|
58 SLOT(handleKeyClicked(int))); |
|
59 mKeyReleasedSignalMapper = new QSignalMapper(this); |
|
60 connect(mKeyReleasedSignalMapper,SIGNAL(mapped(int)), |
|
61 SLOT(handleKeyReleased(int))); |
|
62 |
|
63 connect(&mInputField.backspaceButton(),SIGNAL(clicked()), |
|
64 mKeyClickedSignalMapper,SLOT(map())); |
|
65 mKeyClickedSignalMapper->setMapping(&mInputField.backspaceButton(), |
|
66 Qt::Key_Backspace); |
|
67 |
|
68 // create keypad |
|
69 mNormalButtonStyle = new DialpadButtonStyle(); |
|
70 mCallButtonStyle = new DialpadButtonStyle(); |
|
71 mCallButtonStyle->setButtonStyle(DialpadButtonStyle::CallButtonStyle); |
|
72 |
|
73 for (int i = 0; i < DialpadButtonCount; i++) { |
|
74 int keyCode = DialpadButtonToKeyCodeTable[i]; |
|
75 |
|
76 DialpadButton* button = new DialpadButton(this); |
|
77 mButtons[i] = button; |
|
78 |
|
79 button->setStretched(true); |
|
80 button->setFocusPolicy(Qt::NoFocus); |
|
81 button->setFlag(QGraphicsItem::ItemIsFocusable,false); |
|
82 |
|
83 QString buttonName; |
|
84 buttonName.setNum(keyCode); |
|
85 button->setObjectName(buttonName); |
|
86 |
|
87 if (keyCode==Qt::Key_Yes) { |
|
88 button->setStyle(mCallButtonStyle); |
|
89 HbIcon callIcon(":/qtg_mono_answer_call.svg"); // todo correct icon |
|
90 button->setIcon(callIcon); |
|
91 } else { |
|
92 button->setStyle(mNormalButtonStyle); |
|
93 } |
|
94 |
|
95 if (keyCode==Qt::Key_1) { |
|
96 HbIcon mboxIcon(":/qtg_mono_voice_mailbox.svg"); |
|
97 button->setIcon(mboxIcon); |
|
98 } |
|
99 |
|
100 // for Yes-key clicked() signal is enough |
|
101 if (keyCode!=Qt::Key_Yes) { |
|
102 connect(button,SIGNAL(pressed()), |
|
103 mKeyPressedSignalMapper,SLOT(map())); |
|
104 mKeyPressedSignalMapper->setMapping(button,keyCode); |
|
105 |
|
106 connect(button,SIGNAL(released()), |
|
107 mKeyReleasedSignalMapper,SLOT(map())); |
|
108 mKeyReleasedSignalMapper->setMapping(button,keyCode); |
|
109 } |
|
110 |
|
111 connect(button,SIGNAL(clicked()),mKeyClickedSignalMapper,SLOT(map())); |
|
112 mKeyClickedSignalMapper->setMapping(button,keyCode); |
|
113 } |
|
114 |
|
115 // set button texts |
|
116 setButtonTexts(); |
|
117 // update button texts when input language is changed |
|
118 connect(HbInputSettingProxy::instance(), |
|
119 SIGNAL(globalInputLanguageChanged(HbInputLanguage)), |
|
120 this,SLOT(setButtonTexts())); |
|
121 |
|
122 createButtonGrid(); |
|
123 |
|
124 // timer to handle long press |
|
125 mLongPressTimer = new QTimer(this); |
|
126 mLongPressTimer->setSingleShot(true); |
|
127 connect(mLongPressTimer,SIGNAL(timeout()),SLOT(handleLongPress())); |
|
128 } |
|
129 |
|
130 DialpadKeypad::~DialpadKeypad() |
|
131 { |
|
132 delete mCallButtonStyle; |
|
133 delete mNormalButtonStyle; |
|
134 } |
|
135 |
|
136 void DialpadKeypad::createButtonGrid() |
|
137 { |
|
138 // button grid |
|
139 mGridLayout = new QGraphicsGridLayout; |
|
140 |
|
141 // 12 numeric buttons |
|
142 int i=0; |
|
143 for (int row = 0; row < DialpadRowCount-1; row++) { |
|
144 for (int col = 0; col < DialpadColumnCount; col++) { |
|
145 mGridLayout->addItem(mButtons[i],row,col); |
|
146 i++; |
|
147 } |
|
148 } |
|
149 |
|
150 // call button take the last row |
|
151 mGridLayout->addItem(mButtons[12],4,0,1,3); |
|
152 mGridLayout->setSpacing(0); |
|
153 mGridLayout->setContentsMargins(0,0,0,0); |
|
154 |
|
155 setLayout(mGridLayout); |
|
156 } |
|
157 |
|
158 void DialpadKeypad::setButtonTexts() |
|
159 { |
|
160 HbInputLanguage inputLanguage = |
|
161 HbInputSettingProxy::instance()->globalInputLanguage(); |
|
162 const HbKeymap *keymap = |
|
163 HbKeymapFactory::instance()->keymap(inputLanguage.language()); |
|
164 |
|
165 mGeneratedChar.clear(); |
|
166 |
|
167 if (keymap) { |
|
168 for (int i = 0; i < DialpadButtonCount-1; i++) { |
|
169 int keyCode = DialpadButtonToKeyCodeTable[i]; |
|
170 |
|
171 if (keyCode == Qt::Key_Asterisk) { |
|
172 // asterisk is not localized |
|
173 QChar asterisk('*'); |
|
174 mButtons[i]->setText(asterisk); |
|
175 mButtons[i]->setAdditionalText("+"); |
|
176 mGeneratedChar.insert(Qt::Key_Asterisk, asterisk); |
|
177 continue; |
|
178 } |
|
179 |
|
180 if (keyCode == Qt::Key_NumberSign) { |
|
181 // number sign is not localized |
|
182 QChar numberSign('#'); |
|
183 mButtons[i]->setText(numberSign); |
|
184 mButtons[i]->setAdditionalText(" "); |
|
185 mGeneratedChar.insert(Qt::Key_NumberSign, numberSign); |
|
186 continue; |
|
187 } |
|
188 |
|
189 int index = i; |
|
190 if (keyCode==Qt::Key_0) { |
|
191 index = i-1; |
|
192 } |
|
193 |
|
194 const HbMappedKey *key = |
|
195 keymap->keyForIndex(HbKeyboardVirtual12Key, index); |
|
196 |
|
197 if (key) { |
|
198 QChar numberChar = |
|
199 HbInputUtils::findFirstNumberCharacterBoundToKey( |
|
200 key, |
|
201 inputLanguage.language()); |
|
202 |
|
203 // button text |
|
204 mButtons[i]->setText(numberChar); |
|
205 mGeneratedChar.insert(keyCode,numberChar); |
|
206 |
|
207 // additional text (letters) |
|
208 int numberOfCharacters; |
|
209 if (keyCode==Qt::Key_7 || keyCode == Qt::Key_9) { |
|
210 numberOfCharacters = 4; |
|
211 } else if (keyCode==Qt::Key_0||keyCode==Qt::Key_1) { |
|
212 numberOfCharacters = 0; |
|
213 } else { |
|
214 numberOfCharacters = 3; |
|
215 } |
|
216 |
|
217 QString characters = key->characters(HbModifierNone); |
|
218 |
|
219 if (numberOfCharacters==0 && keyCode!=Qt::Key_1) { |
|
220 mButtons[i]->setAdditionalText(" "); |
|
221 } else { |
|
222 mButtons[i]->setAdditionalText( |
|
223 characters.left(numberOfCharacters)); |
|
224 } |
|
225 } |
|
226 } |
|
227 } |
|
228 } |
|
229 |
|
230 void DialpadKeypad::handleKeyPressed(int key) |
|
231 { |
|
232 // Editor is updated on key release (clicked()) or on long press, |
|
233 // to prevent editor being updated during swipe. |
|
234 mPressedNumericKey = key; |
|
235 mLongPressTimer->start(mLongPressDuration); |
|
236 |
|
237 postKeyEvent(QEvent::KeyPress, key); |
|
238 } |
|
239 |
|
240 void DialpadKeypad::handleKeyClicked(int key) |
|
241 { |
|
242 if (!isNumericKey(key)) { |
|
243 postKeyEvent(QEvent::KeyPress, key); |
|
244 postKeyEvent(QEvent::KeyRelease, key); |
|
245 } else if (mPressedNumericKey) { |
|
246 // update editor: generate key press event. |
|
247 sendKeyEventToEditor(QEvent::KeyPress, key); |
|
248 } |
|
249 } |
|
250 |
|
251 void DialpadKeypad::handleKeyReleased(int key) |
|
252 { |
|
253 mLongPressTimer->stop(); |
|
254 |
|
255 postKeyEvent(QEvent::KeyRelease, key); |
|
256 } |
|
257 |
|
258 void DialpadKeypad::postKeyEvent(QEvent::Type type, int key) |
|
259 { |
|
260 QKeyEvent *keyEvent = new QKeyEvent(type, key, Qt::NoModifier); |
|
261 HbApplication::postEvent(hbInstance->allMainWindows().at(0),keyEvent); |
|
262 } |
|
263 |
|
264 void DialpadKeypad::sendKeyEventToEditor(QEvent::Type type, int key) |
|
265 { |
|
266 QKeyEvent keyEvent(type, key, Qt::NoModifier, mGeneratedChar.value(key)); |
|
267 HbApplication::sendEvent(&mInputField.editor(), &keyEvent); |
|
268 } |
|
269 |
|
270 void DialpadKeypad::handleLongPress() |
|
271 { |
|
272 // key press |
|
273 sendKeyEventToEditor(QEvent::KeyPress, mPressedNumericKey); |
|
274 mPressedNumericKey = 0; |
|
275 } |
|
276 |
|
277 bool DialpadKeypad::isNumericKey(int key) |
|
278 { |
|
279 if (key==Qt::Key_Yes || key==Qt::Key_Backspace) { |
|
280 return false; |
|
281 } else { |
|
282 return true; |
|
283 } |
|
284 } |
|
285 |
|
286 void DialpadKeypad::setLongPressDuration(int duration) |
|
287 { |
|
288 mLongPressDuration = duration; |
|
289 } |
|
290 |
|
291 void DialpadKeypad::setCallButtonEnabled(bool enabled) |
|
292 { |
|
293 mButtons[DialpadButtonCount-1]->setEnabled(enabled); |
|
294 } |
|
295 |
|
296 void DialpadKeypad::showEvent(QShowEvent *event) |
|
297 { |
|
298 HbWidget::showEvent(event); |
|
299 |
|
300 // set fixed row and column dimensions |
|
301 QSizeF effectiveSize(rect().width(), |
|
302 rect().height()); |
|
303 |
|
304 qreal width = effectiveSize.width() / DialpadColumnCount; |
|
305 qreal height = effectiveSize.height() / DialpadRowCount; |
|
306 |
|
307 for (int i=0; i < DialpadColumnCount ;i++) { |
|
308 mGridLayout->setColumnFixedWidth(i, width); |
|
309 } |
|
310 |
|
311 for (int i=0; i < DialpadRowCount ;i++) { |
|
312 mGridLayout->setRowFixedHeight(i, height); |
|
313 } |
|
314 } |