padnavigator.cpp Example File
					 
					
						graphicsview/padnavigator/padnavigator.cpp
					 
					
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/ 
#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 // Splash item 
    SplashItem * splash =  new  SplashItem;
    splash- > setZValue(1 );
    // Pad item 
    FlippablePad * pad =  new  FlippablePad(size);
    QGraphicsRotation * flipRotation =  new  QGraphicsRotation QGraphicsRotation * xRotation =  new  QGraphicsRotation QGraphicsRotation * yRotation =  new  QGraphicsRotation - > setAxis(Qt :: YAxis);
    xRotation- > setAxis(Qt :: YAxis);
    yRotation- > setAxis(Qt :: XAxis);
    pad- > setTransformations(QList < QGraphicsTransform * > ()
                            < <  flipRotation
                            < <  xRotation < <  yRotation);
    // Back (proxy widget) item 
    QGraphicsProxyWidget * backItem =  new  QGraphicsProxyWidget QWidget * widget =  new  QWidget . setupUi(widget);
    form. hostName- > setFocus();
    backItem- > setWidget(widget);
    backItem- > setVisible(false );
    backItem- > setFocus();
    backItem- > setCacheMode(QGraphicsItem :: ItemCoordinateCache);
    const  QRectF =  backItem- > rect();
    backItem- > setTransform(QTransform . rotate(180 ,  Qt :: YAxis)
                           . translate(- r. width()/ 2 ,  - r. height()/ 2 ));
    // Selection item 
    RoundRectItem * selectionItem =  new  RoundRectItem(QRectF - 60 ,  - 60 ,  120 ,  120 ),  Qt :: gray,  pad);
    selectionItem- > setZValue(0.5 );
    // Splash animations 
    QPropertyAnimation * smoothSplashMove =  new  QPropertyAnimation ,  "y" );
    QPropertyAnimation * smoothSplashOpacity =  new  QPropertyAnimation ,  "opacity" );
    smoothSplashMove- > setEasingCurve(QEasingCurve :: InQuad);
    smoothSplashMove- > setDuration(250 );
    smoothSplashOpacity- > setDuration(250 );
    // Selection animation 
    QPropertyAnimation * smoothXSelection =  new  QPropertyAnimation ,  "x" );
    QPropertyAnimation * smoothYSelection =  new  QPropertyAnimation ,  "y" );
    QPropertyAnimation * smoothXRotation =  new  QPropertyAnimation ,  "angle" );
    QPropertyAnimation * smoothYRotation =  new  QPropertyAnimation ,  "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);
    // Flip animation setup 
    QPropertyAnimation * smoothFlipRotation =  new  QPropertyAnimation ,  "angle" );
    QPropertyAnimation * smoothFlipScale =  new  QPropertyAnimation ,  "scale" );
    QPropertyAnimation * smoothFlipXRotation =  new  QPropertyAnimation ,  "angle" );
    QPropertyAnimation * smoothFlipYRotation =  new  QPropertyAnimation ,  "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);
    // Flip animation delayed property assignment 
    QSequentialAnimationGroup * setVariablesSequence =  new  QSequentialAnimationGroup QPropertyAnimation * setFillAnimation =  new  QPropertyAnimation ,  "fill" );
    QPropertyAnimation * setBackItemVisibleAnimation =  new  QPropertyAnimation ,  "visible" );
    QPropertyAnimation * setSelectionItemVisibleAnimation =  new  QPropertyAnimation ,  "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);
    // Build the state machine 
    QStateMachine * stateMachine =  new  QStateMachine this );
    QState * splashState =  new  QState QState * frontState =  new  QState QHistoryState * historyState =  new  QHistoryState QState * backState =  new  QState - > 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);
    // Transitions 
    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);
    // Create substates for each icon; store in temporary grid. 
    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 - > setInitialState(stateGrid[ 0 ] [ 0 ] );
    selectionItem- > setPos(pad- > iconAt(0 ,  0 )- > pos());
    // Enable key navigation using state transitions 
    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 ,  "visible" );
            setIconVisibleAnimation- > setDuration(0 );
            setVariablesSequence- > addAnimation(setIconVisibleAnimation);
        }
    }
    // Scene 
    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);
    // Adjust splash item to scene contents 
    const  QRectF =  splash- > boundingRect();
    splash- > setPos(- sbr. width() /  2 ,  scene- > sceneRect(). top() -  2 );
    frontState- > assignProperty(splash,  "y" ,  splash- > y() -  100.0 );
    scene- > addItem(splash);
    // View 
    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);
}