|
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: glxzoomwidget.cpp |
|
15 * description of the class GlxGlxZoomWidget which controls the Zoom behavior of coverflow. |
|
16 * |
|
17 */ |
|
18 #include <QPinchGesture> |
|
19 #include <hbiconitem.h> |
|
20 #include <QTimeLine> |
|
21 #include <QGesture> |
|
22 #include <hbinstance.h> |
|
23 #include "glximagedecoderwrapper.h" |
|
24 #include "glxmodelparm.h" |
|
25 #include "glxzoomwidget.h" |
|
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 |
|
33 GlxZoomWidget::GlxZoomWidget(QGraphicsItem *parent):HbScrollArea(parent), |
|
34 mModel(NULL), mMinZValue(MINZVALUE), |
|
35 mMaxZValue(MAXZVALUE), mTimerId(0), |
|
36 mImageDecodeRequestSend(false), |
|
37 mPinchGestureOngoing(false), mDecodedImageAvailable(false), |
|
38 mZoomOngoing(false) |
|
39 { |
|
40 grabGesture(Qt::PinchGesture); |
|
41 grabGesture(Qt::TapGesture); |
|
42 setAcceptTouchEvents(true) ; |
|
43 setFrictionEnabled(true); |
|
44 setZValue(mMinZValue); |
|
45 //create the child items and background |
|
46 mZoomWidget = new QGraphicsWidget(this); |
|
47 mZoomItem = new QGraphicsPixmapItem(mZoomWidget); |
|
48 mZoomItem->setTransformationMode(Qt::SmoothTransformation); |
|
49 //the black background |
|
50 //replace when a proper substitute for setting backgrounds is known |
|
51 mBlackBackgroundItem = new HbIconItem(this); |
|
52 mBlackBackgroundItem->setBrush(QBrush(Qt::black)); |
|
53 mBlackBackgroundItem->hide(); |
|
54 //does not work so is commented |
|
55 //setBackgroundItem(mBlackBackgroundItem); |
|
56 |
|
57 //initializing the image decoder |
|
58 mImageDecoder = new GlxImageDecoderWrapper; |
|
59 |
|
60 setVerticalScrollBarPolicy(HbScrollArea::ScrollBarAlwaysOff); |
|
61 setHorizontalScrollBarPolicy(HbScrollArea::ScrollBarAlwaysOff); |
|
62 //AA: signal and slot to perform double tap animation |
|
63 //after every step redraw, signal is emitted to perform the next step |
|
64 connect( this, SIGNAL( stepZoom() ), this, SLOT( animateDoubleTap() ), Qt::QueuedConnection ); |
|
65 } |
|
66 |
|
67 GlxZoomWidget::~GlxZoomWidget() |
|
68 { |
|
69 //disconnect all existing signals |
|
70 disconnect(this,SIGNAL( pinchGestureReceived(int) ), this, SLOT( sendDecodeRequest(int) ) ); |
|
71 //AA |
|
72 disconnect( this, SIGNAL( stepZoom() ), this, SLOT( animateDoubleTap())); |
|
73 //no Null checks required |
|
74 delete mZoomItem; |
|
75 // delete mZoomWidget; //as this is a content widegt it will automatically be deleted |
|
76 delete mBlackBackgroundItem; |
|
77 //reset the decoder to cancel pending tasks |
|
78 if(mImageDecoder) { |
|
79 mImageDecoder->resetDecoder(); |
|
80 delete mImageDecoder; |
|
81 } |
|
82 } |
|
83 |
|
84 void GlxZoomWidget::setModel (QAbstractItemModel *model) |
|
85 { |
|
86 if(model) |
|
87 { |
|
88 mModel = model; |
|
89 retreiveFocusedImage(); //Update mZoomItem with focused Image |
|
90 connect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex) ), this, SLOT( dataChanged(QModelIndex,QModelIndex) ) ); |
|
91 connect( mModel, SIGNAL( destroyed() ), this, SLOT( modelDestroyed() ) ); |
|
92 } |
|
93 } |
|
94 |
|
95 void GlxZoomWidget::setWindowSize(QSize windowSize) |
|
96 { |
|
97 mWindowSize = windowSize; |
|
98 mBlackBackgroundItem->setGeometry(QRectF(QPointF(0,0), mWindowSize)); |
|
99 //try to reset the max and min zoomed size here |
|
100 //In case the zoom widget is in background reset it |
|
101 if(!mZoomOngoing && mModel) { |
|
102 retreiveFocusedImage(); |
|
103 } |
|
104 setZoomParams(); |
|
105 } |
|
106 |
|
107 void GlxZoomWidget::forceZoomToBackground() |
|
108 { |
|
109 mBlackBackgroundItem->hide(); |
|
110 //push the widget back to background |
|
111 setZValue(mMinZValue); |
|
112 mZoomOngoing = false; |
|
113 emit zoomWidgetMovedBackground(mFocusIndex); |
|
114 //this actually resets the ZoomWidget and decoder |
|
115 if(mImageDecoder) { |
|
116 mImageDecoder->resetDecoder(); |
|
117 } |
|
118 retreiveFocusedImage(); |
|
119 |
|
120 } |
|
121 |
|
122 void GlxZoomWidget::indexChanged(int index) |
|
123 { |
|
124 if(mFocusIndex != index) { |
|
125 mImageDecoder->resetDecoder();//reset the decoder first to cancel pending tasks |
|
126 mImageDecodeRequestSend = false; |
|
127 mDecodedImageAvailable = false; |
|
128 retreiveFocusedImage(); //Update mZoomItem with focused Image |
|
129 } |
|
130 } |
|
131 |
|
132 void GlxZoomWidget::cleanUp() |
|
133 { |
|
134 if(mModel) { |
|
135 disconnect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex) ), this, SLOT( dataChanged(QModelIndex,QModelIndex) ) ); |
|
136 disconnect( mModel, SIGNAL( destroyed() ), this, SLOT( modelDestroyed() ) ); |
|
137 mModel = NULL; |
|
138 } |
|
139 if(mImageDecoder) { |
|
140 mImageDecoder->resetDecoder(); |
|
141 } |
|
142 mZoomItem->setPixmap(QPixmap()); |
|
143 } |
|
144 |
|
145 void GlxZoomWidget::activate() |
|
146 { |
|
147 } |
|
148 |
|
149 void GlxZoomWidget::setMinMaxZValue(int minZvalue, int maxZvalue) |
|
150 { |
|
151 mMinZValue = minZvalue; |
|
152 mMaxZValue = maxZvalue; |
|
153 } |
|
154 |
|
155 void GlxZoomWidget::connectDecodeRequestToPinchEvent() |
|
156 { |
|
157 connect(this,SIGNAL( pinchGestureReceived(int) ), this, SLOT( sendDecodeRequest(int) ), Qt::QueuedConnection ); |
|
158 } |
|
159 |
|
160 bool GlxZoomWidget::sceneEvent(QEvent *event) |
|
161 { |
|
162 bool consume(false); |
|
163 if (event->type() == QEvent::Gesture) { |
|
164 consume = executeGestureEvent(this, static_cast<QGestureEvent*>(event)); |
|
165 } |
|
166 if(!consume) |
|
167 { |
|
168 consume = HbScrollArea::sceneEvent(event); |
|
169 } |
|
170 return consume; |
|
171 } |
|
172 |
|
173 bool GlxZoomWidget::sceneEventFilter(QGraphicsItem *watched,QEvent *event) |
|
174 { |
|
175 qDebug( "GlxZoomWidget::sceneEventFilter enter event type %d ", event->type() ); |
|
176 bool consume = false; |
|
177 if (event->type() == QEvent::Gesture) { |
|
178 consume = executeGestureEvent(watched, static_cast<QGestureEvent*>(event)); |
|
179 } |
|
180 |
|
181 if(!consume) { |
|
182 consume = HbScrollArea::sceneEventFilter(watched,event); |
|
183 } |
|
184 return consume; |
|
185 |
|
186 } |
|
187 |
|
188 bool GlxZoomWidget::executeGestureEvent(QGraphicsItem *source,QGestureEvent *event) |
|
189 { |
|
190 if(QTapGesture *gesture = static_cast<QTapGesture *>(event->gesture(Qt::TapGesture))) { |
|
191 if (gesture->state() == Qt::GestureFinished) { |
|
192 if(!mTimerId) { |
|
193 mTimerId = startTimer( DOUBLETAP_TIMEINTERVAL ); |
|
194 } |
|
195 else { |
|
196 killTimer(mTimerId); |
|
197 mTimerId = 0; |
|
198 animateZoomOut(hbInstance->allMainWindows().first()->mapToScene(gesture->position().toPoint())); |
|
199 } |
|
200 } |
|
201 event->accept(gesture); |
|
202 return true; |
|
203 } |
|
204 if (QGesture *pinch = event->gesture(Qt::PinchGesture)) { |
|
205 if (isFocussedItemCorrupt()){ |
|
206 return true; |
|
207 } |
|
208 QPinchGesture* pinchG = static_cast<QPinchGesture *>(pinch); |
|
209 QPinchGesture::ChangeFlags changeFlags = pinchG->changeFlags(); |
|
210 if (changeFlags & QPinchGesture::ScaleFactorChanged) { |
|
211 mPinchGestureOngoing = true; |
|
212 mZoomOngoing = true; |
|
213 |
|
214 //retreive the gesture values |
|
215 qreal value = pinchG->scaleFactor() / pinchG->lastScaleFactor(); |
|
216 QPointF center = pinchG->property("centerPoint").toPointF(); |
|
217 //set the gesture center to the scene coordinates |
|
218 QPointF sceneGestureCenter = hbInstance->allMainWindows().first()->mapToScene(center.toPoint()); |
|
219 zoomImage(value, sceneGestureCenter); |
|
220 |
|
221 } |
|
222 if (pinchG->state() == Qt::GestureStarted) { |
|
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(); |
|
230 } |
|
231 |
|
232 if (pinchG->state() == Qt::GestureFinished) { |
|
233 //For giving a spring effect when user has zoomed more than normal. |
|
234 if(mStepCurrentSize.width() > mMaxScaleDecSize.width()) { |
|
235 //scale the image to limited size |
|
236 qreal value = mMaxScaleDecSize.width()/mCurrentSize.width(); |
|
237 QPointF center(mWindowSize.width()/2, mWindowSize.height()/2); |
|
238 QPointF sceneGestureCenter = source->sceneTransform().map(center); |
|
239 zoomImage(value, sceneGestureCenter); |
|
240 } |
|
241 mPinchGestureOngoing = false; |
|
242 //finalize the transforms to the geometry else panning will not work |
|
243 finalizeWidgetTransform(); |
|
244 |
|
245 //push the Zoom widget to background when zoomed image size nears FS image |
|
246 if(mStepCurrentSize.width() <= mMinDecScaleSize.width()*1.3) { |
|
247 mBlackBackgroundItem->hide(); |
|
248 //push the widget back to background |
|
249 setZValue(mMinZValue); |
|
250 mZoomOngoing = false; |
|
251 emit zoomWidgetMovedBackground(mFocusIndex); |
|
252 //do not reset the transform here as it will then zoom-in the widget to decoded image size |
|
253 } |
|
254 } |
|
255 //gesture accepted |
|
256 return true; |
|
257 } |
|
258 //gesture rejected |
|
259 if(!mPinchGestureOngoing) { |
|
260 return false; |
|
261 } |
|
262 return true; |
|
263 |
|
264 } |
|
265 |
|
266 void GlxZoomWidget::zoomImage(qreal zoomFactor, QPointF center) |
|
267 { |
|
268 // Pinch event filtering for very small zoom factors |
|
269 if (qAbs(1.0 - zoomFactor) < 0.007) { |
|
270 return; |
|
271 } |
|
272 adjustGestureCenter(center, zoomFactor); |
|
273 QSizeF requiredSize(mCurrentSize.width()*zoomFactor, mCurrentSize.height()*zoomFactor); |
|
274 limitRequiredSize(requiredSize); |
|
275 if(requiredSize != mCurrentSize) { |
|
276 QTransform zoomTransform = mZoomWidget->transform(); |
|
277 QPointF transformedCenter = mZoomWidget->sceneTransform().inverted().map(center); |
|
278 zoomTransform.translate(transformedCenter.x(),transformedCenter.y()); |
|
279 zoomTransform.scale(requiredSize.width()/mCurrentSize.width(), requiredSize.height()/mCurrentSize.height()); |
|
280 zoomTransform.translate(-transformedCenter.x(),-transformedCenter.y()); |
|
281 mZoomWidget->setTransform(zoomTransform); |
|
282 mCurrentSize = requiredSize; |
|
283 } |
|
284 |
|
285 } |
|
286 |
|
287 |
|
288 void GlxZoomWidget::limitRequiredSize(QSizeF &requiredSize) |
|
289 { |
|
290 if(requiredSize.width() > mMaxScaleSize.width() ) { |
|
291 requiredSize = mMaxScaleSize ; |
|
292 } |
|
293 else if(requiredSize.width() < mMinDecScaleSize.width() ) { |
|
294 requiredSize = mMinDecScaleSize ; |
|
295 } |
|
296 |
|
297 |
|
298 } |
|
299 |
|
300 //makes sure that the gesture is on the screen center if the image is smaller than the screen |
|
301 void GlxZoomWidget::adjustGestureCenter(QPointF & gestureCenter, qreal& zoomFactor) |
|
302 { |
|
303 |
|
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 ) { |
|
307 zoomFactor = 1.2; |
|
308 } |
|
309 if(zoomFactor < 0.7 ) { |
|
310 zoomFactor = 0.8; |
|
311 }*/ |
|
312 |
|
313 qDebug("AA::adjustGestureCenter::ZoomFactor (%f)",zoomFactor); |
|
314 QPointF itemOriginPos = mZoomWidget->sceneTransform().map(QPointF(0,0)); |
|
315 QPointF gesCenter = mZoomWidget->sceneTransform().map(gestureCenter); |
|
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()) ) { |
|
363 gestureCenter.setX(mWindowSize.width()/2); |
|
364 gestureCenter.setY(mWindowSize.height()/2); |
|
365 } |
|
366 |
|
367 //reduce the ZF so as to show a decelerated effect at max/min levels |
|
368 /* |
|
369 if(mCurrentSize.width() > mMaxScaleDecSize.width() && zoomFactor > 1 ) { |
|
370 zoomFactor = 1.0 + ((zoomFactor-1.0)/6) ; |
|
371 } |
|
372 if(mCurrentSize.width() < mMinDecScaleSize.width() && zoomFactor < 1 ) { |
|
373 zoomFactor = 1.0 - ((1.0-zoomFactor)/6) ; |
|
374 } |
|
375 */ |
|
376 |
|
377 } |
|
378 |
|
379 //get the latest focused image and set it to mZoomItem |
|
380 void GlxZoomWidget::retreiveFocusedImage() |
|
381 { |
|
382 |
|
383 QPixmap targetPixmap(getFocusedImage()); |
|
384 //initialize all the variables wrt the focussed pixmap |
|
385 mZoomWidget->resetTransform(); |
|
386 mItemSize = targetPixmap.size(); |
|
387 mMaxScaleSize = mItemSize; |
|
388 mMaxScaleSize.scale(mWindowSize*13, Qt::KeepAspectRatio); |
|
389 mMaxScaleDecSize = mItemSize; |
|
390 mMaxScaleDecSize.scale(mWindowSize*7, Qt::KeepAspectRatio); |
|
391 mMinScaleSize = mItemSize* 0.7; |
|
392 mMinDecScaleSize = mItemSize; |
|
393 QPointF originPos = sceneTransform().map(QPointF(0,0)); |
|
394 mZoomWidget->setGeometry(QRectF(QPointF(mWindowSize.width()/2 - mItemSize.width()/2,mWindowSize.height()/2 - mItemSize.height()/2),mItemSize )); //chk this |
|
395 mZoomWidget->setPreferredSize(mItemSize); |
|
396 mZoomItem->setPixmap(targetPixmap); |
|
397 mCurrentSize = mItemSize; |
|
398 mStepCurrentSize = mItemSize; |
|
399 setContentWidget(mZoomWidget); |
|
400 show(); |
|
401 } |
|
402 |
|
403 |
|
404 void GlxZoomWidget::dataChanged(QModelIndex startIndex, QModelIndex endIndex) |
|
405 { |
|
406 if(mFocusIndex >= startIndex.row() && mFocusIndex <= endIndex.row()) { |
|
407 //get the latest image from the model |
|
408 //will replace a decoded image if callback is received after decoded image is received so a fix is required |
|
409 //retreiveFocusedImage(); |
|
410 if(!mDecodedImageAvailable) { |
|
411 QPixmap targetPixmap(getFocusedImage()); |
|
412 mItemSize = targetPixmap.size(); |
|
413 mMaxScaleSize = mItemSize; |
|
414 mMaxScaleSize.scale(mWindowSize*13, Qt::KeepAspectRatio); |
|
415 mMaxScaleDecSize = mItemSize; |
|
416 mMaxScaleDecSize.scale(mWindowSize*7, Qt::KeepAspectRatio); |
|
417 mMinScaleSize = mItemSize* 0.7; |
|
418 mMinDecScaleSize = mItemSize; |
|
419 mCurrentSize = mItemSize; |
|
420 mZoomItem->setPixmap(targetPixmap); |
|
421 finalizeWidgetTransform(); |
|
422 } |
|
423 } |
|
424 } |
|
425 |
|
426 void GlxZoomWidget::modelDestroyed() |
|
427 { |
|
428 mModel = NULL ; |
|
429 } |
|
430 |
|
431 void GlxZoomWidget::indexChanged() |
|
432 { |
|
433 retreiveFocusedImage(); |
|
434 } |
|
435 |
|
436 void GlxZoomWidget::decodedImageAvailable() |
|
437 { |
|
438 //new bitmap with better resolution is available |
|
439 //so set it to the item |
|
440 QPixmap decodedPixmap = mImageDecoder->getPixmap(); |
|
441 disconnect(mImageDecoder, SIGNAL(pixmapDecoded()), this, SLOT(decodedImageAvailable())); |
|
442 if(decodedPixmap.isNull()){ |
|
443 return; |
|
444 } |
|
445 mDecodedImageAvailable = true; |
|
446 mZoomItem->setPixmap(decodedPixmap); |
|
447 mItemSize = decodedPixmap.size(); |
|
448 //this is important if not done then old transforms will be applied on the new image |
|
449 finalizeWidgetTransform(); |
|
450 } |
|
451 |
|
452 void GlxZoomWidget::sendDecodeRequest(int index) |
|
453 { |
|
454 if(!mImageDecodeRequestSend) { |
|
455 QString imagePath = (mModel->data(mModel->index(index,0),GlxUriRole)).value<QString>(); |
|
456 mImageDecoder->decodeImage(imagePath); |
|
457 connect(mImageDecoder, SIGNAL(pixmapDecoded()), this, SLOT(decodedImageAvailable())); |
|
458 mImageDecodeRequestSend = true; |
|
459 } |
|
460 } |
|
461 |
|
462 |
|
463 void GlxZoomWidget::finalizeWidgetTransform() |
|
464 { |
|
465 QPointF widgetPos = mZoomWidget->sceneTransform().map(QPointF(0,0)); //Map the origin wrt scene |
|
466 mZoomWidget->resetTransform(); |
|
467 mZoomWidget->scale(mCurrentSize.width()/mItemSize.width(), mCurrentSize.height()/mItemSize.height()); |
|
468 mZoomWidget->setGeometry(QRectF(widgetPos , mCurrentSize)); |
|
469 // this updates HbScrollArea on the sizeHint of ZoomWidget |
|
470 mZoomWidget->setPreferredSize(mCurrentSize); |
|
471 mStepCurrentSize = mCurrentSize; |
|
472 } |
|
473 |
|
474 QPixmap GlxZoomWidget::getFocusedImage() |
|
475 { |
|
476 mFocusIndex = mModel->data(mModel->index(0,0),GlxFocusIndexRole).value<int>(); |
|
477 QVariant iconVariant = mModel->data(mModel->index(mFocusIndex,0),GlxFsImageRole); |
|
478 QVariant sizeVariant = mModel->data(mModel->index(mFocusIndex,0),GlxDimensionsRole); |
|
479 QPixmap targetPixmap; |
|
480 //retreive pixmap from the HbIcon received from model |
|
481 //should change the model to return and save pixmaps and convert to HbIcons Instead |
|
482 if ( iconVariant.isValid() && iconVariant.canConvert<HbIcon> () ) { |
|
483 QIcon itemIcon = iconVariant.value<HbIcon>().qicon(); |
|
484 QSize itemSize = itemIcon.actualSize(mWindowSize); |
|
485 QSize scaleSize; |
|
486 if(sizeVariant.isValid() && sizeVariant.canConvert<QSize> ()) { |
|
487 scaleSize = sizeVariant.toSize(); |
|
488 if(!(scaleSize.width() < mWindowSize.width() && scaleSize.height() < mWindowSize.height())) { |
|
489 scaleSize = mWindowSize; |
|
490 } |
|
491 } |
|
492 targetPixmap = itemIcon.pixmap(itemSize).scaled(scaleSize, Qt::KeepAspectRatio); |
|
493 mItemSize = targetPixmap.size(); |
|
494 } |
|
495 return targetPixmap; |
|
496 |
|
497 } |
|
498 |
|
499 void GlxZoomWidget::setZoomParams() |
|
500 { |
|
501 if (mModel) { |
|
502 QVariant sizeVariant = mModel->data(mModel->index(mFocusIndex,0),GlxDimensionsRole); |
|
503 QSize fsSize; |
|
504 if(sizeVariant.isValid() && sizeVariant.canConvert<QSize> ()) { |
|
505 fsSize = sizeVariant.toSize(); |
|
506 if(!(fsSize.width() < mWindowSize.width() && fsSize.height() < mWindowSize.height())) { |
|
507 fsSize.scale( mWindowSize, Qt::KeepAspectRatio); |
|
508 } |
|
509 mMaxScaleSize = fsSize; |
|
510 mMaxScaleSize.scale(mWindowSize*13, Qt::KeepAspectRatio); |
|
511 mMaxScaleDecSize = fsSize; |
|
512 mMaxScaleDecSize.scale(mWindowSize*7, Qt::KeepAspectRatio); |
|
513 mMinScaleSize = fsSize* 0.7; |
|
514 mMinDecScaleSize = fsSize; |
|
515 } |
|
516 } |
|
517 |
|
518 |
|
519 } |
|
520 |
|
521 |
|
522 |
|
523 void GlxZoomWidget::animateZoomIn(QPointF animRefPoint) |
|
524 { |
|
525 if (isFocussedItemCorrupt()){ |
|
526 return; |
|
527 } |
|
528 emit pinchGestureReceived(mFocusIndex); |
|
529 //bring the zoom widget to foreground |
|
530 mZoomOngoing = true; |
|
531 setZValue(mMaxZValue); |
|
532 //show the black background |
|
533 mBlackBackgroundItem->setParentItem(parentItem()); |
|
534 mBlackBackgroundItem->setZValue(mMaxZValue - 1); |
|
535 mBlackBackgroundItem->show(); |
|
536 m_AnimRefPoint = animRefPoint; |
|
537 QSizeF requiredSize = mMinDecScaleSize; |
|
538 //MAXDTZOOMIN size is set to 3.5 times window size |
|
539 requiredSize.scale(mWindowSize*MAXDTZOOMIN, Qt::KeepAspectRatio); |
|
540 m_FinalAnimatedScaleFactor = requiredSize.width()/mMinDecScaleSize.width(); |
|
541 //initiale variable for double tap animation |
|
542 mIncSF = 1; |
|
543 //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor |
|
544 //SF has to always greater than 1 for upscaling, hence range for zoomout is [1,m_FinalAnimatedScaleFactor] |
|
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; |
|
548 //set the no. of steps for double tap animation |
|
549 mdoubletapSteps = NOOFSTEPSZI; |
|
550 animateDoubleTap(); |
|
551 |
|
552 } |
|
553 void GlxZoomWidget::animateZoomOut(QPointF animRefPoint) |
|
554 { |
|
555 m_AnimRefPoint = animRefPoint; |
|
556 //Zoom out to FS (mMinDecScaleSize) from the currentsize |
|
557 m_FinalAnimatedScaleFactor = mMinDecScaleSize.width()/mCurrentSize.width(); |
|
558 //initiale variable for double tap animation |
|
559 mIncSF = 1; |
|
560 //calculate the step increment SF for each step |
|
561 msfInc = (1 - m_FinalAnimatedScaleFactor)/(NOOFSTEPSZO); |
|
562 //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor |
|
563 minitSize = mCurrentSize; |
|
564 //set the no. of steps for double tap animation |
|
565 //AA:: the no.of steps are kept the same for zoomin/zoomout, however tweaking them can be considered |
|
566 mdoubletapSteps = NOOFSTEPSZO; |
|
567 animateDoubleTap(); |
|
568 //AA |
|
569 |
|
570 } |
|
571 |
|
572 |
|
573 void GlxZoomWidget::animateDoubleTap() |
|
574 { |
|
575 //calculate increamental scale factor based on the step and then calculate the applicable scale factor this step |
|
576 //increamental SF works on the ImageSize when double tap started, applicable(required) SF calculates the delate SF |
|
577 if(m_FinalAnimatedScaleFactor > 1) { |
|
578 //AA::zoomin case |
|
579 mIncSF += msfInc; |
|
580 qreal reqSF = (minitSize.width()*(mIncSF))/mCurrentSize.width(); |
|
581 zoomImage(reqSF, m_AnimRefPoint); |
|
582 } |
|
583 if(m_FinalAnimatedScaleFactor < 1) { |
|
584 //AA::zoomout case |
|
585 mIncSF -= msfInc; |
|
586 qreal reqSF = (minitSize.width()* mIncSF)/mCurrentSize.width(); |
|
587 zoomImage(reqSF, m_AnimRefPoint); |
|
588 } |
|
589 //check if all steps are done,if not emit signal to continue the animation |
|
590 if(mdoubletapSteps > 1 ){ |
|
591 mdoubletapSteps -= 1; |
|
592 emit stepZoom(); |
|
593 } |
|
594 else { |
|
595 //animation is complete, finalize the widget transform using setgeometry |
|
596 //reset the counter |
|
597 mdoubletapSteps = 0; |
|
598 animationTimeLineFinished(); |
|
599 } |
|
600 |
|
601 } |
|
602 void GlxZoomWidget::animationTimeLineFinished() |
|
603 { |
|
604 finalizeWidgetTransform(); |
|
605 //push the Zoom widget to background when zoomed image size nears FS image |
|
606 if(mStepCurrentSize.width() <= mMinDecScaleSize.width()*1.3) { |
|
607 mBlackBackgroundItem->hide(); |
|
608 //push the widget back to background |
|
609 setZValue(mMinZValue); |
|
610 mZoomOngoing = false; |
|
611 emit zoomWidgetMovedBackground(mFocusIndex); |
|
612 //do not reset the transform here as it will then zoom-in the widget to decoded image size |
|
613 } |
|
614 } |
|
615 |
|
616 |
|
617 void GlxZoomWidget::timerEvent(QTimerEvent *event) |
|
618 { |
|
619 if(mTimerId == event->timerId()) |
|
620 { |
|
621 killTimer(mTimerId); |
|
622 mTimerId = 0; |
|
623 } |
|
624 else { |
|
625 HbScrollArea::timerEvent( event ); |
|
626 } |
|
627 } |
|
628 |
|
629 bool GlxZoomWidget::isFocussedItemCorrupt() |
|
630 { |
|
631 QVariant variant = mModel->data( mModel->index( mFocusIndex, 0 ), GlxImageCorruptRole ); |
|
632 if ( variant.isValid() && variant.canConvert< bool> () ) { |
|
633 return variant.value< bool > () ; |
|
634 } |
|
635 return false ; |
|
636 } |
|
637 |