#include "flippablepad.h"
#include "padnavigator.h"
#include "splashitem.h"
#ifndef QT_NO_OPENGL
#include <QtOpenGL>
#else
#include <QtWidgets>
#endif
PadNavigator::PadNavigator(const QSize &size, QWidget *parent)
: QGraphicsView(parent)
{
SplashItem *splash = new SplashItem;
splash->setZValue(1);
FlippablePad *pad = new FlippablePad(size);
QGraphicsRotation *flipRotation = new QGraphicsRotation(pad);
QGraphicsRotation *xRotation = new QGraphicsRotation(pad);
QGraphicsRotation *yRotation = new QGraphicsRotation(pad);
flipRotation->setAxis(Qt::YAxis);
xRotation->setAxis(Qt::YAxis);
yRotation->setAxis(Qt::XAxis);
pad->setTransformations(QList<QGraphicsTransform *>()
<< flipRotation
<< xRotation << yRotation);
QGraphicsProxyWidget *backItem = new QGraphicsProxyWidget(pad);
QWidget *widget = new QWidget;
form.setupUi(widget);
form.hostName->setFocus();
backItem->setWidget(widget);
backItem->setVisible(false);
backItem->setFocus();
backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
const QRectF r = backItem->rect();
backItem->setTransform(QTransform()
.rotate(180, Qt::YAxis)
.translate(-r.width()/2, -r.height()/2));
RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray, pad);
selectionItem->setZValue(0.5);
QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y");
QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity");
smoothSplashMove->setEasingCurve(QEasingCurve::InQuad);
smoothSplashMove->setDuration(250);
smoothSplashOpacity->setDuration(250);
QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x");
QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y");
QPropertyAnimation *smoothXRotation = new QPropertyAnimation(xRotation, "angle");
QPropertyAnimation *smoothYRotation = new QPropertyAnimation(yRotation, "angle");
smoothXSelection->setDuration(125);
smoothYSelection->setDuration(125);
smoothXRotation->setDuration(125);
smoothYRotation->setDuration(125);
smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad);
smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad);
smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad);
smoothYRotation->setEasingCurve(QEasingCurve::InOutQuad);
QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle");
QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale");
QPropertyAnimation *smoothFlipXRotation = new QPropertyAnimation(xRotation, "angle");
QPropertyAnimation *smoothFlipYRotation = new QPropertyAnimation(yRotation, "angle");
QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this);
smoothFlipScale->setDuration(500);
smoothFlipRotation->setDuration(500);
smoothFlipXRotation->setDuration(500);
smoothFlipYRotation->setDuration(500);
smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad);
smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad);
smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad);
smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad);
smoothFlipScale->setKeyValueAt(0, qvariant_cast<qreal>(1.0));
smoothFlipScale->setKeyValueAt(0.5, qvariant_cast<qreal>(0.7));
smoothFlipScale->setKeyValueAt(1, qvariant_cast<qreal>(1.0));
flipAnimation->addAnimation(smoothFlipRotation);
flipAnimation->addAnimation(smoothFlipScale);
flipAnimation->addAnimation(smoothFlipXRotation);
flipAnimation->addAnimation(smoothFlipYRotation);
QSequentialAnimationGroup *setVariablesSequence = new QSequentialAnimationGroup;
QPropertyAnimation *setFillAnimation = new QPropertyAnimation(pad, "fill");
QPropertyAnimation *setBackItemVisibleAnimation = new QPropertyAnimation(backItem, "visible");
QPropertyAnimation *setSelectionItemVisibleAnimation = new QPropertyAnimation(selectionItem, "visible");
setFillAnimation->setDuration(0);
setBackItemVisibleAnimation->setDuration(0);
setSelectionItemVisibleAnimation->setDuration(0);
setVariablesSequence->addPause(250);
setVariablesSequence->addAnimation(setBackItemVisibleAnimation);
setVariablesSequence->addAnimation(setSelectionItemVisibleAnimation);
setVariablesSequence->addAnimation(setFillAnimation);
flipAnimation->addAnimation(setVariablesSequence);
QStateMachine *stateMachine = new QStateMachine(this);
QState *splashState = new QState(stateMachine);
QState *frontState = new QState(stateMachine);
QHistoryState *historyState = new QHistoryState(frontState);
QState *backState = new QState(stateMachine);
frontState->assignProperty(pad, "fill", false);
frontState->assignProperty(splash, "opacity", 0.0);
frontState->assignProperty(backItem, "visible", false);
frontState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(0.0));
frontState->assignProperty(selectionItem, "visible", true);
backState->assignProperty(pad, "fill", true);
backState->assignProperty(backItem, "visible", true);
backState->assignProperty(xRotation, "angle", qvariant_cast<qreal>(0.0));
backState->assignProperty(yRotation, "angle", qvariant_cast<qreal>(0.0));
backState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(180.0));
backState->assignProperty(selectionItem, "visible", false);
stateMachine->addDefaultAnimation(smoothXRotation);
stateMachine->addDefaultAnimation(smoothYRotation);
stateMachine->addDefaultAnimation(smoothXSelection);
stateMachine->addDefaultAnimation(smoothYSelection);
stateMachine->setInitialState(splashState);
QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState);
anyKeyTransition->setTargetState(frontState);
anyKeyTransition->addAnimation(smoothSplashMove);
anyKeyTransition->addAnimation(smoothSplashOpacity);
QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Enter, backState);
QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Return, backState);
QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Enter, frontState);
QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Return, frontState);
enterTransition->setTargetState(historyState);
returnTransition->setTargetState(historyState);
backEnterTransition->setTargetState(backState);
backReturnTransition->setTargetState(backState);
enterTransition->addAnimation(flipAnimation);
returnTransition->addAnimation(flipAnimation);
backEnterTransition->addAnimation(flipAnimation);
backReturnTransition->addAnimation(flipAnimation);
int columns = size.width();
int rows = size.height();
QVector< QVector< QState * > > stateGrid;
stateGrid.resize(rows);
for (int y = 0; y < rows; ++y) {
stateGrid[y].resize(columns);
for (int x = 0; x < columns; ++x)
stateGrid[y][x] = new QState(frontState);
}
frontState->setInitialState(stateGrid[0][0]);
selectionItem->setPos(pad->iconAt(0, 0)->pos());
for (int y = 0; y < rows; ++y) {
for (int x = 0; x < columns; ++x) {
QState *state = stateGrid[y][x];
QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Right, state);
QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Left, state);
QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Down, state);
QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress,
Qt::Key_Up, state);
rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]);
leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]);
downTransition->setTargetState(stateGrid[(y + 1) % rows][x]);
upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]);
RoundRectItem *icon = pad->iconAt(x, y);
state->assignProperty(xRotation, "angle", -icon->x() / 6.0);
state->assignProperty(yRotation, "angle", icon->y() / 6.0);
state->assignProperty(selectionItem, "x", icon->x());
state->assignProperty(selectionItem, "y", icon->y());
frontState->assignProperty(icon, "visible", true);
backState->assignProperty(icon, "visible", false);
QPropertyAnimation *setIconVisibleAnimation = new QPropertyAnimation(icon, "visible");
setIconVisibleAnimation->setDuration(0);
setVariablesSequence->addAnimation(setIconVisibleAnimation);
}
}
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg"));
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->addItem(pad);
scene->setSceneRect(scene->itemsBoundingRect());
setScene(scene);
const QRectF sbr = splash->boundingRect();
splash->setPos(-sbr.width() / 2, scene->sceneRect().top() - 2);
frontState->assignProperty(splash, "y", splash->y() - 100.0);
scene->addItem(splash);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMinimumSize(50, 50);
setViewportUpdateMode(FullViewportUpdate);
setCacheMode(CacheBackground);
setRenderHints(QPainter::Antialiasing
| QPainter::SmoothPixmapTransform
| QPainter::TextAntialiasing);
#ifndef QT_NO_OPENGL
setViewport(new QOpenGLWidget);
#endif
stateMachine->start();
}
void PadNavigator::resizeEvent(QResizeEvent *event)
{
QGraphicsView::resizeEvent(event);
fitInView(scene()->sceneRect(), Qt::KeepAspectRatio);
}