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 popup |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <QGraphicsLinearLayout> |
|
19 |
|
20 #include <hbframedrawer.h> |
|
21 #include <hbinstance.h> |
|
22 #include <hbeffect.h> |
|
23 #include <hbinstance.h> |
|
24 #include <hbmainwindow.h> |
|
25 #include <hbstyleloader.h> |
|
26 #include <hblineedit.h> |
|
27 #include <hbapplication.h> |
|
28 #include <hbswipegesture.h> |
|
29 #include <hbeffect.h> |
|
30 #include <hbevent.h> |
|
31 |
|
32 #include "dialpad.h" |
|
33 #include "dialpadinputfield.h" |
|
34 #include "dialpadkeypad.h" |
|
35 #include "dialpadbutton.h" |
|
36 #include "dialpadmultitaphandler.h" |
|
37 #include "dialpadbackground.h" |
|
38 #include "dialpadbutton.h" |
|
39 |
|
40 static const QLatin1String backgroundGraphics("qtg_fr_input_v_bg"); |
|
41 static const QLatin1String backgroundGraphicsH("qtg_fr_input_h_bg"); |
|
42 static const QLatin1String minimizeIcon("qtg_graf_input_v_swipe"); |
|
43 static const QLatin1String minimizeIconH("qtg_graf_input_h_swipe"); |
|
44 static const int DialpadCloseAnimDuration = 200; // ms |
|
45 static const int DialpadOpenAnimDuration = 200; // ms |
|
46 static const qreal DialpadComponentMargin = 0.75; // units |
|
47 static const qreal DialpadCloseHandleHeight = 2.23; // units |
|
48 static const qreal DialpadCloseHandleWidth = 18.8; // units |
|
49 static const qreal DialpadCallButtonHeight = 8.75; // units, same as numeric buttons |
|
50 static const qreal DialpadCallButtonHeightH = 7.25; // units |
|
51 |
|
52 static const QLatin1String handsetIcon("qtg_mono_call"); |
|
53 static const QLatin1String vmbxIcon("qtg_mono_voice_mailbox"); |
|
54 |
|
55 const QLatin1String DIALPAD_TO_PRT_FXML(":/dialpad_to_prt.fxml"); |
|
56 const QLatin1String DIALPAD_TO_LSC_FXML(":/dialpad_to_lsc.fxml"); |
|
57 const QLatin1String DIALPAD_TO_PRT_EVENT("prt_activated"); |
|
58 const QLatin1String DIALPAD_TO_LSC_EVENT("lsc_activated"); |
|
59 |
|
60 Dialpad::Dialpad() : |
|
61 mMainWindow(*hbInstance->allMainWindows().at(0)), |
|
62 mBackgroundItem(0), |
|
63 mOpenTimeLine(DialpadOpenAnimDuration), |
|
64 mCloseTimeLine(DialpadCloseAnimDuration), |
|
65 mAnimationOngoing(false), |
|
66 mOrientation(Qt::Vertical), |
|
67 mIsOpen(false) |
|
68 { |
|
69 // this constuctor is deprecated |
|
70 initialize(); |
|
71 } |
|
72 |
|
73 Dialpad::Dialpad(const HbMainWindow& mainWindow) : |
|
74 mMainWindow(mainWindow), |
|
75 mBackgroundItem(0), |
|
76 mOpenTimeLine(DialpadOpenAnimDuration), |
|
77 mCloseTimeLine(DialpadCloseAnimDuration), |
|
78 mAnimationOngoing(false), |
|
79 mOrientation(Qt::Vertical), |
|
80 mIsOpen(false) |
|
81 { |
|
82 initialize(); |
|
83 } |
|
84 |
|
85 void Dialpad::initialize() |
|
86 { |
|
87 setFocusPolicy(Qt::StrongFocus); |
|
88 setFlag(QGraphicsItem::ItemIsFocusable,true); |
|
89 setFlag(QGraphicsItem::ItemHasNoContents, false); |
|
90 |
|
91 // create input field |
|
92 mInputField = new DialpadInputField(this); |
|
93 |
|
94 // create keypad |
|
95 mKeypad = new DialpadKeypad(mMainWindow,*mInputField,this); |
|
96 |
|
97 // layouting params |
|
98 qreal unit = HbDeviceProfile::current().unitValue(); |
|
99 qreal margin = DialpadComponentMargin * unit; |
|
100 mCloseHandleHeight = DialpadCloseHandleHeight * unit; |
|
101 mCloseHandleWidth = DialpadCloseHandleWidth * unit; |
|
102 |
|
103 mKeypad->callButton().setPreferredHeight(DialpadCallButtonHeight*unit); |
|
104 mKeypad->callButton().setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
|
105 |
|
106 // create popup background |
|
107 mBackgroundDrawer = new HbFrameDrawer(); |
|
108 mIconDrawer = new HbFrameDrawer(); |
|
109 |
|
110 // popup layout |
|
111 QGraphicsLinearLayout* popupLayout = |
|
112 new QGraphicsLinearLayout(Qt::Vertical); |
|
113 popupLayout->addItem(mInputField); |
|
114 popupLayout->addItem(mKeypad); |
|
115 popupLayout->addItem(&mKeypad->callButton()); |
|
116 popupLayout->setContentsMargins(margin, mCloseHandleHeight, margin, margin); |
|
117 popupLayout->setSpacing(0); |
|
118 popupLayout->setItemSpacing(0,margin); |
|
119 setLayout(popupLayout); |
|
120 setLayoutDirection(Qt::LeftToRight); |
|
121 |
|
122 // asterisk multitap handler |
|
123 mMultitap = new DialpadMultitapHandler(mInputField->editor(),this); |
|
124 mInputField->editor().installEventFilter(mMultitap); |
|
125 |
|
126 // close animation |
|
127 mCloseTimeLine.setUpdateInterval(16); |
|
128 mCloseTimeLine.setEasingCurve(QEasingCurve::InQuad); |
|
129 connect(&mCloseTimeLine, SIGNAL(finished()), |
|
130 SLOT(closeAnimFinished())); |
|
131 connect(&mCloseTimeLine, SIGNAL(valueChanged(qreal)), |
|
132 SLOT(closeAnimValueChanged(qreal))); |
|
133 |
|
134 // open animation |
|
135 mOpenTimeLine.setUpdateInterval(16); |
|
136 mOpenTimeLine.setEasingCurve(QEasingCurve::OutQuad); |
|
137 connect(&mOpenTimeLine, SIGNAL(finished()), |
|
138 SLOT(openAnimFinished())); |
|
139 connect(&mOpenTimeLine, SIGNAL(valueChanged(qreal)), |
|
140 SLOT(openAnimValueChanged(qreal))); |
|
141 |
|
142 // default values |
|
143 setPos(0,0); |
|
144 setPreferredSize(360,360); |
|
145 setZValue(0x00004000); // Hb PopupZValueRangeStart |
|
146 hide(); |
|
147 mMainWindow.scene()->addItem(this); |
|
148 |
|
149 // custom button style |
|
150 HbStyleLoader::registerFilePath(QLatin1String(":/dialpad.css")); |
|
151 HbStyleLoader::registerFilePath(QLatin1String(":/dialpad_color.css")); |
|
152 |
|
153 // grab gestures so that those are not passed to widgets behind dialpad |
|
154 grabGesture(Qt::TapGesture); |
|
155 grabGesture(Qt::TapAndHoldGesture); |
|
156 grabGesture(Qt::PanGesture); |
|
157 grabGesture(Qt::SwipeGesture); |
|
158 grabGesture(Qt::PinchGesture); |
|
159 |
|
160 // effects |
|
161 HbEffect::add(this, DIALPAD_TO_PRT_FXML, DIALPAD_TO_PRT_EVENT); |
|
162 HbEffect::add(this, DIALPAD_TO_LSC_FXML, DIALPAD_TO_LSC_EVENT); |
|
163 } |
|
164 |
|
165 Dialpad::~Dialpad() |
|
166 { |
|
167 delete mBackgroundDrawer; |
|
168 delete mIconDrawer; |
|
169 delete mBackgroundItem; |
|
170 } |
|
171 |
|
172 void Dialpad::paint( |
|
173 QPainter* painter, |
|
174 const QStyleOptionGraphicsItem* option, |
|
175 QWidget* widget) |
|
176 { |
|
177 Q_UNUSED(option); |
|
178 Q_UNUSED(widget); |
|
179 |
|
180 // paint popup background |
|
181 if ( mOrientation == Qt::Vertical ) { |
|
182 mBackgroundDrawer->setFrameGraphicsName(backgroundGraphics); |
|
183 mIconDrawer->setFrameGraphicsName(minimizeIcon); |
|
184 mBackgroundDrawer->setFrameType(HbFrameDrawer::ThreePiecesVertical); |
|
185 mBackgroundDrawer->setBorderWidths(0.0, mCloseHandleHeight, 0.0, 0.0); |
|
186 } else { |
|
187 mBackgroundDrawer->setFrameGraphicsName(backgroundGraphicsH); |
|
188 mIconDrawer->setFrameGraphicsName(minimizeIconH); |
|
189 mBackgroundDrawer->setFrameType(HbFrameDrawer::ThreePiecesHorizontal); |
|
190 mBackgroundDrawer->setBorderWidths(mCloseHandleHeight, 0.0, 0.0, 0.0); |
|
191 } |
|
192 |
|
193 // draw background |
|
194 QRectF rect = boundingRect(); |
|
195 mBackgroundDrawer->setFillWholeRect(true); |
|
196 mBackgroundDrawer->paint(painter, rect); |
|
197 |
|
198 // adjust rectangle to close bar position |
|
199 if ( mOrientation == Qt::Vertical ) { |
|
200 rect.setLeft((rect.width()- mCloseHandleWidth)/2); |
|
201 rect.setWidth(mCloseHandleWidth); |
|
202 rect.setHeight(mCloseHandleHeight); |
|
203 } else { |
|
204 rect.setTop((rect.height() - mCloseHandleWidth)/2); |
|
205 rect.setWidth(mCloseHandleHeight); |
|
206 rect.setHeight(mCloseHandleWidth); |
|
207 } |
|
208 |
|
209 mIconDrawer->setFrameType(HbFrameDrawer::OnePiece); |
|
210 mIconDrawer->paint(painter, rect); |
|
211 } |
|
212 |
|
213 void Dialpad::changeEvent(QEvent *event) |
|
214 { |
|
215 if (event->type() == QEvent::LayoutDirectionChange) { |
|
216 mBackgroundDrawer->setLayoutDirection(layoutDirection()); |
|
217 } else if (event->type() == HbEvent::ThemeChanged) { |
|
218 mBackgroundDrawer->themeChanged(); |
|
219 mIconDrawer->themeChanged(); |
|
220 } |
|
221 } |
|
222 |
|
223 bool Dialpad::isOpen() const |
|
224 { |
|
225 return mIsOpen; |
|
226 } |
|
227 |
|
228 bool Dialpad::isCallButtonEnabled() const |
|
229 { |
|
230 return mKeypad->callButton().isEnabled(); |
|
231 } |
|
232 |
|
233 void Dialpad::openDialpad() |
|
234 { |
|
235 mKeypad->resetButtons(); |
|
236 |
|
237 if (mIsOpen) { |
|
238 return; |
|
239 } |
|
240 |
|
241 connect(&mMainWindow,SIGNAL(aboutToChangeOrientation()), |
|
242 SLOT(orientationChangeStarted())); |
|
243 connect(&mMainWindow,SIGNAL(orientationChanged(Qt::Orientation)), |
|
244 SLOT(orientationChangeFinished(Qt::Orientation))); |
|
245 |
|
246 // set offset for open animation |
|
247 int previousOrientation = mOrientation; |
|
248 mOrientation = mMainWindow.orientation(); |
|
249 |
|
250 mPosition = pos(); |
|
251 if (mOrientation==Qt::Vertical) { |
|
252 qreal height = geometry().height(); |
|
253 setPos(mPosition.x(),mPosition.y()+height); |
|
254 } else { |
|
255 qreal width = geometry().width(); |
|
256 setPos(mPosition.x()+width,mPosition.y()); |
|
257 } |
|
258 |
|
259 if (mOrientation!=previousOrientation) { |
|
260 updateLayout((Qt::Orientation)mOrientation); |
|
261 } |
|
262 |
|
263 show(); |
|
264 |
|
265 setFocusProxy(&mInputField->editor()); |
|
266 mInputField->editor().setFocus(); |
|
267 |
|
268 mOpenTimeLine.start(); |
|
269 mAnimationOngoing = true; |
|
270 if (!mInputField->editor().text().isEmpty()) { |
|
271 setCallButtonEnabled(true); |
|
272 } |
|
273 mIsOpen = true; |
|
274 |
|
275 emit aboutToOpen(); |
|
276 } |
|
277 |
|
278 void Dialpad::closeDialpad() |
|
279 { |
|
280 close(); |
|
281 |
|
282 disconnect(&mMainWindow,SIGNAL(aboutToChangeOrientation()), |
|
283 this, SLOT(orientationChangeStarted())); |
|
284 disconnect(&mMainWindow,SIGNAL(orientationChanged(Qt::Orientation)), |
|
285 this, SLOT(orientationChangeFinished(Qt::Orientation))); |
|
286 |
|
287 if (mBackgroundItem) { |
|
288 mBackgroundItem->hide(); |
|
289 } |
|
290 } |
|
291 |
|
292 HbLineEdit& Dialpad::editor() const |
|
293 { |
|
294 return mInputField->editor(); |
|
295 } |
|
296 |
|
297 void Dialpad::setCallButtonEnabled(bool enabled) |
|
298 { |
|
299 mKeypad->setCallButtonEnabled(enabled); |
|
300 } |
|
301 |
|
302 void Dialpad::setTapOutsideDismiss(bool dismiss) |
|
303 { |
|
304 // set dismiss policy before opening dialpad |
|
305 Q_ASSERT(!isVisible()); |
|
306 |
|
307 if (dismiss) { |
|
308 mBackgroundItem = new DialpadBackground(*this); |
|
309 mBackgroundItem->setZValue(zValue()-1); |
|
310 mMainWindow.scene()->addItem(mBackgroundItem); |
|
311 qreal chromeHeight = 0; |
|
312 hbInstance->style()->parameter(QLatin1String("hb-param-widget-chrome-height"), |
|
313 chromeHeight); |
|
314 mTitleBarHeight = chromeHeight; |
|
315 } else { |
|
316 delete mBackgroundItem; |
|
317 mBackgroundItem = 0; |
|
318 } |
|
319 } |
|
320 |
|
321 void Dialpad::startCloseAnimation() |
|
322 { |
|
323 if (!mAnimationOngoing) { |
|
324 mCloseTimeLine.start(); |
|
325 mAnimationOngoing = true; |
|
326 } |
|
327 } |
|
328 |
|
329 void Dialpad::showEvent(QShowEvent *event) |
|
330 { |
|
331 HbWidget::showEvent(event); |
|
332 |
|
333 if (mBackgroundItem) { |
|
334 layoutBackgroundItem(); |
|
335 mBackgroundItem->show(); |
|
336 } |
|
337 } |
|
338 |
|
339 void Dialpad::hideEvent(QHideEvent *event) |
|
340 { |
|
341 HbWidget::hideEvent(event); |
|
342 } |
|
343 |
|
344 void Dialpad::closeEvent(QCloseEvent * event) |
|
345 { |
|
346 mIsOpen = false; |
|
347 HbWidget::closeEvent(event); |
|
348 emit aboutToClose(); |
|
349 } |
|
350 |
|
351 void Dialpad::closeAnimValueChanged(qreal value) |
|
352 { |
|
353 QPointF currentPos = pos(); |
|
354 QPointF newPos; |
|
355 |
|
356 if (mOrientation==Qt::Vertical) { |
|
357 qreal height = geometry().height(); |
|
358 |
|
359 newPos.setX(currentPos.x()); |
|
360 newPos.setY(mPosition.y()+(height*value)); |
|
361 } else { |
|
362 qreal width = geometry().width(); |
|
363 |
|
364 newPos.setY(currentPos.y()); |
|
365 newPos.setX(mPosition.x()+(width*value)); |
|
366 } |
|
367 |
|
368 setPos(newPos); |
|
369 } |
|
370 |
|
371 |
|
372 void Dialpad::closeAnimFinished() |
|
373 { |
|
374 mAnimationOngoing = false; |
|
375 closeDialpad(); |
|
376 setPos(mPosition); |
|
377 } |
|
378 |
|
379 void Dialpad::openAnimValueChanged(qreal value) |
|
380 { |
|
381 QPointF currentPos = pos(); |
|
382 QPointF newPos; |
|
383 |
|
384 if (mOrientation==Qt::Vertical) { |
|
385 qreal height = geometry().height(); |
|
386 |
|
387 newPos.setX(currentPos.x()); |
|
388 newPos.setY(mPosition.y()+(height*(1-value))); |
|
389 } else { |
|
390 qreal width = geometry().width(); |
|
391 |
|
392 newPos.setY(currentPos.y()); |
|
393 newPos.setX(mPosition.x()+(width*(1-value))); |
|
394 } |
|
395 |
|
396 setPos(newPos); |
|
397 } |
|
398 |
|
399 void Dialpad::openAnimFinished() |
|
400 { |
|
401 mAnimationOngoing = false; |
|
402 setPos(mPosition); |
|
403 } |
|
404 |
|
405 void Dialpad::orientationChangeStarted() |
|
406 { |
|
407 hide(); |
|
408 } |
|
409 |
|
410 void Dialpad::orientationChangeFinished(Qt::Orientation current) |
|
411 { |
|
412 updateLayout(current); |
|
413 |
|
414 show(); |
|
415 |
|
416 // run orientation change effect |
|
417 if (current==Qt::Horizontal) { |
|
418 HbEffect::start(this, DIALPAD_TO_LSC_EVENT); |
|
419 } else { |
|
420 HbEffect::start(this, DIALPAD_TO_PRT_EVENT); |
|
421 } |
|
422 |
|
423 mOrientation = current; |
|
424 |
|
425 mPosition = pos(); |
|
426 |
|
427 if (mBackgroundItem) { |
|
428 layoutBackgroundItem(); |
|
429 } |
|
430 } |
|
431 |
|
432 void Dialpad::layoutBackgroundItem() |
|
433 { |
|
434 Q_ASSERT(mBackgroundItem); |
|
435 QRectF backgroundRect(mMainWindow.layoutRect()); |
|
436 backgroundRect.adjust(0,mTitleBarHeight,0,0); |
|
437 mBackgroundItem->setRect(backgroundRect); |
|
438 } |
|
439 |
|
440 void Dialpad::updateLayout(Qt::Orientation orientation) |
|
441 { |
|
442 Q_ASSERT(layout()); |
|
443 |
|
444 qreal unit = HbDeviceProfile::current().unitValue(); |
|
445 qreal margin = DialpadComponentMargin * unit; |
|
446 |
|
447 QGraphicsLinearLayout* mainLayout = |
|
448 static_cast<QGraphicsLinearLayout*>(layout()); |
|
449 |
|
450 // close handle location changes, update margin values |
|
451 if (orientation==Qt::Vertical) { |
|
452 mainLayout->setContentsMargins(margin, |
|
453 mCloseHandleHeight, |
|
454 margin, |
|
455 margin); |
|
456 mKeypad->callButton().setPreferredHeight(DialpadCallButtonHeight*unit); |
|
457 } else { |
|
458 mainLayout->setContentsMargins(mCloseHandleHeight, |
|
459 margin, |
|
460 margin, |
|
461 margin); |
|
462 mKeypad->callButton().setPreferredHeight(DialpadCallButtonHeightH*unit); |
|
463 } |
|
464 } |
|
465 |
|
466 void Dialpad::gestureEvent(QGestureEvent *event) |
|
467 { |
|
468 bool closeGesture(false); |
|
469 |
|
470 if(HbSwipeGesture *gesture = qobject_cast<HbSwipeGesture*>( |
|
471 event->gesture(Qt::SwipeGesture))) { |
|
472 if (gesture->state() == Qt::GestureFinished) { |
|
473 if ( mOrientation==Qt::Vertical && |
|
474 gesture->sceneVerticalDirection() == QSwipeGesture::Down ) { |
|
475 closeGesture = true; |
|
476 } else if (mOrientation==Qt::Horizontal && |
|
477 gesture->sceneHorizontalDirection() == QSwipeGesture::Right) { |
|
478 closeGesture = true; |
|
479 } |
|
480 } |
|
481 } |
|
482 |
|
483 if (closeGesture) { |
|
484 startCloseAnimation(); |
|
485 event->accept(); |
|
486 } else { |
|
487 event->ignore(); |
|
488 } |
|
489 } |
|