|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the examples of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:BSD$ |
|
10 ** You may use this file under the terms of the BSD license as follows: |
|
11 ** |
|
12 ** "Redistribution and use in source and binary forms, with or without |
|
13 ** modification, are permitted provided that the following conditions are |
|
14 ** met: |
|
15 ** * Redistributions of source code must retain the above copyright |
|
16 ** notice, this list of conditions and the following disclaimer. |
|
17 ** * Redistributions in binary form must reproduce the above copyright |
|
18 ** notice, this list of conditions and the following disclaimer in |
|
19 ** the documentation and/or other materials provided with the |
|
20 ** distribution. |
|
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor |
|
22 ** the names of its contributors may be used to endorse or promote |
|
23 ** products derived from this software without specific prior written |
|
24 ** permission. |
|
25 ** |
|
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
|
37 ** $QT_END_LICENSE$ |
|
38 ** |
|
39 ****************************************************************************/ |
|
40 |
|
41 #include "flippablepad.h" |
|
42 #include "padnavigator.h" |
|
43 #include "splashitem.h" |
|
44 |
|
45 #include <QtGui/QtGui> |
|
46 #ifndef QT_NO_OPENGL |
|
47 #include <QtOpenGL/QtOpenGL> |
|
48 #endif |
|
49 |
|
50 //! [0] |
|
51 PadNavigator::PadNavigator(const QSize &size, QWidget *parent) |
|
52 : QGraphicsView(parent) |
|
53 { |
|
54 //! [0] |
|
55 //! [1] |
|
56 // Splash item |
|
57 SplashItem *splash = new SplashItem; |
|
58 splash->setZValue(1); |
|
59 //! [1] |
|
60 |
|
61 //! [2] |
|
62 // Pad item |
|
63 FlippablePad *pad = new FlippablePad(size); |
|
64 QGraphicsRotation *flipRotation = new QGraphicsRotation(pad); |
|
65 QGraphicsRotation *xRotation = new QGraphicsRotation(pad); |
|
66 QGraphicsRotation *yRotation = new QGraphicsRotation(pad); |
|
67 flipRotation->setAxis(Qt::YAxis); |
|
68 xRotation->setAxis(Qt::YAxis); |
|
69 yRotation->setAxis(Qt::XAxis); |
|
70 pad->setTransformations(QList<QGraphicsTransform *>() |
|
71 << flipRotation |
|
72 << xRotation << yRotation); |
|
73 //! [2] |
|
74 |
|
75 //! [3] |
|
76 // Back (proxy widget) item |
|
77 QGraphicsProxyWidget *backItem = new QGraphicsProxyWidget(pad); |
|
78 QWidget *widget = new QWidget; |
|
79 form.setupUi(widget); |
|
80 form.hostName->setFocus(); |
|
81 backItem->setWidget(widget); |
|
82 backItem->setVisible(false); |
|
83 backItem->setFocus(); |
|
84 backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
|
85 const QRectF r = backItem->rect(); |
|
86 backItem->setTransform(QTransform() |
|
87 .rotate(180, Qt::YAxis) |
|
88 .translate(-r.width()/2, -r.height()/2)); |
|
89 //! [3] |
|
90 |
|
91 //! [4] |
|
92 // Selection item |
|
93 RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), |
|
94 Qt::gray, pad); |
|
95 selectionItem->setZValue(0.5); |
|
96 //! [4] |
|
97 |
|
98 //! [5] |
|
99 // Splash animations |
|
100 QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y"); |
|
101 QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity"); |
|
102 smoothSplashMove->setEasingCurve(QEasingCurve::InQuad); |
|
103 smoothSplashMove->setDuration(250); |
|
104 smoothSplashOpacity->setDuration(250); |
|
105 //! [5] |
|
106 |
|
107 //! [6] |
|
108 // Selection animation |
|
109 QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x"); |
|
110 QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y"); |
|
111 QPropertyAnimation *smoothXRotation = new QPropertyAnimation(xRotation, "angle"); |
|
112 QPropertyAnimation *smoothYRotation = new QPropertyAnimation(yRotation, "angle"); |
|
113 smoothXSelection->setDuration(125); |
|
114 smoothYSelection->setDuration(125); |
|
115 smoothXRotation->setDuration(125); |
|
116 smoothYRotation->setDuration(125); |
|
117 smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad); |
|
118 smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad); |
|
119 smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad); |
|
120 smoothYRotation->setEasingCurve(QEasingCurve::InOutQuad); |
|
121 //! [6] |
|
122 |
|
123 //! [7] |
|
124 // Flip animation setup |
|
125 QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle"); |
|
126 QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale"); |
|
127 QPropertyAnimation *smoothFlipXRotation = new QPropertyAnimation(xRotation, "angle"); |
|
128 QPropertyAnimation *smoothFlipYRotation = new QPropertyAnimation(yRotation, "angle"); |
|
129 QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this); |
|
130 smoothFlipScale->setDuration(500); |
|
131 smoothFlipRotation->setDuration(500); |
|
132 smoothFlipXRotation->setDuration(500); |
|
133 smoothFlipYRotation->setDuration(500); |
|
134 smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad); |
|
135 smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad); |
|
136 smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad); |
|
137 smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad); |
|
138 smoothFlipScale->setKeyValueAt(0, qVariantValue<qreal>(1.0)); |
|
139 smoothFlipScale->setKeyValueAt(0.5, qVariantValue<qreal>(0.7)); |
|
140 smoothFlipScale->setKeyValueAt(1, qVariantValue<qreal>(1.0)); |
|
141 flipAnimation->addAnimation(smoothFlipRotation); |
|
142 flipAnimation->addAnimation(smoothFlipScale); |
|
143 flipAnimation->addAnimation(smoothFlipXRotation); |
|
144 flipAnimation->addAnimation(smoothFlipYRotation); |
|
145 //! [7] |
|
146 |
|
147 //! [8] |
|
148 // Flip animation delayed property assignment |
|
149 QSequentialAnimationGroup *setVariablesSequence = new QSequentialAnimationGroup; |
|
150 QPropertyAnimation *setFillAnimation = new QPropertyAnimation(pad, "fill"); |
|
151 QPropertyAnimation *setBackItemVisibleAnimation = new QPropertyAnimation(backItem, "visible"); |
|
152 QPropertyAnimation *setSelectionItemVisibleAnimation = new QPropertyAnimation(selectionItem, "visible"); |
|
153 setFillAnimation->setDuration(0); |
|
154 setBackItemVisibleAnimation->setDuration(0); |
|
155 setSelectionItemVisibleAnimation->setDuration(0); |
|
156 setVariablesSequence->addPause(250); |
|
157 setVariablesSequence->addAnimation(setBackItemVisibleAnimation); |
|
158 setVariablesSequence->addAnimation(setSelectionItemVisibleAnimation); |
|
159 setVariablesSequence->addAnimation(setFillAnimation); |
|
160 flipAnimation->addAnimation(setVariablesSequence); |
|
161 //! [8] |
|
162 |
|
163 //! [9] |
|
164 // Build the state machine |
|
165 QStateMachine *stateMachine = new QStateMachine(this); |
|
166 QState *splashState = new QState(stateMachine); |
|
167 QState *frontState = new QState(stateMachine); |
|
168 QHistoryState *historyState = new QHistoryState(frontState); |
|
169 QState *backState = new QState(stateMachine); |
|
170 //! [9] |
|
171 //! [10] |
|
172 frontState->assignProperty(pad, "fill", false); |
|
173 frontState->assignProperty(splash, "opacity", 0.0); |
|
174 frontState->assignProperty(backItem, "visible", false); |
|
175 frontState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(0.0)); |
|
176 frontState->assignProperty(selectionItem, "visible", true); |
|
177 backState->assignProperty(pad, "fill", true); |
|
178 backState->assignProperty(backItem, "visible", true); |
|
179 backState->assignProperty(xRotation, "angle", qVariantValue<qreal>(0.0)); |
|
180 backState->assignProperty(yRotation, "angle", qVariantValue<qreal>(0.0)); |
|
181 backState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(180.0)); |
|
182 backState->assignProperty(selectionItem, "visible", false); |
|
183 stateMachine->addDefaultAnimation(smoothXRotation); |
|
184 stateMachine->addDefaultAnimation(smoothYRotation); |
|
185 stateMachine->addDefaultAnimation(smoothXSelection); |
|
186 stateMachine->addDefaultAnimation(smoothYSelection); |
|
187 stateMachine->setInitialState(splashState); |
|
188 //! [10] |
|
189 |
|
190 //! [11] |
|
191 // Transitions |
|
192 QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState); |
|
193 anyKeyTransition->setTargetState(frontState); |
|
194 anyKeyTransition->addAnimation(smoothSplashMove); |
|
195 anyKeyTransition->addAnimation(smoothSplashOpacity); |
|
196 //! [11] |
|
197 |
|
198 //! [12] |
|
199 QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
200 Qt::Key_Enter, backState); |
|
201 QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
202 Qt::Key_Return, backState); |
|
203 QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
204 Qt::Key_Enter, frontState); |
|
205 QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
206 Qt::Key_Return, frontState); |
|
207 enterTransition->setTargetState(historyState); |
|
208 returnTransition->setTargetState(historyState); |
|
209 backEnterTransition->setTargetState(backState); |
|
210 backReturnTransition->setTargetState(backState); |
|
211 enterTransition->addAnimation(flipAnimation); |
|
212 returnTransition->addAnimation(flipAnimation); |
|
213 backEnterTransition->addAnimation(flipAnimation); |
|
214 backReturnTransition->addAnimation(flipAnimation); |
|
215 //! [12] |
|
216 |
|
217 //! [13] |
|
218 // Create substates for each icon; store in temporary grid. |
|
219 int columns = size.width(); |
|
220 int rows = size.height(); |
|
221 QVector< QVector< QState * > > stateGrid; |
|
222 stateGrid.resize(rows); |
|
223 for (int y = 0; y < rows; ++y) { |
|
224 stateGrid[y].resize(columns); |
|
225 for (int x = 0; x < columns; ++x) |
|
226 stateGrid[y][x] = new QState(frontState); |
|
227 } |
|
228 frontState->setInitialState(stateGrid[0][0]); |
|
229 selectionItem->setPos(pad->iconAt(0, 0)->pos()); |
|
230 //! [13] |
|
231 |
|
232 //! [14] |
|
233 // Enable key navigation using state transitions |
|
234 for (int y = 0; y < rows; ++y) { |
|
235 for (int x = 0; x < columns; ++x) { |
|
236 QState *state = stateGrid[y][x]; |
|
237 QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
238 Qt::Key_Right, state); |
|
239 QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
240 Qt::Key_Left, state); |
|
241 QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
242 Qt::Key_Down, state); |
|
243 QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress, |
|
244 Qt::Key_Up, state); |
|
245 rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]); |
|
246 leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]); |
|
247 downTransition->setTargetState(stateGrid[(y + 1) % rows][x]); |
|
248 upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]); |
|
249 //! [14] |
|
250 //! [15] |
|
251 RoundRectItem *icon = pad->iconAt(x, y); |
|
252 state->assignProperty(xRotation, "angle", -icon->x() / 6.0); |
|
253 state->assignProperty(yRotation, "angle", icon->y() / 6.0); |
|
254 state->assignProperty(selectionItem, "x", icon->x()); |
|
255 state->assignProperty(selectionItem, "y", icon->y()); |
|
256 frontState->assignProperty(icon, "visible", true); |
|
257 backState->assignProperty(icon, "visible", false); |
|
258 |
|
259 QPropertyAnimation *setIconVisibleAnimation = new QPropertyAnimation(icon, "visible"); |
|
260 setIconVisibleAnimation->setDuration(0); |
|
261 setVariablesSequence->addAnimation(setIconVisibleAnimation); |
|
262 } |
|
263 } |
|
264 //! [15] |
|
265 |
|
266 //! [16] |
|
267 // Scene |
|
268 QGraphicsScene *scene = new QGraphicsScene(this); |
|
269 scene->setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg")); |
|
270 scene->setItemIndexMethod(QGraphicsScene::NoIndex); |
|
271 scene->addItem(pad); |
|
272 scene->setSceneRect(scene->itemsBoundingRect()); |
|
273 setScene(scene); |
|
274 //! [16] |
|
275 |
|
276 //! [17] |
|
277 // Adjust splash item to scene contents |
|
278 const QRectF sbr = splash->boundingRect(); |
|
279 splash->setPos(-sbr.width() / 2, scene->sceneRect().top() - 2); |
|
280 frontState->assignProperty(splash, "y", splash->y() - 100.0); |
|
281 scene->addItem(splash); |
|
282 //! [17] |
|
283 |
|
284 //! [18] |
|
285 // View |
|
286 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
287 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
288 setMinimumSize(50, 50); |
|
289 setViewportUpdateMode(FullViewportUpdate); |
|
290 setCacheMode(CacheBackground); |
|
291 setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); |
|
292 #ifndef QT_NO_OPENGL |
|
293 setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); |
|
294 #endif |
|
295 |
|
296 stateMachine->start(); |
|
297 //! [18] |
|
298 } |
|
299 |
|
300 //! [19] |
|
301 void PadNavigator::resizeEvent(QResizeEvent *event) |
|
302 { |
|
303 QGraphicsView::resizeEvent(event); |
|
304 fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); |
|
305 } |
|
306 //! [19] |