ginebra/graphicsitemflipper.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 04 May 2010 12:39:35 +0300
changeset 0 1450b09d0cfd
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#include <assert.h>
#include "graphicsitemflipper.h"
#include "utilities.h"

GraphicsItemFlipper::GraphicsItemFlipper(QGraphicsItem *parentItem, QGraphicsScene *scene, int duration,
                                         uint updateInterval, int zValue)
  : m_timeLine(duration)
{
    m_timeLine.setUpdateInterval(updateInterval);
    m_timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
    safe_connect(&m_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(updateFlipStep(qreal)));
    safe_connect(&m_timeLine, SIGNAL(finished()), this, SLOT(onFinished()));

    m_pixmapItem = new QGraphicsPixmapItem(parentItem);
    scene->addItem(m_pixmapItem);
    m_pixmapItem->setZValue(zValue);
}

GraphicsItemFlipper::~GraphicsItemFlipper()
{
    delete m_pixmapItem;
    if(m_sourcePixmap) delete m_sourcePixmap;
    if(m_targetPixmap) delete m_targetPixmap;
}

void GraphicsItemFlipper::start(QGraphicsView *view, QGraphicsWidget *sourceWidget, QGraphicsWidget *targetWidget,
                                bool forward)
{
    emit starting();

    getPixmaps(view, sourceWidget, targetWidget);

    m_pixmapItem->setPixmap(forward ? *m_sourcePixmap : *m_targetPixmap);

    m_pixmapItem->show();

    m_timeLine.setDirection(forward ? QTimeLine::Forward : QTimeLine::Backward);
    m_timeLine.start();
}

void GraphicsItemFlipper::getPixmaps(QGraphicsView *view, QGraphicsWidget *sourceWidget, QGraphicsWidget *targetWidget)
{
    Q_UNUSED(view)
    QStyleOptionGraphicsItem options;

    m_sourceRect = sourceWidget->geometry();
    m_targetRect = targetWidget->geometry();

    // Get a snapshot of the source widget.
    m_sourcePixmap = new QPixmap(m_sourceRect.size().toSize());
    QPainter painter(m_sourcePixmap);
    options.exposedRect = m_sourceRect;
    sourceWidget->paint(&painter, &options);
    painter.end();

    // Get a snapshot of the target widget and flip it left to right.
    QPixmap tmpPixmap(m_targetRect.size().toSize());
    QPainter targetPainter(&tmpPixmap);
    options.exposedRect = m_targetRect;
    targetWidget->paint(&targetPainter, &options);
    targetPainter.end();
    m_targetPixmap = new QPixmap(tmpPixmap.transformed(QTransform().rotate(180, Qt::YAxis)));
}

void GraphicsItemFlipper::updateFlipStep(qreal value)  // slot
{
    //qreal scale = 1 - sin(3.14 * value) * 0.5;
    qreal sourceW = m_sourceRect.width();
    qreal sourceH = m_sourceRect.height();
    qreal deltaW = m_targetRect.width() - sourceW;
    qreal deltaH = m_targetRect.height() - sourceH;
    qreal deltaX = m_targetRect.left() - m_sourceRect.left();
    qreal deltaY = m_targetRect.top() - m_sourceRect.top();
    qreal xScale = (sourceW + (deltaW * value))/sourceW;
    qreal yScale = (sourceH + (deltaH * value))/sourceH;
    qreal newW = sourceW * xScale;
    qreal newH = sourceH * yScale;
    qreal dx = m_pixmapItem->pos().x() + (deltaX * value) + (newW/2);

//    qDebug() << "GraphicsItemFlipper::updateFlipStep: value=" << value;
//            << " xScale=" << xScale
//            << " newW=" << newW
//            << " deltaX=" << deltaX;

    // Set the appropriate pixmap.  If we've gone past the halfway point, ie. the item is edge-on,
    // switch pixmaps.
    // To do: Only set the pixmap twice, once when the animation starts and once at the halfway
    //        point.  Need to be sure resolution is correct at the end of the animation.
    if(value > 0.5) {
        m_pixmapItem->setPixmap(m_targetPixmap->scaled(int(newW), int(newH)));
    }
    else {
        m_pixmapItem->setPixmap(m_sourcePixmap->scaled(int(newW), int(newH)));
    }

    QTransform transform;
    transform.translate(dx, 0);
    transform.rotate(180 * value, Qt::YAxis);
    transform.translate(-dx, 0);
    transform.translate(deltaX * value, deltaY * value);
    m_pixmapItem->setTransform(transform);
}

void GraphicsItemFlipper::onFinished()
{
    m_pixmapItem->hide();
    emit finished();
}