| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2011 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 QtCore module 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 <QtCore> | 
|---|
| 42 | #include <QtGui> | 
|---|
| 43 |  | 
|---|
| 44 | //![15] | 
|---|
| 45 | class StateSwitchEvent: public QEvent | 
|---|
| 46 | { | 
|---|
| 47 | public: | 
|---|
| 48 | StateSwitchEvent() | 
|---|
| 49 | : QEvent(Type(StateSwitchType)) | 
|---|
| 50 | { | 
|---|
| 51 | } | 
|---|
| 52 |  | 
|---|
| 53 | StateSwitchEvent(int rand) | 
|---|
| 54 | : QEvent(Type(StateSwitchType)), | 
|---|
| 55 | m_rand(rand) | 
|---|
| 56 | { | 
|---|
| 57 | } | 
|---|
| 58 |  | 
|---|
| 59 | enum { StateSwitchType = QEvent::User + 256 }; | 
|---|
| 60 |  | 
|---|
| 61 | int rand() const { return m_rand; } | 
|---|
| 62 |  | 
|---|
| 63 | private: | 
|---|
| 64 | int m_rand; | 
|---|
| 65 | }; | 
|---|
| 66 | //![15] | 
|---|
| 67 |  | 
|---|
| 68 | //![16] | 
|---|
| 69 | class QGraphicsRectWidget : public QGraphicsWidget | 
|---|
| 70 | { | 
|---|
| 71 | public: | 
|---|
| 72 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *, | 
|---|
| 73 | QWidget *) | 
|---|
| 74 | { | 
|---|
| 75 | painter->fillRect(rect(), Qt::blue); | 
|---|
| 76 | } | 
|---|
| 77 | }; | 
|---|
| 78 | //![16] | 
|---|
| 79 |  | 
|---|
| 80 | class StateSwitchTransition: public QAbstractTransition | 
|---|
| 81 | { | 
|---|
| 82 | public: | 
|---|
| 83 | StateSwitchTransition(int rand) | 
|---|
| 84 | : QAbstractTransition(), | 
|---|
| 85 | m_rand(rand) | 
|---|
| 86 | { | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 | protected: | 
|---|
| 90 | //![14] | 
|---|
| 91 | virtual bool eventTest(QEvent *event) | 
|---|
| 92 | { | 
|---|
| 93 | return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType)) | 
|---|
| 94 | && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand); | 
|---|
| 95 | } | 
|---|
| 96 | //![14] | 
|---|
| 97 |  | 
|---|
| 98 | virtual void onTransition(QEvent *) {} | 
|---|
| 99 |  | 
|---|
| 100 | private: | 
|---|
| 101 | int m_rand; | 
|---|
| 102 | }; | 
|---|
| 103 |  | 
|---|
| 104 | //![10] | 
|---|
| 105 | class StateSwitcher : public QState | 
|---|
| 106 | { | 
|---|
| 107 | Q_OBJECT | 
|---|
| 108 | public: | 
|---|
| 109 | StateSwitcher(QStateMachine *machine) | 
|---|
| 110 | : QState(machine), m_stateCount(0), m_lastIndex(0) | 
|---|
| 111 | { } | 
|---|
| 112 | //![10] | 
|---|
| 113 |  | 
|---|
| 114 | //![11] | 
|---|
| 115 | virtual void onEntry(QEvent *) | 
|---|
| 116 | { | 
|---|
| 117 | int n; | 
|---|
| 118 | while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) | 
|---|
| 119 | { } | 
|---|
| 120 | m_lastIndex = n; | 
|---|
| 121 | machine()->postEvent(new StateSwitchEvent(n)); | 
|---|
| 122 | } | 
|---|
| 123 | virtual void onExit(QEvent *) {} | 
|---|
| 124 | //![11] | 
|---|
| 125 |  | 
|---|
| 126 | //![12] | 
|---|
| 127 | void addState(QState *state, QAbstractAnimation *animation) { | 
|---|
| 128 | StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); | 
|---|
| 129 | trans->setTargetState(state); | 
|---|
| 130 | addTransition(trans); | 
|---|
| 131 | trans->addAnimation(animation); | 
|---|
| 132 | } | 
|---|
| 133 | //![12] | 
|---|
| 134 |  | 
|---|
| 135 | private: | 
|---|
| 136 | int m_stateCount; | 
|---|
| 137 | int m_lastIndex; | 
|---|
| 138 | }; | 
|---|
| 139 |  | 
|---|
| 140 | //![13] | 
|---|
| 141 | QState *createGeometryState(QObject *w1, const QRect &rect1, | 
|---|
| 142 | QObject *w2, const QRect &rect2, | 
|---|
| 143 | QObject *w3, const QRect &rect3, | 
|---|
| 144 | QObject *w4, const QRect &rect4, | 
|---|
| 145 | QState *parent) | 
|---|
| 146 | { | 
|---|
| 147 | QState *result = new QState(parent); | 
|---|
| 148 | result->assignProperty(w1, "geometry", rect1); | 
|---|
| 149 | result->assignProperty(w2, "geometry", rect2); | 
|---|
| 150 | result->assignProperty(w3, "geometry", rect3); | 
|---|
| 151 | result->assignProperty(w4, "geometry", rect4); | 
|---|
| 152 |  | 
|---|
| 153 | return result; | 
|---|
| 154 | } | 
|---|
| 155 | //![13] | 
|---|
| 156 |  | 
|---|
| 157 | int main(int argc, char **argv) | 
|---|
| 158 | { | 
|---|
| 159 | QApplication app(argc, argv); | 
|---|
| 160 |  | 
|---|
| 161 | #if 0 | 
|---|
| 162 | QWidget window; | 
|---|
| 163 | QPalette palette; | 
|---|
| 164 | palette.setBrush(QPalette::Window, Qt::black); | 
|---|
| 165 | window.setPalette(palette); | 
|---|
| 166 | QPushButton *button1 = new QPushButton("A", &window); | 
|---|
| 167 | QPushButton *button2 = new QPushButton("B", &window); | 
|---|
| 168 | QPushButton *button3 = new QPushButton("C", &window); | 
|---|
| 169 | QPushButton *button4 = new QPushButton("D", &window); | 
|---|
| 170 |  | 
|---|
| 171 | button1->setObjectName("button1"); | 
|---|
| 172 | button2->setObjectName("button2"); | 
|---|
| 173 | button3->setObjectName("button3"); | 
|---|
| 174 | button4->setObjectName("button4"); | 
|---|
| 175 | #else | 
|---|
| 176 | //![1] | 
|---|
| 177 | QGraphicsRectWidget *button1 = new QGraphicsRectWidget; | 
|---|
| 178 | QGraphicsRectWidget *button2 = new QGraphicsRectWidget; | 
|---|
| 179 | QGraphicsRectWidget *button3 = new QGraphicsRectWidget; | 
|---|
| 180 | QGraphicsRectWidget *button4 = new QGraphicsRectWidget; | 
|---|
| 181 | button2->setZValue(1); | 
|---|
| 182 | button3->setZValue(2); | 
|---|
| 183 | button4->setZValue(3); | 
|---|
| 184 | QGraphicsScene scene(0, 0, 300, 300); | 
|---|
| 185 | scene.setBackgroundBrush(Qt::black); | 
|---|
| 186 | scene.addItem(button1); | 
|---|
| 187 | scene.addItem(button2); | 
|---|
| 188 | scene.addItem(button3); | 
|---|
| 189 | scene.addItem(button4); | 
|---|
| 190 | //![1] | 
|---|
| 191 | QGraphicsView window(&scene); | 
|---|
| 192 | window.setFrameStyle(0); | 
|---|
| 193 | window.setAlignment(Qt::AlignLeft | Qt::AlignTop); | 
|---|
| 194 | window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
|---|
| 195 | window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
|---|
| 196 | #endif | 
|---|
| 197 | //![2] | 
|---|
| 198 | QStateMachine machine; | 
|---|
| 199 |  | 
|---|
| 200 | QState *group = new QState(); | 
|---|
| 201 | group->setObjectName("group"); | 
|---|
| 202 | QTimer timer; | 
|---|
| 203 | timer.setInterval(1250); | 
|---|
| 204 | timer.setSingleShot(true); | 
|---|
| 205 | QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start())); | 
|---|
| 206 | //![2] | 
|---|
| 207 |  | 
|---|
| 208 | //![3] | 
|---|
| 209 | QState *state1; | 
|---|
| 210 | QState *state2; | 
|---|
| 211 | QState *state3; | 
|---|
| 212 | QState *state4; | 
|---|
| 213 | QState *state5; | 
|---|
| 214 | QState *state6; | 
|---|
| 215 | QState *state7; | 
|---|
| 216 |  | 
|---|
| 217 | state1 = createGeometryState(button1, QRect(100, 0, 50, 50), | 
|---|
| 218 | button2, QRect(150, 0, 50, 50), | 
|---|
| 219 | button3, QRect(200, 0, 50, 50), | 
|---|
| 220 | button4, QRect(250, 0, 50, 50), | 
|---|
| 221 | group); | 
|---|
| 222 | //![3] | 
|---|
| 223 | state2 = createGeometryState(button1, QRect(250, 100, 50, 50), | 
|---|
| 224 | button2, QRect(250, 150, 50, 50), | 
|---|
| 225 | button3, QRect(250, 200, 50, 50), | 
|---|
| 226 | button4, QRect(250, 250, 50, 50), | 
|---|
| 227 | group); | 
|---|
| 228 | state3 = createGeometryState(button1, QRect(150, 250, 50, 50), | 
|---|
| 229 | button2, QRect(100, 250, 50, 50), | 
|---|
| 230 | button3, QRect(50, 250, 50, 50), | 
|---|
| 231 | button4, QRect(0, 250, 50, 50), | 
|---|
| 232 | group); | 
|---|
| 233 | state4 = createGeometryState(button1, QRect(0, 150, 50, 50), | 
|---|
| 234 | button2, QRect(0, 100, 50, 50), | 
|---|
| 235 | button3, QRect(0, 50, 50, 50), | 
|---|
| 236 | button4, QRect(0, 0, 50, 50), | 
|---|
| 237 | group); | 
|---|
| 238 | state5 = createGeometryState(button1, QRect(100, 100, 50, 50), | 
|---|
| 239 | button2, QRect(150, 100, 50, 50), | 
|---|
| 240 | button3, QRect(100, 150, 50, 50), | 
|---|
| 241 | button4, QRect(150, 150, 50, 50), | 
|---|
| 242 | group); | 
|---|
| 243 | state6 = createGeometryState(button1, QRect(50, 50, 50, 50), | 
|---|
| 244 | button2, QRect(200, 50, 50, 50), | 
|---|
| 245 | button3, QRect(50, 200, 50, 50), | 
|---|
| 246 | button4, QRect(200, 200, 50, 50), | 
|---|
| 247 | group); | 
|---|
| 248 | //![4] | 
|---|
| 249 | state7 = createGeometryState(button1, QRect(0, 0, 50, 50), | 
|---|
| 250 | button2, QRect(250, 0, 50, 50), | 
|---|
| 251 | button3, QRect(0, 250, 50, 50), | 
|---|
| 252 | button4, QRect(250, 250, 50, 50), | 
|---|
| 253 | group); | 
|---|
| 254 | group->setInitialState(state1); | 
|---|
| 255 | //![4] | 
|---|
| 256 |  | 
|---|
| 257 | //![5] | 
|---|
| 258 | QParallelAnimationGroup animationGroup; | 
|---|
| 259 | QSequentialAnimationGroup *subGroup; | 
|---|
| 260 |  | 
|---|
| 261 | QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry"); | 
|---|
| 262 | anim->setDuration(1000); | 
|---|
| 263 | anim->setEasingCurve(QEasingCurve::OutElastic); | 
|---|
| 264 | animationGroup.addAnimation(anim); | 
|---|
| 265 | //![5] | 
|---|
| 266 |  | 
|---|
| 267 | //![6] | 
|---|
| 268 | subGroup = new QSequentialAnimationGroup(&animationGroup); | 
|---|
| 269 | subGroup->addPause(100); | 
|---|
| 270 | anim = new QPropertyAnimation(button3, "geometry"); | 
|---|
| 271 | anim->setDuration(1000); | 
|---|
| 272 | anim->setEasingCurve(QEasingCurve::OutElastic); | 
|---|
| 273 | subGroup->addAnimation(anim); | 
|---|
| 274 | //![6] | 
|---|
| 275 |  | 
|---|
| 276 | subGroup = new QSequentialAnimationGroup(&animationGroup); | 
|---|
| 277 | subGroup->addPause(150); | 
|---|
| 278 | anim = new QPropertyAnimation(button2, "geometry"); | 
|---|
| 279 | anim->setDuration(1000); | 
|---|
| 280 | anim->setEasingCurve(QEasingCurve::OutElastic); | 
|---|
| 281 | subGroup->addAnimation(anim); | 
|---|
| 282 |  | 
|---|
| 283 | subGroup = new QSequentialAnimationGroup(&animationGroup); | 
|---|
| 284 | subGroup->addPause(200); | 
|---|
| 285 | anim = new QPropertyAnimation(button1, "geometry"); | 
|---|
| 286 | anim->setDuration(1000); | 
|---|
| 287 | anim->setEasingCurve(QEasingCurve::OutElastic); | 
|---|
| 288 | subGroup->addAnimation(anim); | 
|---|
| 289 |  | 
|---|
| 290 | //![7] | 
|---|
| 291 | StateSwitcher *stateSwitcher = new StateSwitcher(&machine); | 
|---|
| 292 | stateSwitcher->setObjectName("stateSwitcher"); | 
|---|
| 293 | group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher); | 
|---|
| 294 | stateSwitcher->addState(state1, &animationGroup); | 
|---|
| 295 | stateSwitcher->addState(state2, &animationGroup); | 
|---|
| 296 | //![7] | 
|---|
| 297 | stateSwitcher->addState(state3, &animationGroup); | 
|---|
| 298 | stateSwitcher->addState(state4, &animationGroup); | 
|---|
| 299 | stateSwitcher->addState(state5, &animationGroup); | 
|---|
| 300 | stateSwitcher->addState(state6, &animationGroup); | 
|---|
| 301 | //![8] | 
|---|
| 302 | stateSwitcher->addState(state7, &animationGroup); | 
|---|
| 303 | //![8] | 
|---|
| 304 |  | 
|---|
| 305 | //![9] | 
|---|
| 306 | machine.addState(group); | 
|---|
| 307 | machine.setInitialState(group); | 
|---|
| 308 | machine.start(); | 
|---|
| 309 | //![9] | 
|---|
| 310 |  | 
|---|
| 311 | window.resize(300, 300); | 
|---|
| 312 | window.show(); | 
|---|
| 313 |  | 
|---|
| 314 | qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); | 
|---|
| 315 |  | 
|---|
| 316 | return app.exec(); | 
|---|
| 317 | } | 
|---|
| 318 |  | 
|---|
| 319 | #include "main.moc" | 
|---|