13 * |
13 * |
14 * Description: Dialpad keypad |
14 * Description: Dialpad keypad |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 #include <QtGui> |
18 #include <QLocale> |
|
19 #include <QSignalMapper> |
|
20 |
19 #include <hbinstance.h> |
21 #include <hbinstance.h> |
20 #include <hbinputkeymapfactory.h> |
22 #include <hbinputkeymapfactory.h> |
21 #include <hbinputkeymap.h> |
23 #include <hbinputkeymap.h> |
22 #include <hbinpututils.h> |
24 #include <hbinpututils.h> |
23 #include <hbinputsettingproxy.h> |
25 #include <hbinputsettingproxy.h> |
24 #include <hbinputlanguage.h> |
26 #include <hbinputlanguage.h> |
25 #include <hbapplication.h> |
27 #include <hbapplication.h> |
26 #include <hblineedit.h> |
28 #include <hblineedit.h> |
|
29 #include <hbinputbutton.h> |
27 |
30 |
28 #include "dialpadkeypad.h" |
31 #include "dialpadkeypad.h" |
29 #include "dialpadbutton.h" |
32 #include "dialpadbutton.h" |
30 #include "dialpadinputfield.h" |
33 #include "dialpadinputfield.h" |
31 |
34 |
32 static const int DialpadRowCount = 5; |
35 static const int DialpadRowCount = 4; |
33 static const int DialpadColumnCount = 3; |
36 static const int DialpadColumnCount = 3; |
34 static const QString handsetIcon("qtg_mono_call"); |
37 static const QString handsetIcon("qtg_mono_call"); |
35 static const QString vmbxIcon("qtg_mono_voice_mailbox"); |
38 static const QString vmbxIcon("qtg_mono_voice_mailbox"); |
36 |
39 static const qreal DialpadKeypadBorderWidth = 0.25; |
37 static const int DialpadButtonToKeyCodeTable[DialpadButtonCount] = |
40 |
|
41 static const int DialpadKeyCodeTable[DialpadRowCount*DialpadColumnCount] = |
38 { |
42 { |
39 Qt::Key_1, Qt::Key_2, Qt::Key_3, |
43 Qt::Key_1, Qt::Key_2, Qt::Key_3, |
40 Qt::Key_4, Qt::Key_5, Qt::Key_6, |
44 Qt::Key_4, Qt::Key_5, Qt::Key_6, |
41 Qt::Key_7, Qt::Key_8, Qt::Key_9, |
45 Qt::Key_7, Qt::Key_8, Qt::Key_9, |
42 Qt::Key_Asterisk, Qt::Key_0, Qt::Key_NumberSign, |
46 Qt::Key_Asterisk, Qt::Key_0, Qt::Key_NumberSign |
43 Qt::Key_Yes |
47 // Qt::Key_Yes and Qt::Key_BackSpace are handled separately |
44 // Qt::Key_BackSpace is in input field |
|
45 }; |
48 }; |
46 |
49 |
47 DialpadKeypad::DialpadKeypad( |
50 DialpadKeypad::DialpadKeypad( |
48 const HbMainWindow& mainWindow, |
51 const HbMainWindow& mainWindow, |
49 DialpadInputField& inputField, |
52 DialpadInputField& inputField, |
50 QGraphicsItem* parent) : |
53 QGraphicsItem* parent) : |
51 HbWidget(parent), |
54 HbInputButtonGroup(parent), |
52 mMainWindow(mainWindow), |
55 mMainWindow(mainWindow), |
53 mInputField(inputField), |
56 mInputField(inputField) |
54 mLongPressDuration(0) |
57 { |
55 { |
58 setObjectName("keypad"); |
56 // create signal mappers |
59 |
57 mKeyPressedSignalMapper = new QSignalMapper(this); |
60 // create clicked signal mapper |
58 connect(mKeyPressedSignalMapper,SIGNAL(mapped(int)), |
|
59 SLOT(handleKeyPressed(int))); |
|
60 mKeyClickedSignalMapper = new QSignalMapper(this); |
61 mKeyClickedSignalMapper = new QSignalMapper(this); |
61 connect(mKeyClickedSignalMapper,SIGNAL(mapped(int)), |
62 connect(mKeyClickedSignalMapper,SIGNAL(mapped(int)), |
62 SLOT(handleKeyClicked(int))); |
63 SLOT(handleKeyClicked(int))); |
63 mKeyReleasedSignalMapper = new QSignalMapper(this); |
64 |
64 connect(mKeyReleasedSignalMapper,SIGNAL(mapped(int)), |
65 // connect backspace signals |
65 SLOT(handleKeyReleased(int))); |
|
66 |
|
67 connect(&mInputField.backspaceButton(),SIGNAL(clicked()), |
66 connect(&mInputField.backspaceButton(),SIGNAL(clicked()), |
68 mKeyClickedSignalMapper,SLOT(map())); |
67 mKeyClickedSignalMapper,SLOT(map())); |
69 mKeyClickedSignalMapper->setMapping(&mInputField.backspaceButton(), |
68 mKeyClickedSignalMapper->setMapping(&mInputField.backspaceButton(), |
70 Qt::Key_Backspace); |
69 Qt::Key_Backspace); |
71 |
70 |
72 // create keypad |
71 // create keypad |
73 for (int i = 0; i < DialpadButtonCount; i++) { |
72 setGridSize(QSize(DialpadColumnCount, DialpadRowCount)); |
74 int keyCode = DialpadButtonToKeyCodeTable[i]; |
73 setButtonBorderSize(DialpadKeypadBorderWidth); |
75 |
74 |
76 DialpadButton* button = new DialpadButton(this); |
75 QList<HbInputButton*> buttons; |
77 mButtons[i] = button; |
76 |
78 |
77 for (int i = 0; i < DialpadRowCount * DialpadColumnCount; ++i) { |
79 button->setStretched(true); |
78 HbInputButton *item = new HbInputButton( |
80 button->setFocusPolicy(Qt::NoFocus); |
79 DialpadKeyCodeTable[i], |
81 button->setFlag(QGraphicsItem::ItemIsFocusable,false); |
80 QPoint(i % DialpadColumnCount, i / DialpadColumnCount)); |
82 |
81 buttons.append(item); |
83 QString buttonName; |
82 |
84 buttonName.setNum(keyCode); |
83 item->setType(HbInputButton::ButtonTypeNormal); |
85 button->setObjectName(buttonName); |
|
86 |
|
87 if (keyCode==Qt::Key_Yes) { |
|
88 HbIcon callIcon(handsetIcon); // todo correct icon |
|
89 button->setIcon(callIcon); |
|
90 button->setButtonType(DialpadButton::CallButton); // for css |
|
91 } else { |
|
92 button->setButtonType(DialpadButton::NumericButton); // for css |
|
93 } |
|
94 |
|
95 if (keyCode==Qt::Key_1) { |
|
96 HbIcon mboxIcon(vmbxIcon); |
|
97 button->setIcon(mboxIcon); |
|
98 } |
|
99 |
|
100 if (keyCode!=Qt::Key_Yes) { |
|
101 connect(button,SIGNAL(pressed()), |
|
102 mKeyPressedSignalMapper,SLOT(map())); |
|
103 mKeyPressedSignalMapper->setMapping(button,keyCode); |
|
104 |
|
105 connect(button,SIGNAL(released()), |
|
106 mKeyReleasedSignalMapper,SLOT(map())); |
|
107 mKeyReleasedSignalMapper->setMapping(button,keyCode); |
|
108 } else { |
|
109 // for Yes-key longPress() functionality is same as clicked() |
|
110 connect(button,SIGNAL(longPress(QPointF)), |
|
111 mKeyClickedSignalMapper,SLOT(map())); |
|
112 mKeyClickedSignalMapper->setMapping(button,keyCode); |
|
113 } |
|
114 |
|
115 connect(button,SIGNAL(clicked()),mKeyClickedSignalMapper,SLOT(map())); |
|
116 mKeyClickedSignalMapper->setMapping(button,keyCode); |
|
117 } |
84 } |
|
85 |
|
86 setButtons(buttons); |
|
87 |
|
88 // connect keypad signals |
|
89 QObject::connect(this, SIGNAL(buttonPressed(const QKeyEvent&)), |
|
90 this, SLOT(sendKeyPressEvent(const QKeyEvent&))); |
|
91 QObject::connect(this, SIGNAL(buttonReleased(const QKeyEvent&)), |
|
92 this, SLOT(sendKeyReleaseEvent(const QKeyEvent&))); |
|
93 QObject::connect(this, SIGNAL(buttonLongPressed(const QKeyEvent&)), |
|
94 this, SLOT(sendLongPressEvent(const QKeyEvent&))); |
|
95 QObject::connect(this, SIGNAL(pressedButtonChanged(const QKeyEvent&, |
|
96 const QKeyEvent&)), |
|
97 this, SLOT(handleKeyChangeEvent(const QKeyEvent&, |
|
98 const QKeyEvent&))); |
|
99 |
|
100 // create call button (parent layouts this) |
|
101 mCallButton = new DialpadButton(parent); |
|
102 mCallButton->setButtonType(DialpadButton::CallButton); |
|
103 mCallButton->setIcon(HbIcon(handsetIcon)); |
|
104 QString buttonName; |
|
105 buttonName.setNum(Qt::Key_Yes); |
|
106 mCallButton->setObjectName(buttonName); |
|
107 connect(mCallButton,SIGNAL(clicked()), |
|
108 mKeyClickedSignalMapper,SLOT(map())); |
|
109 connect(mCallButton,SIGNAL(longPress(QPointF)), |
|
110 mKeyClickedSignalMapper,SLOT(map())); |
|
111 mKeyClickedSignalMapper->setMapping(mCallButton, |
|
112 Qt::Key_Yes); |
118 |
113 |
119 // set button texts |
114 // set button texts |
120 setButtonTexts(); |
115 setButtonTexts(); |
|
116 // set button icons |
|
117 button(0)->setIcon(HbIcon(vmbxIcon), |
|
118 HbInputButton::ButtonIconIndexSecondaryFirstRow); |
|
119 |
121 // update button texts when input language is changed |
120 // update button texts when input language is changed |
122 connect(HbInputSettingProxy::instance(), |
121 connect(HbInputSettingProxy::instance(), |
123 SIGNAL(globalInputLanguageChanged(HbInputLanguage)), |
122 SIGNAL(globalInputLanguageChanged(HbInputLanguage)), |
124 this,SLOT(setButtonTexts())); |
123 this,SLOT(setButtonTexts())); |
125 |
|
126 createButtonGrid(); |
|
127 |
|
128 // timer to handle long press |
|
129 mLongPressTimer = new QTimer(this); |
|
130 mLongPressTimer->setSingleShot(true); |
|
131 connect(mLongPressTimer,SIGNAL(timeout()),SLOT(handleLongPress())); |
|
132 } |
124 } |
133 |
125 |
134 DialpadKeypad::~DialpadKeypad() |
126 DialpadKeypad::~DialpadKeypad() |
135 { |
127 { |
136 } |
|
137 |
|
138 void DialpadKeypad::createButtonGrid() |
|
139 { |
|
140 // button grid |
|
141 mGridLayout = new QGraphicsGridLayout; |
|
142 |
|
143 // 12 numeric buttons |
|
144 int i=0; |
|
145 for (int row = 0; row < DialpadRowCount-1; row++) { |
|
146 for (int col = 0; col < DialpadColumnCount; col++) { |
|
147 mGridLayout->addItem(mButtons[i],row,col); |
|
148 i++; |
|
149 } |
|
150 } |
|
151 |
|
152 // call button take the last row |
|
153 mGridLayout->addItem(mButtons[12],4,0,1,3); |
|
154 mGridLayout->setSpacing(0); |
|
155 mGridLayout->setContentsMargins(0,0,0,0); |
|
156 |
|
157 setLayout(mGridLayout); |
|
158 } |
128 } |
159 |
129 |
160 void DialpadKeypad::setButtonTexts() |
130 void DialpadKeypad::setButtonTexts() |
161 { |
131 { |
162 HbInputLanguage inputLanguage = |
132 HbInputLanguage inputLanguage = |
217 } |
193 } |
218 |
194 |
219 QString characters = key->characters(HbModifierNone); |
195 QString characters = key->characters(HbModifierNone); |
220 |
196 |
221 if (numberOfCharacters==0 && keyCode!=Qt::Key_1) { |
197 if (numberOfCharacters==0 && keyCode!=Qt::Key_1) { |
222 mButtons[i]->setAdditionalText(" "); |
198 button(i)->setText(" ", |
|
199 HbInputButton::ButtonTextIndexSecondaryFirstRow); |
223 } else { |
200 } else { |
224 mButtons[i]->setAdditionalText( |
201 button(i)->setText(characters.left(numberOfCharacters), |
225 characters.left(numberOfCharacters)); |
202 HbInputButton::ButtonTextIndexSecondaryFirstRow); |
226 } |
203 } |
227 } |
204 } |
228 } |
205 } |
229 } |
206 } |
230 } |
207 } |
231 |
208 |
232 void DialpadKeypad::handleKeyPressed(int key) |
209 void DialpadKeypad::handleKeyClicked(int key) |
233 { |
210 { |
234 // Editor is updated on key release (clicked()) or on long press, |
211 // concerns only yes and backspace keys |
235 // to prevent editor being updated during swipe. |
|
236 mPressedNumericKey = key; |
|
237 mLongPressTimer->start(mLongPressDuration); |
|
238 |
|
239 postKeyEvent(QEvent::KeyPress, key); |
212 postKeyEvent(QEvent::KeyPress, key); |
240 } |
|
241 |
|
242 void DialpadKeypad::handleKeyClicked(int key) |
|
243 { |
|
244 if (!isNumericKey(key)) { |
|
245 postKeyEvent(QEvent::KeyPress, key); |
|
246 postKeyEvent(QEvent::KeyRelease, key); |
|
247 } else if (mPressedNumericKey) { |
|
248 // update editor: generate key press event. |
|
249 sendKeyEventToEditor(QEvent::KeyPress, key); |
|
250 } |
|
251 } |
|
252 |
|
253 void DialpadKeypad::handleKeyReleased(int key) |
|
254 { |
|
255 mLongPressTimer->stop(); |
|
256 |
|
257 postKeyEvent(QEvent::KeyRelease, key); |
213 postKeyEvent(QEvent::KeyRelease, key); |
258 } |
214 } |
259 |
215 |
260 void DialpadKeypad::postKeyEvent(QEvent::Type type, int key) |
216 void DialpadKeypad::postKeyEvent(QEvent::Type type, int key) |
261 { |
217 { |
|
218 // send simulated key to application |
262 QKeyEvent *keyEvent = new QKeyEvent(type, key, Qt::NoModifier); |
219 QKeyEvent *keyEvent = new QKeyEvent(type, key, Qt::NoModifier); |
263 HbApplication::postEvent(const_cast<HbMainWindow*>(&mMainWindow),keyEvent); |
220 HbApplication::postEvent(const_cast<HbMainWindow*>(&mMainWindow),keyEvent); |
264 } |
221 } |
265 |
222 |
266 void DialpadKeypad::sendKeyEventToEditor(QEvent::Type type, int key) |
223 void DialpadKeypad::sendKeyEventToEditor(QEvent::Type type, int key) |
267 { |
224 { |
|
225 // send key event to editor |
268 QKeyEvent keyEvent(type, key, Qt::NoModifier, mGeneratedChar.value(key)); |
226 QKeyEvent keyEvent(type, key, Qt::NoModifier, mGeneratedChar.value(key)); |
269 HbApplication::sendEvent(&mInputField.editor(), &keyEvent); |
227 HbApplication::sendEvent(&mInputField.editor(), &keyEvent); |
270 } |
228 } |
271 |
229 |
272 void DialpadKeypad::handleLongPress() |
230 void DialpadKeypad::sendKeyPressEvent(const QKeyEvent& event) |
273 { |
231 { |
274 // key press |
232 mPressedNumericKey = event.key(); |
275 sendKeyEventToEditor(QEvent::KeyPress, mPressedNumericKey); |
233 postKeyEvent(QEvent::KeyPress, event.key()); |
|
234 } |
|
235 |
|
236 void DialpadKeypad::sendKeyReleaseEvent(const QKeyEvent& event) |
|
237 { |
|
238 if (mPressedNumericKey) { |
|
239 // short press, update editor here |
|
240 sendKeyEventToEditor(QEvent::KeyPress, event.key()); |
|
241 } |
|
242 |
|
243 postKeyEvent(QEvent::KeyRelease, event.key()); |
|
244 } |
|
245 |
|
246 void DialpadKeypad::sendLongPressEvent(const QKeyEvent& event) |
|
247 { |
|
248 sendKeyEventToEditor(QEvent::KeyPress, event.key()); |
276 mPressedNumericKey = 0; |
249 mPressedNumericKey = 0; |
277 } |
250 } |
278 |
251 |
279 bool DialpadKeypad::isNumericKey(int key) |
252 void DialpadKeypad::handleKeyChangeEvent( |
280 { |
253 const QKeyEvent& releaseEvent, |
281 if (key==Qt::Key_Yes || key==Qt::Key_Backspace) { |
254 const QKeyEvent& pressEvent) |
282 return false; |
255 { |
283 } else { |
256 Q_UNUSED(pressEvent) |
284 return true; |
257 |
285 } |
258 postKeyEvent(QEvent::KeyRelease, releaseEvent.key()); |
286 } |
259 cancelButtonPress(); |
287 |
|
288 void DialpadKeypad::setLongPressDuration(int duration) |
|
289 { |
|
290 mLongPressDuration = duration; |
|
291 } |
260 } |
292 |
261 |
293 void DialpadKeypad::setCallButtonEnabled(bool enabled) |
262 void DialpadKeypad::setCallButtonEnabled(bool enabled) |
294 { |
263 { |
295 mButtons[DialpadButtonCount-1]->setEnabled(enabled); |
264 mCallButton->setEnabled(enabled); |
296 } |
|
297 |
|
298 void DialpadKeypad::showEvent(QShowEvent *event) |
|
299 { |
|
300 HbWidget::showEvent(event); |
|
301 |
|
302 if (parentWidget()->isVisible()) { |
|
303 // first show event comes before dialpad is open |
|
304 // set fixed row and column dimensions |
|
305 QSizeF effectiveSize(rect().width(), |
|
306 rect().height()); |
|
307 |
|
308 qreal width = effectiveSize.width() / DialpadColumnCount; |
|
309 qreal height = effectiveSize.height() / DialpadRowCount; |
|
310 |
|
311 for (int i=0; i < DialpadColumnCount ;i++) { |
|
312 mGridLayout->setColumnFixedWidth(i, width); |
|
313 } |
|
314 |
|
315 for (int i=0; i < DialpadRowCount ;i++) { |
|
316 mGridLayout->setRowFixedHeight(i, height); |
|
317 } |
|
318 } |
|
319 } |
265 } |
320 |
266 |
321 void DialpadKeypad::resetButtons() |
267 void DialpadKeypad::resetButtons() |
322 { |
268 { |
323 for(int i = 0; i < DialpadButtonCount; i++) { |
269 cancelButtonPress(); |
324 mButtons[i]->setDown(false); |
270 mCallButton->setDown(false); |
325 } |
271 } |
326 } |
272 |
|
273 DialpadButton& DialpadKeypad::callButton() const |
|
274 { |
|
275 return *mCallButton; |
|
276 } |