22 #include <hbinstance.h> |
22 #include <hbinstance.h> |
23 #include "glximagedecoderwrapper.h" |
23 #include "glximagedecoderwrapper.h" |
24 #include "glxmodelparm.h" |
24 #include "glxmodelparm.h" |
25 #include "glxzoomwidget.h" |
25 #include "glxzoomwidget.h" |
26 |
26 |
|
27 const int MAXZVALUE = 100; |
|
28 const int MINZVALUE = 0; |
|
29 const int NOOFSTEPSZI = 24; |
|
30 const int NOOFSTEPSZO = 18; |
|
31 const float MAXDTZOOMIN = 3.5; |
|
32 |
27 GlxZoomWidget::GlxZoomWidget(QGraphicsItem *parent):HbScrollArea(parent), |
33 GlxZoomWidget::GlxZoomWidget(QGraphicsItem *parent):HbScrollArea(parent), |
28 mModel(NULL), mMinZValue(MINZVALUE), |
34 mModel(NULL), mMinZValue(MINZVALUE), |
29 mMaxZValue(MAXZVALUE), mTimerId(0), |
35 mMaxZValue(MAXZVALUE), mTimerId(0), |
30 mImageDecodeRequestSend(false), |
36 mImageDecodeRequestSend(false), |
31 mPinchGestureOngoing(false), mDecodedImageAvailable(false), |
37 mPinchGestureOngoing(false), mDecodedImageAvailable(false), |
32 mZoomOngoing(false) |
38 mZoomOngoing(false) |
33 { |
39 { |
34 grabGesture(Qt::PinchGesture); |
40 grabGesture(Qt::PinchGesture); |
35 grabGesture(Qt::TapGesture); |
41 grabGesture(Qt::TapGesture); |
36 setAcceptTouchEvents(true) ; |
42 setAcceptTouchEvents(true) ; |
37 setFrictionEnabled(false); |
43 setFrictionEnabled(true); |
38 setZValue(mMinZValue); |
44 setZValue(mMinZValue); |
39 //create the child items and background |
45 //create the child items and background |
40 mZoomWidget = new QGraphicsWidget(this); |
46 mZoomWidget = new QGraphicsWidget(this); |
41 mZoomItem = new QGraphicsPixmapItem(mZoomWidget); |
47 mZoomItem = new QGraphicsPixmapItem(mZoomWidget); |
42 mZoomItem->setTransformationMode(Qt::SmoothTransformation); |
48 mZoomItem->setTransformationMode(Qt::SmoothTransformation); |
201 QPinchGesture* pinchG = static_cast<QPinchGesture *>(pinch); |
208 QPinchGesture* pinchG = static_cast<QPinchGesture *>(pinch); |
202 QPinchGesture::ChangeFlags changeFlags = pinchG->changeFlags(); |
209 QPinchGesture::ChangeFlags changeFlags = pinchG->changeFlags(); |
203 if (changeFlags & QPinchGesture::ScaleFactorChanged) { |
210 if (changeFlags & QPinchGesture::ScaleFactorChanged) { |
204 mPinchGestureOngoing = true; |
211 mPinchGestureOngoing = true; |
205 mZoomOngoing = true; |
212 mZoomOngoing = true; |
206 //bring the zoom widget to foreground |
213 |
207 setZValue(mMaxZValue); |
|
208 //show the black background |
|
209 mBlackBackgroundItem->setParentItem(parentItem()); |
|
210 mBlackBackgroundItem->setZValue(mMaxZValue - 1); |
|
211 mBlackBackgroundItem->show(); |
|
212 |
|
213 //retreive the gesture values |
214 //retreive the gesture values |
214 qreal value = pinchG->scaleFactor() / pinchG->lastScaleFactor(); |
215 qreal value = pinchG->scaleFactor() / pinchG->lastScaleFactor(); |
215 QPointF center = pinchG->property("centerPoint").toPointF(); |
216 QPointF center = pinchG->property("centerPoint").toPointF(); |
216 //set the gesture center to the scene coordinates |
217 //set the gesture center to the scene coordinates |
217 QPointF sceneGestureCenter = hbInstance->allMainWindows().first()->mapToScene(center.toPoint()); |
218 QPointF sceneGestureCenter = hbInstance->allMainWindows().first()->mapToScene(center.toPoint()); |
218 zoomImage(value, sceneGestureCenter); |
219 zoomImage(value, sceneGestureCenter); |
219 |
220 |
220 } |
221 } |
221 if (pinchG->state() == Qt::GestureStarted) { |
222 if (pinchG->state() == Qt::GestureStarted) { |
222 emit pinchGestureReceived(mFocusIndex); |
223 emit pinchGestureReceived(mFocusIndex); |
|
224 //bring the zoom widget to foreground |
|
225 setZValue(mMaxZValue); |
|
226 //show the black background |
|
227 mBlackBackgroundItem->setParentItem(parentItem()); |
|
228 mBlackBackgroundItem->setZValue(mMaxZValue - 1); |
|
229 mBlackBackgroundItem->show(); |
223 } |
230 } |
224 |
231 |
225 if (pinchG->state() == Qt::GestureFinished) { |
232 if (pinchG->state() == Qt::GestureFinished) { |
226 if(mStepCurrentSize != mCurrentSize) { |
|
227 //For giving a spring effect when user has zoomed more than normal. |
233 //For giving a spring effect when user has zoomed more than normal. |
228 if(mStepCurrentSize.width() > mMaxScaleDecSize.width()) { |
234 if(mStepCurrentSize.width() > mMaxScaleDecSize.width()) { |
229 //scale the image to limited size |
235 //scale the image to limited size |
230 qreal value = mMaxScaleDecSize.width()/mCurrentSize.width(); |
236 qreal value = mMaxScaleDecSize.width()/mCurrentSize.width(); |
231 QPointF center(mWindowSize.width()/2, mWindowSize.height()/2); |
237 QPointF center(mWindowSize.width()/2, mWindowSize.height()/2); |
292 } |
298 } |
293 |
299 |
294 //makes sure that the gesture is on the screen center if the image is smaller than the screen |
300 //makes sure that the gesture is on the screen center if the image is smaller than the screen |
295 void GlxZoomWidget::adjustGestureCenter(QPointF & gestureCenter, qreal& zoomFactor) |
301 void GlxZoomWidget::adjustGestureCenter(QPointF & gestureCenter, qreal& zoomFactor) |
296 { |
302 { |
297 /* commenting this tweak, not necessary, needs to be reimplemented for pinch: IN progress |
303 |
298 if(zoomFactor > 1 &&zoomFactor > 1.2 ) { |
304 //clip zoom factor for pinch zoom. Double tap zoomfactor should never exceed |
|
305 //1.2 or 0.8 in any given step |
|
306 /* if(zoomFactor > 1.2 ) { |
299 zoomFactor = 1.2; |
307 zoomFactor = 1.2; |
300 } |
308 } |
301 |
309 if(zoomFactor < 0.7 ) { |
302 if(zoomFactor < 1 &&zoomFactor < 0.8 ) { |
|
303 zoomFactor = 0.8; |
310 zoomFactor = 0.8; |
304 } |
311 }*/ |
305 */ |
312 |
306 QSizeF requiredSize(mCurrentSize.width()*zoomFactor, mCurrentSize.height()*zoomFactor); |
313 qDebug("AA::adjustGestureCenter::ZoomFactor (%f)",zoomFactor); |
307 //keep smaller image centered |
314 QPointF itemOriginPos = mZoomWidget->sceneTransform().map(QPointF(0,0)); |
308 if(mCurrentSize.width() <= mWindowSize.width() ) |
315 QPointF gesCenter = mZoomWidget->sceneTransform().map(gestureCenter); |
309 { |
316 |
|
317 |
|
318 //keep smaller image centered irrespective of zoomin or zoom out |
|
319 //note, only if the image is smaller than window size, else preserve the |
|
320 //gesture center. Adjustments need to be done for both height/width |
|
321 //only one of them will be applicable, unless the image is smaller than |
|
322 //fullscreen size on both dimensions |
|
323 if( (mCurrentSize.width() <= mWindowSize.width())) { |
|
324 //requires adjustment only in portrait orientation |
|
325 if(mWindowSize.width() > mWindowSize.height()) |
|
326 gestureCenter.setX(mWindowSize.width()/2); |
|
327 } |
|
328 //handle the case when CurrentSize is grater than window size |
|
329 //this applies to zoomout flow |
|
330 else { |
|
331 //when the image is positioned beyond the left edge of the window |
|
332 //clamp the image to left edge |
|
333 if(itemOriginPos.x() >= 0) { |
|
334 gestureCenter.setX(itemOriginPos.x()); |
|
335 } |
|
336 //same applies when the image needs clamping on right edge |
|
337 else if(itemOriginPos.x()+ mCurrentSize.width() <= mWindowSize.width()){ |
|
338 gestureCenter.setX(itemOriginPos.x() + mCurrentSize.width()); |
|
339 } |
|
340 //else no clamping is required, theg esture center can be preserved |
|
341 //as is for the zoom step |
|
342 } |
|
343 |
|
344 //same logic applied for Y axis |
|
345 if( (mCurrentSize.height() <= mWindowSize.height()) ) { |
|
346 //requires adjustment only in landscape orientation |
|
347 if(mWindowSize.width() < mWindowSize.height()) |
|
348 gestureCenter.setY(mWindowSize.height()/2); |
|
349 } |
|
350 else { |
|
351 if(itemOriginPos.y() >= 0) { |
|
352 gestureCenter.setY(itemOriginPos.y()); |
|
353 } |
|
354 else if(itemOriginPos.y()+ mCurrentSize.height() <= mWindowSize.height()){ |
|
355 gestureCenter.setY(itemOriginPos.y() + mCurrentSize.height()); |
|
356 } |
|
357 } |
|
358 |
|
359 //special case for images that are smaller on both sides |
|
360 //centering of the gesture is important to prevent movement of the image |
|
361 //while zoom in or out |
|
362 if( (mCurrentSize.height() <= mWindowSize.height()) && (mCurrentSize.width() <= mWindowSize.width()) ) { |
310 gestureCenter.setX(mWindowSize.width()/2); |
363 gestureCenter.setX(mWindowSize.width()/2); |
311 |
|
312 } |
|
313 if(mCurrentSize.height() <= mWindowSize.height()) |
|
314 { |
|
315 gestureCenter.setY(mWindowSize.height()/2); |
364 gestureCenter.setY(mWindowSize.height()/2); |
316 |
365 } |
317 } |
|
318 //maintains the boundary of the edges for zoom out conditions |
|
319 if(zoomFactor < 1) { |
|
320 QPointF itemOriginPos = mZoomWidget->sceneTransform().map(QPointF(0,0)); |
|
321 bool hasWidthExceededWindow = mCurrentSize.width() > mWindowSize.width(); |
|
322 bool hasHeightExceededWindow = mCurrentSize.height() > mWindowSize.height(); |
|
323 if(hasWidthExceededWindow) { |
|
324 bool hasItemCrossedBoundary = false; |
|
325 if(itemOriginPos.x() >= -5) { |
|
326 //image has crossed left boundry leaving blank space |
|
327 //stick the gesture to the left corner |
|
328 gestureCenter.setX(itemOriginPos.x()); |
|
329 hasItemCrossedBoundary = true; |
|
330 } |
|
331 |
366 |
332 //Check if the right boundry can be adjusted |
|
333 if(itemOriginPos.x()+ mCurrentSize.width() <= mWindowSize.width()+5) { |
|
334 //Image is before the right boundry leaving blank space |
|
335 gestureCenter.setX(itemOriginPos.x()+ mCurrentSize.width() ); |
|
336 hasItemCrossedBoundary = true; |
|
337 } |
|
338 if((mCurrentSize.width() - mWindowSize.width() <= 20) && !hasItemCrossedBoundary) { |
|
339 gestureCenter.setX(mWindowSize.width()/2 + (qAbs(itemOriginPos.x()) - 10)); |
|
340 } |
|
341 } |
|
342 |
|
343 if(hasHeightExceededWindow) { |
|
344 bool hasItemCrossedBoundary = false; |
|
345 //check if the upper boundry could be adjusted |
|
346 if(itemOriginPos.y() >= -5) { |
|
347 //image has crossed the upper boundry leaving blank space |
|
348 //stick the image to the upper boundry |
|
349 gestureCenter.setY(itemOriginPos.y()); |
|
350 hasItemCrossedBoundary = true; |
|
351 } |
|
352 //check if the lower boundry could be adjusted |
|
353 if(itemOriginPos.y()+ mCurrentSize.height() <= mWindowSize.height()+5) { |
|
354 //Image is before the right boundry leaving blank space |
|
355 //stick the image to the right corner |
|
356 gestureCenter.setY(itemOriginPos.y()+ mCurrentSize.height()); |
|
357 hasItemCrossedBoundary = true; |
|
358 } |
|
359 if((mCurrentSize.height() - mWindowSize.height() <= 20) && !hasItemCrossedBoundary) { |
|
360 gestureCenter.setY(mWindowSize.height()/2 + (qAbs(itemOriginPos.y()) - 10)); |
|
361 } |
|
362 } |
|
363 } |
|
364 //control the zoom Factor to boundaries |
|
365 if(mCurrentSize.width() > mWindowSize.width() && requiredSize.width() <= mWindowSize.width()) |
|
366 { |
|
367 zoomFactor = mWindowSize.width()/mCurrentSize.width(); |
|
368 |
|
369 } |
|
370 else if(mCurrentSize.height() > mWindowSize.height() && requiredSize.height() <= mWindowSize.height()) |
|
371 { |
|
372 zoomFactor = mWindowSize.height()/mCurrentSize.height(); |
|
373 |
|
374 } |
|
375 |
|
376 //reduce the ZF so as to show a decelerated effect at max/min levels |
367 //reduce the ZF so as to show a decelerated effect at max/min levels |
377 |
368 /* |
378 if(mCurrentSize.width() > mMaxScaleDecSize.width() && zoomFactor > 1 ) { |
369 if(mCurrentSize.width() > mMaxScaleDecSize.width() && zoomFactor > 1 ) { |
379 zoomFactor = 1.0 + ((zoomFactor-1.0)/6) ; |
370 zoomFactor = 1.0 + ((zoomFactor-1.0)/6) ; |
380 } |
371 } |
381 if(mCurrentSize.width() < mMinDecScaleSize.width() && zoomFactor < 1 ) { |
372 if(mCurrentSize.width() < mMinDecScaleSize.width() && zoomFactor < 1 ) { |
382 zoomFactor = 1.0 - ((1.0-zoomFactor)/6) ; |
373 zoomFactor = 1.0 - ((1.0-zoomFactor)/6) ; |
383 } |
374 } |
384 |
375 */ |
385 |
376 |
386 } |
377 } |
387 |
378 |
388 //get the latest focused image and set it to mZoomItem |
379 //get the latest focused image and set it to mZoomItem |
389 void GlxZoomWidget::retreiveFocusedImage() |
380 void GlxZoomWidget::retreiveFocusedImage() |
540 //show the black background |
532 //show the black background |
541 mBlackBackgroundItem->setParentItem(parentItem()); |
533 mBlackBackgroundItem->setParentItem(parentItem()); |
542 mBlackBackgroundItem->setZValue(mMaxZValue - 1); |
534 mBlackBackgroundItem->setZValue(mMaxZValue - 1); |
543 mBlackBackgroundItem->show(); |
535 mBlackBackgroundItem->show(); |
544 m_AnimRefPoint = animRefPoint; |
536 m_AnimRefPoint = animRefPoint; |
545 QSizeF requiredSize = mItemSize; |
537 QSizeF requiredSize = mMinDecScaleSize; |
546 //MAXDTZOOMIN size is set to 3.5 times window size |
538 //MAXDTZOOMIN size is set to 3.5 times window size |
547 requiredSize.scale(mWindowSize*MAXDTZOOMIN, Qt::KeepAspectRatio); |
539 requiredSize.scale(mWindowSize*MAXDTZOOMIN, Qt::KeepAspectRatio); |
548 m_FinalAnimatedScaleFactor = requiredSize.width()/mMinDecScaleSize.width(); |
540 m_FinalAnimatedScaleFactor = requiredSize.width()/mMinDecScaleSize.width(); |
549 //initiale variable for double tap animation |
541 //initiale variable for double tap animation |
550 mIncSF = 1; |
542 mIncSF = 1; |
551 //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor |
543 //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor |
552 //SF has to always greater than 1 for upscaling, hence range for zoomout is [1,m_FinalAnimatedScaleFactor] |
544 //SF has to always greater than 1 for upscaling, hence range for zoomout is [1,m_FinalAnimatedScaleFactor] |
553 msfInc = (m_FinalAnimatedScaleFactor-1)/NOOFSTEPS; |
545 msfInc = (m_FinalAnimatedScaleFactor-1)/(NOOFSTEPSZI); |
|
546 //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor |
|
547 minitSize = mCurrentSize; |
554 //set the no. of steps for double tap animation |
548 //set the no. of steps for double tap animation |
555 mdoubletapSteps = NOOFSTEPS; |
549 mdoubletapSteps = NOOFSTEPSZI; |
556 animateDoubleTap(); |
550 animateDoubleTap(); |
557 |
551 |
558 } |
552 } |
559 void GlxZoomWidget::animateZoomOut(QPointF animRefPoint) |
553 void GlxZoomWidget::animateZoomOut(QPointF animRefPoint) |
560 { |
554 { |
581 //calculate increamental scale factor based on the step and then calculate the applicable scale factor this step |
575 //calculate increamental scale factor based on the step and then calculate the applicable scale factor this step |
582 //increamental SF works on the ImageSize when double tap started, applicable(required) SF calculates the delate SF |
576 //increamental SF works on the ImageSize when double tap started, applicable(required) SF calculates the delate SF |
583 if(m_FinalAnimatedScaleFactor > 1) { |
577 if(m_FinalAnimatedScaleFactor > 1) { |
584 //AA::zoomin case |
578 //AA::zoomin case |
585 mIncSF += msfInc; |
579 mIncSF += msfInc; |
586 qreal reqSF = (mItemSize.width()*(mIncSF))/mCurrentSize.width(); |
580 qreal reqSF = (minitSize.width()*(mIncSF))/mCurrentSize.width(); |
587 zoomImage(reqSF, m_AnimRefPoint); |
581 zoomImage(reqSF, m_AnimRefPoint); |
588 } |
582 } |
589 if(m_FinalAnimatedScaleFactor < 1) { |
583 if(m_FinalAnimatedScaleFactor < 1) { |
590 //AA::zoomout case |
584 //AA::zoomout case |
591 mIncSF -= msfInc; |
585 mIncSF -= msfInc; |
592 qreal reqSF = (mzoSize.width()* mIncSF)/mCurrentSize.width(); |
586 qreal reqSF = (minitSize.width()* mIncSF)/mCurrentSize.width(); |
593 zoomImage(reqSF, m_AnimRefPoint); |
587 zoomImage(reqSF, m_AnimRefPoint); |
594 } |
588 } |
595 //check if all steps are done,if not emit signal to continue the animation |
589 //check if all steps are done,if not emit signal to continue the animation |
596 if(mdoubletapSteps >= 1 ){ |
590 if(mdoubletapSteps > 1 ){ |
597 mdoubletapSteps -= 1; |
591 mdoubletapSteps -= 1; |
598 emit stepZoom(); |
592 emit stepZoom(); |
599 } |
593 } |
600 else { |
594 else { |
601 //animation is complete, finalize the widget transform using setgeometry |
595 //animation is complete, finalize the widget transform using setgeometry |