--- a/ui/widgets/glxzoomwidget/src/glxzoomwidget.cpp Tue Jul 06 14:16:16 2010 +0300
+++ b/ui/widgets/glxzoomwidget/src/glxzoomwidget.cpp Wed Aug 18 09:48:53 2010 +0300
@@ -19,11 +19,17 @@
#include <hbiconitem.h>
#include <QTimeLine>
#include <QGesture>
+#include <hbinstance.h>
#include "glximagedecoderwrapper.h"
#include "glxmodelparm.h"
#include "glxzoomwidget.h"
-GlxZoomWidget::GlxZoomWidget(QGraphicsItem *parent):HbScrollArea(parent), mModel(NULL), mMinZValue(MINZVALUE), mMaxZValue(MAXZVALUE), mImageDecodeRequestSend(false), mPinchGestureOngoing(false), mDecodedImageAvailable(false), mTimerId(0)
+GlxZoomWidget::GlxZoomWidget(QGraphicsItem *parent):HbScrollArea(parent),
+ mModel(NULL), mMinZValue(MINZVALUE),
+ mMaxZValue(MAXZVALUE), mTimerId(0),
+ mImageDecodeRequestSend(false),
+ mPinchGestureOngoing(false), mDecodedImageAvailable(false),
+ mZoomOngoing(false)
{
grabGesture(Qt::PinchGesture);
grabGesture(Qt::TapGesture);
@@ -45,17 +51,18 @@
//initializing the image decoder
mImageDecoder = new GlxImageDecoderWrapper;
- //inititalizing the timer for animation
- m_AnimTimeLine = new QTimeLine(500, this);
- m_AnimTimeLine->setFrameRange(0, 100);
- connect(m_AnimTimeLine, SIGNAL(frameChanged(int)), this, SLOT(animationFrameChanged(int)));
- connect(m_AnimTimeLine, SIGNAL(finished()), this, SLOT(animationTimeLineFinished()));
+
+ //AA: signal and slot to perform double tap animation
+ //after every step redraw, signal is emitted to perform the next step
+ connect( this, SIGNAL( stepZoom() ), this, SLOT( animateDoubleTap() ), Qt::QueuedConnection );
}
GlxZoomWidget::~GlxZoomWidget()
{
//disconnect all existing signals
disconnect(this,SIGNAL( pinchGestureReceived(int) ), this, SLOT( sendDecodeRequest(int) ) );
+ //AA
+ disconnect( this, SIGNAL( stepZoom() ), this, SLOT( animateDoubleTap()));
//no Null checks required
delete mZoomItem;
// delete mZoomWidget; //as this is a content widegt it will automatically be deleted
@@ -83,11 +90,30 @@
mWindowSize = windowSize;
mBlackBackgroundItem->setGeometry(QRectF(QPointF(0,0), mWindowSize));
//try to reset the max and min zoomed size here
+ //In case the zoom widget is in background reset it
+ if(!mZoomOngoing && mModel) {
+ retreiveFocusedImage();
+ }
+ setZoomParams();
+}
+
+void GlxZoomWidget::forceZoomToBackground()
+{
+ mBlackBackgroundItem->hide();
+ //push the widget back to background
+ setZValue(mMinZValue);
+ mZoomOngoing = false;
+ emit zoomWidgetMovedBackground(mFocusIndex);
+ //this actually resets the ZoomWidget and decoder
+ if(mImageDecoder) {
+ mImageDecoder->resetDecoder();
+ }
+ retreiveFocusedImage();
+
}
void GlxZoomWidget::indexChanged(int index)
{
- Q_UNUSED(index);
if(mFocusIndex != index) {
mImageDecoder->resetDecoder();//reset the decoder first to cancel pending tasks
mImageDecodeRequestSend = false;
@@ -139,7 +165,7 @@
bool GlxZoomWidget::sceneEventFilter(QGraphicsItem *watched,QEvent *event)
{
- qDebug("GlxCoverFlow::eventFilter " );
+ qDebug( "GlxZoomWidget::sceneEventFilter enter event type %d ", event->type() );
bool consume = false;
if (event->type() == QEvent::Gesture) {
consume = executeGestureEvent(watched, static_cast<QGestureEvent*>(event));
@@ -162,17 +188,21 @@
else {
killTimer(mTimerId);
mTimerId = 0;
- animateZoomOut(gesture->position());
+ animateZoomOut(hbInstance->allMainWindows().first()->mapToScene(gesture->position().toPoint()));
}
}
event->accept(gesture);
return true;
}
if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
+ if (isFocussedItemCorrupt()){
+ return true;
+ }
QPinchGesture* pinchG = static_cast<QPinchGesture *>(pinch);
QPinchGesture::ChangeFlags changeFlags = pinchG->changeFlags();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
mPinchGestureOngoing = true;
+ mZoomOngoing = true;
//bring the zoom widget to foreground
setZValue(mMaxZValue);
//show the black background
@@ -184,7 +214,7 @@
qreal value = pinchG->scaleFactor() / pinchG->lastScaleFactor();
QPointF center = pinchG->property("centerPoint").toPointF();
//set the gesture center to the scene coordinates
- QPointF sceneGestureCenter = source->sceneTransform().map(center);
+ QPointF sceneGestureCenter = hbInstance->allMainWindows().first()->mapToScene(center.toPoint());
zoomImage(value, sceneGestureCenter);
}
@@ -211,6 +241,7 @@
mBlackBackgroundItem->hide();
//push the widget back to background
setZValue(mMinZValue);
+ mZoomOngoing = false;
emit zoomWidgetMovedBackground(mFocusIndex);
//do not reset the transform here as it will then zoom-in the widget to decoded image size
}
@@ -228,6 +259,10 @@
void GlxZoomWidget::zoomImage(qreal zoomFactor, QPointF center)
{
+ // Pinch event filtering for very small zoom factors
+ if (qAbs(1.0 - zoomFactor) < 0.007) {
+ return;
+ }
adjustGestureCenter(center, zoomFactor);
QSizeF requiredSize(mCurrentSize.width()*zoomFactor, mCurrentSize.height()*zoomFactor);
limitRequiredSize(requiredSize);
@@ -259,6 +294,7 @@
//makes sure that the gesture is on the screen center if the image is smaller than the screen
void GlxZoomWidget::adjustGestureCenter(QPointF & gestureCenter, qreal& zoomFactor)
{
+ /* commenting this tweak, not necessary, needs to be reimplemented for pinch: IN progress
if(zoomFactor > 1 &&zoomFactor > 1.2 ) {
zoomFactor = 1.2;
}
@@ -266,6 +302,7 @@
if(zoomFactor < 1 &&zoomFactor < 0.8 ) {
zoomFactor = 0.8;
}
+ */
QSizeF requiredSize(mCurrentSize.width()*zoomFactor, mCurrentSize.height()*zoomFactor);
//keep smaller image centered
if(mCurrentSize.width() <= mWindowSize.width() )
@@ -279,42 +316,49 @@
}
//maintains the boundary of the edges for zoom out conditions
- if(zoomFactor < 1)
- {
+ if(zoomFactor < 1) {
QPointF itemOriginPos = mZoomWidget->sceneTransform().map(QPointF(0,0));
bool hasWidthExceededWindow = mCurrentSize.width() > mWindowSize.width();
bool hasHeightExceededWindow = mCurrentSize.height() > mWindowSize.height();
- if(itemOriginPos.x() >= 0) {
- //image has crossed left boundry leaving blank space
- if(hasWidthExceededWindow) {
+ if(hasWidthExceededWindow) {
+ bool hasItemCrossedBoundary = false;
+ if(itemOriginPos.x() >= -5) {
+ //image has crossed left boundry leaving blank space
//stick the gesture to the left corner
gestureCenter.setX(itemOriginPos.x());
+ hasItemCrossedBoundary = true;
+ }
+
+ //Check if the right boundry can be adjusted
+ if(itemOriginPos.x()+ mCurrentSize.width() <= mWindowSize.width()+5) {
+ //Image is before the right boundry leaving blank space
+ gestureCenter.setX(itemOriginPos.x()+ mCurrentSize.width() );
+ hasItemCrossedBoundary = true;
+ }
+ if((mCurrentSize.width() - mWindowSize.width() <= 20) && !hasItemCrossedBoundary) {
+ gestureCenter.setX(mWindowSize.width()/2 + (qAbs(itemOriginPos.x()) - 10));
}
}
- //Check if the right boundry can be adjusted
- if(itemOriginPos.x()+ mCurrentSize.width() <= mWindowSize.width()) {
+
+ if(hasHeightExceededWindow) {
+ bool hasItemCrossedBoundary = false;
+ //check if the upper boundry could be adjusted
+ if(itemOriginPos.y() >= -5) {
+ //image has crossed the upper boundry leaving blank space
+ //stick the image to the upper boundry
+ gestureCenter.setY(itemOriginPos.y());
+ hasItemCrossedBoundary = true;
+ }
+ //check if the lower boundry could be adjusted
+ if(itemOriginPos.y()+ mCurrentSize.height() <= mWindowSize.height()+5) {
//Image is before the right boundry leaving blank space
- if(hasWidthExceededWindow) {
- //stick the gesture to the right corner
- gestureCenter.setX(itemOriginPos.x()+ mCurrentSize.width());
- }
- }
- //check if the upper boundry could be adjusted
- if(itemOriginPos.y() >= 0) {
- //image has crossed the upper boundry leaving blank space
- if(hasHeightExceededWindow) {
- //stick the image to the upper boundry
- gestureCenter.setY(itemOriginPos.y());
- }
- }
- //check if the lower boundry could be adjusted
- if(itemOriginPos.y()+ mCurrentSize.height() <= mWindowSize.height()) {
- //Image is before the right boundry leaving blank space
- if(hasHeightExceededWindow) {
//stick the image to the right corner
gestureCenter.setY(itemOriginPos.y()+ mCurrentSize.height());
+ hasItemCrossedBoundary = true;
}
-
+ if((mCurrentSize.height() - mWindowSize.height() <= 20) && !hasItemCrossedBoundary) {
+ gestureCenter.setY(mWindowSize.height()/2 + (qAbs(itemOriginPos.y()) - 10));
+ }
}
}
//control the zoom Factor to boundaries
@@ -460,48 +504,107 @@
}
+void GlxZoomWidget::setZoomParams()
+{
+ if (mModel) {
+ QVariant sizeVariant = mModel->data(mModel->index(mFocusIndex,0),GlxDimensionsRole);
+ QSize fsSize;
+ if(sizeVariant.isValid() && sizeVariant.canConvert<QSize> ()) {
+ fsSize = sizeVariant.toSize();
+ if(!(fsSize.width() < mWindowSize.width() && fsSize.height() < mWindowSize.height())) {
+ fsSize.scale( mWindowSize, Qt::KeepAspectRatio);
+ }
+ mMaxScaleSize = fsSize;
+ mMaxScaleSize.scale(mWindowSize*13, Qt::KeepAspectRatio);
+ mMaxScaleDecSize = fsSize;
+ mMaxScaleDecSize.scale(mWindowSize*7, Qt::KeepAspectRatio);
+ mMinScaleSize = fsSize* 0.7;
+ mMinDecScaleSize = fsSize;
+ }
+ }
+}
+
void GlxZoomWidget::animateZoomIn(QPointF animRefPoint)
{
- emit pinchGestureReceived(mFocusIndex);
- //bring the zoom widget to foreground
- setZValue(mMaxZValue);
- //show the black background
- mBlackBackgroundItem->setParentItem(parentItem());
- mBlackBackgroundItem->setZValue(mMaxZValue - 1);
- mBlackBackgroundItem->show();
- m_AnimRefPoint = animRefPoint;
+ if (isFocussedItemCorrupt()){
+ return;
+ }
+ emit pinchGestureReceived(mFocusIndex);
+ //bring the zoom widget to foreground
+ mZoomOngoing = true;
+ setZValue(mMaxZValue);
+ //show the black background
+ mBlackBackgroundItem->setParentItem(parentItem());
+ mBlackBackgroundItem->setZValue(mMaxZValue - 1);
+ mBlackBackgroundItem->show();
+ m_AnimRefPoint = animRefPoint;
QSizeF requiredSize = mItemSize;
- requiredSize.scale(mWindowSize*3.5, Qt::KeepAspectRatio);
+ //MAXDTZOOMIN size is set to 3.5 times window size
+ requiredSize.scale(mWindowSize*MAXDTZOOMIN, Qt::KeepAspectRatio);
m_FinalAnimatedScaleFactor = requiredSize.width()/mMinDecScaleSize.width();
- m_AnimTimeLine->setDirection(QTimeLine::Forward);
- m_AnimTimeLine->start();
- // zoomImage(5, m_AnimRefPoint);
+ //initiale variable for double tap animation
+ mIncSF = 1;
+ //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor
+ //SF has to always greater than 1 for upscaling, hence range for zoomout is [1,m_FinalAnimatedScaleFactor]
+ msfInc = (m_FinalAnimatedScaleFactor-1)/NOOFSTEPS;
+ //set the no. of steps for double tap animation
+ mdoubletapSteps = NOOFSTEPS;
+ animateDoubleTap();
}
void GlxZoomWidget::animateZoomOut(QPointF animRefPoint)
{
- m_AnimRefPoint = animRefPoint;
- m_FinalAnimatedScaleFactor = mMinDecScaleSize.width()/mCurrentSize.width();
- //m_AnimTimeLine->setDirection(QTimeLine::Backward);
- m_AnimTimeLine->start();
+ m_AnimRefPoint = animRefPoint;
+ //Zoom out to FS (mMinDecScaleSize) from the currentsize
+ m_FinalAnimatedScaleFactor = mMinDecScaleSize.width()/mCurrentSize.width();
+ //initiale variable for double tap animation
+ mIncSF = 1;
+ //calculate the step increment SF for each step
+ msfInc = (1 - m_FinalAnimatedScaleFactor)/NOOFSTEPS;
+ //preserve the size when zoom out was initiated, requried for calculates applicable/req scale factor
+ mzoSize = mCurrentSize;
+ //set the no. of steps for double tap animation
+ //AA:: the no.of steps are kept the same for zoomin/zoomout, however tweaking them can be considered
+ mdoubletapSteps = NOOFSTEPS;
+ animateDoubleTap();
+ //AA
+
}
-void GlxZoomWidget::animationFrameChanged(int frameNumber)
-{
-qreal scaleFactor = 1;
- if(m_FinalAnimatedScaleFactor > 1) {
- scaleFactor = (1.0 + (((m_FinalAnimatedScaleFactor - 1)/100)*frameNumber))/(mCurrentSize.width()/mMinDecScaleSize.width());
- }
- if(m_FinalAnimatedScaleFactor < 1) {
- scaleFactor = (m_FinalAnimatedScaleFactor+ (((1 - m_FinalAnimatedScaleFactor)/100)*frameNumber))/(mCurrentSize.width()/mMinDecScaleSize.width());
- }
+
- zoomImage(scaleFactor, m_AnimRefPoint);
-
-}
+void GlxZoomWidget::animateDoubleTap()
+ {
+ //calculate increamental scale factor based on the step and then calculate the applicable scale factor this step
+ //increamental SF works on the ImageSize when double tap started, applicable(required) SF calculates the delate SF
+ if(m_FinalAnimatedScaleFactor > 1) {
+ //AA::zoomin case
+ mIncSF += msfInc;
+ qreal reqSF = (mItemSize.width()*(mIncSF))/mCurrentSize.width();
+ zoomImage(reqSF, m_AnimRefPoint);
+ }
+ if(m_FinalAnimatedScaleFactor < 1) {
+ //AA::zoomout case
+ mIncSF -= msfInc;
+ qreal reqSF = (mzoSize.width()* mIncSF)/mCurrentSize.width();
+ zoomImage(reqSF, m_AnimRefPoint);
+ }
+ //check if all steps are done,if not emit signal to continue the animation
+ if(mdoubletapSteps >= 1 ){
+ mdoubletapSteps -= 1;
+ emit stepZoom();
+ }
+ else {
+ //animation is complete, finalize the widget transform using setgeometry
+ //reset the counter
+ mdoubletapSteps = 0;
+ animationTimeLineFinished();
+ }
+
+ }
void GlxZoomWidget::animationTimeLineFinished()
{
finalizeWidgetTransform();
@@ -510,6 +613,7 @@
mBlackBackgroundItem->hide();
//push the widget back to background
setZValue(mMinZValue);
+ mZoomOngoing = false;
emit zoomWidgetMovedBackground(mFocusIndex);
//do not reset the transform here as it will then zoom-in the widget to decoded image size
}
@@ -524,3 +628,13 @@
mTimerId = 0;
}
}
+
+bool GlxZoomWidget::isFocussedItemCorrupt()
+{
+ QVariant variant = mModel->data( mModel->index( mFocusIndex, 0 ), GlxImageCorruptRole );
+ if ( variant.isValid() && variant.canConvert< bool> () ) {
+ return variant.value< bool > () ;
+ }
+ return false ;
+}
+