diff options
author | Karsten Heimrich <karsten.heimrich@qt.io> | 2020-08-25 13:19:19 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2020-08-28 15:55:10 +0200 |
commit | 8c4a7f508eed8049dec1f0ffdfb16e050341cce4 (patch) | |
tree | ffa8f528db0ef2d565c76c18923065d59077a838 | |
parent | b0f3d51f0833dd070907d5f62f11513744e711a3 (diff) |
Move state machine examples into QtScxml
Task-number: QTBUG-80316
Change-Id: Ibca5668d4be742b90dd2004358ddccbb3910bacd
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
190 files changed, 14309 insertions, 1 deletions
diff --git a/examples/examples.pro b/examples/examples.pro index 2d6d823..10ef070 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs qtHaveModule(scxml): SUBDIRS += scxml - +qtHaveModule(statemachine): SUBDIRS += widgets diff --git a/examples/widgets/.prev_CMakeLists.txt b/examples/widgets/.prev_CMakeLists.txt new file mode 100644 index 0000000..26d094d --- /dev/null +++ b/examples/widgets/.prev_CMakeLists.txt @@ -0,0 +1,10 @@ +# Generated from widgets.pro. + +if(NOT TARGET Qt::Widgets) + return() +endif() +if(QT_FEATURE_animation) + add_subdirectory(animation) +endif() +add_subdirectory(graphicsview) +add_subdirectory(statemachine) diff --git a/examples/widgets/CMakeLists.txt b/examples/widgets/CMakeLists.txt new file mode 100644 index 0000000..5ddc90e --- /dev/null +++ b/examples/widgets/CMakeLists.txt @@ -0,0 +1,10 @@ +# Generated from widgets.pro. + +if(NOT TARGET Qt::Widgets) + return() +endif() +add_subdirectory(graphicsview) +add_subdirectory(statemachine) +if(QT_FEATURE_animation) + add_subdirectory(animation) +endif() diff --git a/examples/widgets/animation/CMakeLists.txt b/examples/widgets/animation/CMakeLists.txt new file mode 100644 index 0000000..6a60fe4 --- /dev/null +++ b/examples/widgets/animation/CMakeLists.txt @@ -0,0 +1,7 @@ +# Generated from animation.pro. + +add_subdirectory(animatedtiles) +add_subdirectory(moveblocks) +add_subdirectory(states) +add_subdirectory(stickman) +add_subdirectory(sub-attaq) diff --git a/examples/widgets/animation/README b/examples/widgets/animation/README new file mode 100644 index 0000000..e723a28 --- /dev/null +++ b/examples/widgets/animation/README @@ -0,0 +1,8 @@ +The animation framework aims to provide an easy way for creating animated and +smooth GUI's. By animating Qt properties, the framework provides great freedom +for animating widgets and other QObjects. The framework can also be used with +the Graphics View framework. + + +Documentation for these examples can be found via the Examples +link in the main Qt documentation. diff --git a/examples/widgets/animation/animatedtiles/CMakeLists.txt b/examples/widgets/animation/animatedtiles/CMakeLists.txt new file mode 100644 index 0000000..351926b --- /dev/null +++ b/examples/widgets/animation/animatedtiles/CMakeLists.txt @@ -0,0 +1,55 @@ +# Generated from animatedtiles.pro. + +cmake_minimum_required(VERSION 3.14) +project(animatedtiles LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/animatedtiles") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(animatedtiles + main.cpp +) +target_link_libraries(animatedtiles PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set(animatedtiles_resource_files + "images/Time-For-Lunch-2.jpg" + "images/centered.png" + "images/ellipse.png" + "images/figure8.png" + "images/kinetic.png" + "images/random.png" + "images/tile.png" +) + +qt6_add_resources(animatedtiles "animatedtiles" + PREFIX + "/" + FILES + ${animatedtiles_resource_files} +) + +install(TARGETS animatedtiles + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/animatedtiles/animatedtiles.pro b/examples/widgets/animation/animatedtiles/animatedtiles.pro new file mode 100644 index 0000000..4701aa5 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/animatedtiles.pro @@ -0,0 +1,8 @@ +QT += statemachine widgets + +SOURCES = main.cpp +RESOURCES = animatedtiles.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/animatedtiles +INSTALLS += target diff --git a/examples/widgets/animation/animatedtiles/animatedtiles.qrc b/examples/widgets/animation/animatedtiles/animatedtiles.qrc new file mode 100644 index 0000000..c43a979 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/animatedtiles.qrc @@ -0,0 +1,11 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>images/Time-For-Lunch-2.jpg</file> + <file>images/centered.png</file> + <file>images/ellipse.png</file> + <file>images/figure8.png</file> + <file>images/kinetic.png</file> + <file>images/random.png</file> + <file>images/tile.png</file> +</qresource> +</RCC> diff --git a/examples/widgets/animation/animatedtiles/images/Time-For-Lunch-2.jpg b/examples/widgets/animation/animatedtiles/images/Time-For-Lunch-2.jpg Binary files differnew file mode 100644 index 0000000..c57a555 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/Time-For-Lunch-2.jpg diff --git a/examples/widgets/animation/animatedtiles/images/centered.png b/examples/widgets/animation/animatedtiles/images/centered.png Binary files differnew file mode 100644 index 0000000..e416156 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/centered.png diff --git a/examples/widgets/animation/animatedtiles/images/ellipse.png b/examples/widgets/animation/animatedtiles/images/ellipse.png Binary files differnew file mode 100644 index 0000000..2c3ba88 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/ellipse.png diff --git a/examples/widgets/animation/animatedtiles/images/figure8.png b/examples/widgets/animation/animatedtiles/images/figure8.png Binary files differnew file mode 100644 index 0000000..6b05804 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/figure8.png diff --git a/examples/widgets/animation/animatedtiles/images/kinetic.png b/examples/widgets/animation/animatedtiles/images/kinetic.png Binary files differnew file mode 100644 index 0000000..d5fc0af --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/kinetic.png diff --git a/examples/widgets/animation/animatedtiles/images/random.png b/examples/widgets/animation/animatedtiles/images/random.png Binary files differnew file mode 100644 index 0000000..415d96f --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/random.png diff --git a/examples/widgets/animation/animatedtiles/images/tile.png b/examples/widgets/animation/animatedtiles/images/tile.png Binary files differnew file mode 100644 index 0000000..c8f39d8 --- /dev/null +++ b/examples/widgets/animation/animatedtiles/images/tile.png diff --git a/examples/widgets/animation/animatedtiles/main.cpp b/examples/widgets/animation/animatedtiles/main.cpp new file mode 100644 index 0000000..29670bb --- /dev/null +++ b/examples/widgets/animation/animatedtiles/main.cpp @@ -0,0 +1,267 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtCore> +#include <QtStateMachine> +#include <QtWidgets> + +class Pixmap : public QObject, public QGraphicsPixmapItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + Pixmap(const QPixmap &pix) + : QObject(), QGraphicsPixmapItem(pix) + { + setCacheMode(DeviceCoordinateCache); + } +}; + +class Button : public QGraphicsWidget +{ + Q_OBJECT +public: + Button(const QPixmap &pixmap, QGraphicsItem *parent = nullptr) + : QGraphicsWidget(parent), _pix(pixmap) + { + setAcceptHoverEvents(true); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const override + { + return QRectF(-65, -65, 130, 130); + } + + QPainterPath shape() const override + { + QPainterPath path; + path.addEllipse(boundingRect()); + return path; + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override + { + bool down = option->state & QStyle::State_Sunken; + QRectF r = boundingRect(); + QLinearGradient grad(r.topLeft(), r.bottomRight()); + grad.setColorAt(down ? 1 : 0, option->state & QStyle::State_MouseOver ? Qt::white : Qt::lightGray); + grad.setColorAt(down ? 0 : 1, Qt::darkGray); + painter->setPen(Qt::darkGray); + painter->setBrush(grad); + painter->drawEllipse(r); + QLinearGradient grad2(r.topLeft(), r.bottomRight()); + grad.setColorAt(down ? 1 : 0, Qt::darkGray); + grad.setColorAt(down ? 0 : 1, Qt::lightGray); + painter->setPen(Qt::NoPen); + painter->setBrush(grad); + if (down) + painter->translate(2, 2); + painter->drawEllipse(r.adjusted(5, 5, -5, -5)); + painter->drawPixmap(-_pix.width()/2, -_pix.height()/2, _pix); + } + +signals: + void pressed(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *) override + { + emit pressed(); + update(); + } + + void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override + { + update(); + } + +private: + QPixmap _pix; +}; + +class View : public QGraphicsView +{ +public: + View(QGraphicsScene *scene) : QGraphicsView(scene) { } + +protected: + void resizeEvent(QResizeEvent *event) override + { + QGraphicsView::resizeEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); + } +}; + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(animatedtiles); + + QApplication app(argc, argv); + + QPixmap kineticPix(":/images/kinetic.png"); + QPixmap bgPix(":/images/Time-For-Lunch-2.jpg"); + + QGraphicsScene scene(-350, -350, 700, 700); + + QList<Pixmap *> items; + for (int i = 0; i < 64; ++i) { + Pixmap *item = new Pixmap(kineticPix); + item->setOffset(-kineticPix.width()/2, -kineticPix.height()/2); + item->setZValue(i); + items << item; + scene.addItem(item); + } + + // Buttons + QGraphicsItem *buttonParent = new QGraphicsRectItem; + Button *ellipseButton = new Button(QPixmap(":/images/ellipse.png"), buttonParent); + Button *figure8Button = new Button(QPixmap(":/images/figure8.png"), buttonParent); + Button *randomButton = new Button(QPixmap(":/images/random.png"), buttonParent); + Button *tiledButton = new Button(QPixmap(":/images/tile.png"), buttonParent); + Button *centeredButton = new Button(QPixmap(":/images/centered.png"), buttonParent); + + ellipseButton->setPos(-100, -100); + figure8Button->setPos(100, -100); + randomButton->setPos(0, 0); + tiledButton->setPos(-100, 100); + centeredButton->setPos(100, 100); + + scene.addItem(buttonParent); + buttonParent->setTransform(QTransform::fromScale(0.75, 0.75), true); + buttonParent->setPos(200, 200); + buttonParent->setZValue(65); + + // States + QState *rootState = new QState; + QState *ellipseState = new QState(rootState); + QState *figure8State = new QState(rootState); + QState *randomState = new QState(rootState); + QState *tiledState = new QState(rootState); + QState *centeredState = new QState(rootState); + + // Values + for (int i = 0; i < items.count(); ++i) { + Pixmap *item = items.at(i); + // Ellipse + ellipseState->assignProperty(item, "pos", + QPointF(qCos((i / 63.0) * 6.28) * 250, + qSin((i / 63.0) * 6.28) * 250)); + + // Figure 8 + figure8State->assignProperty(item, "pos", + QPointF(qSin((i / 63.0) * 6.28) * 250, + qSin(((i * 2)/63.0) * 6.28) * 250)); + + // Random + randomState->assignProperty(item, "pos", + QPointF(-250 + QRandomGenerator::global()->bounded(500), + -250 + QRandomGenerator::global()->bounded(500))); + + // Tiled + tiledState->assignProperty(item, "pos", + QPointF(((i % 8) - 4) * kineticPix.width() + kineticPix.width() / 2, + ((i / 8) - 4) * kineticPix.height() + kineticPix.height() / 2)); + + // Centered + centeredState->assignProperty(item, "pos", QPointF()); + } + + // Ui + View *view = new View(&scene); + view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Animated Tiles")); + view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view->setBackgroundBrush(bgPix); + view->setCacheMode(QGraphicsView::CacheBackground); + view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + view->show(); + + QStateMachine states; + states.addState(rootState); + states.setInitialState(rootState); + rootState->setInitialState(centeredState); + + QParallelAnimationGroup *group = new QParallelAnimationGroup; + for (int i = 0; i < items.count(); ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + QAbstractTransition *trans = rootState->addTransition(ellipseButton, &Button::pressed, ellipseState); + trans->addAnimation(group); + + trans = rootState->addTransition(figure8Button, &Button::pressed, figure8State); + trans->addAnimation(group); + + trans = rootState->addTransition(randomButton, &Button::pressed, randomState); + trans->addAnimation(group); + + trans = rootState->addTransition(tiledButton, &Button::pressed, tiledState); + trans->addAnimation(group); + + trans = rootState->addTransition(centeredButton, &Button::pressed, centeredState); + trans->addAnimation(group); + + QTimer timer; + timer.start(125); + timer.setSingleShot(true); + trans = rootState->addTransition(&timer, &QTimer::timeout, ellipseState); + trans->addAnimation(group); + + states.start(); + +#ifdef QT_KEYPAD_NAVIGATION + QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); +#endif + return app.exec(); +} + +#include "main.moc" diff --git a/examples/widgets/animation/animation.pro b/examples/widgets/animation/animation.pro new file mode 100644 index 0000000..9e84d43 --- /dev/null +++ b/examples/widgets/animation/animation.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +SUBDIRS = animatedtiles \ + moveblocks \ + states \ + stickman \ + sub-attaq diff --git a/examples/widgets/animation/moveblocks/CMakeLists.txt b/examples/widgets/animation/moveblocks/CMakeLists.txt new file mode 100644 index 0000000..d531f9f --- /dev/null +++ b/examples/widgets/animation/moveblocks/CMakeLists.txt @@ -0,0 +1,36 @@ +# Generated from moveblocks.pro. + +cmake_minimum_required(VERSION 3.14) +project(moveblocks LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/moveblocks") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(moveblocks + main.cpp +) +target_link_libraries(moveblocks PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + +install(TARGETS moveblocks + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/moveblocks/main.cpp b/examples/widgets/animation/moveblocks/main.cpp new file mode 100644 index 0000000..daaa503 --- /dev/null +++ b/examples/widgets/animation/moveblocks/main.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtCore> +#include <QtWidgets> +#include <QtStateMachine> + +//![15] +class StateSwitchEvent: public QEvent +{ +public: + StateSwitchEvent() + : QEvent(Type(StateSwitchType)) + { + } + + explicit StateSwitchEvent(int rand) + : QEvent(Type(StateSwitchType)), + m_rand(rand) + { + } + + enum { StateSwitchType = QEvent::User + 256 }; + + int rand() const { return m_rand; } + +private: + int m_rand; +}; +//![15] + +//![16] +class QGraphicsRectWidget : public QGraphicsWidget +{ +public: + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, + QWidget *) override + { + painter->fillRect(rect(), Qt::blue); + } +}; +//![16] + +class StateSwitchTransition: public QAbstractTransition +{ +public: + StateSwitchTransition(int rand) + : QAbstractTransition(), + m_rand(rand) + { + } + +protected: +//![14] + bool eventTest(QEvent *event) override + { + return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType)) + && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand); + } +//![14] + + void onTransition(QEvent *) override {} + +private: + int m_rand; +}; + +//![10] +class StateSwitcher : public QState +{ + Q_OBJECT +public: + StateSwitcher(QStateMachine *machine) + : QState(machine), m_stateCount(0), m_lastIndex(0) + { } +//![10] + +//![11] + void onEntry(QEvent *) override + { + int n; + while ((n = QRandomGenerator::global()->bounded(m_stateCount) + 1) == m_lastIndex) + { } + m_lastIndex = n; + machine()->postEvent(new StateSwitchEvent(n)); + } + void onExit(QEvent *) override {} +//![11] + +//![12] + void addState(QState *state, QAbstractAnimation *animation) { + StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); + trans->setTargetState(state); + addTransition(trans); + trans->addAnimation(animation); + } +//![12] + +private: + int m_stateCount; + int m_lastIndex; +}; + +//![13] +QState *createGeometryState(QObject *w1, const QRect &rect1, + QObject *w2, const QRect &rect2, + QObject *w3, const QRect &rect3, + QObject *w4, const QRect &rect4, + QState *parent) +{ + QState *result = new QState(parent); + result->assignProperty(w1, "geometry", rect1); + result->assignProperty(w2, "geometry", rect2); + result->assignProperty(w3, "geometry", rect3); + result->assignProperty(w4, "geometry", rect4); + + return result; +} +//![13] + + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr) + : QGraphicsView(scene, parent) + { + } + +protected: + void resizeEvent(QResizeEvent *event) override + { + fitInView(scene()->sceneRect()); + QGraphicsView::resizeEvent(event); + } +}; + + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + +//![1] + QGraphicsRectWidget *button1 = new QGraphicsRectWidget; + QGraphicsRectWidget *button2 = new QGraphicsRectWidget; + QGraphicsRectWidget *button3 = new QGraphicsRectWidget; + QGraphicsRectWidget *button4 = new QGraphicsRectWidget; + button2->setZValue(1); + button3->setZValue(2); + button4->setZValue(3); + QGraphicsScene scene(0, 0, 300, 300); + scene.setBackgroundBrush(Qt::black); + scene.addItem(button1); + scene.addItem(button2); + scene.addItem(button3); + scene.addItem(button4); +//![1] + GraphicsView window(&scene); + window.setFrameStyle(0); + window.setAlignment(Qt::AlignLeft | Qt::AlignTop); + window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +//![2] + QStateMachine machine; + + QState *group = new QState(); + group->setObjectName("group"); + QTimer timer; + timer.setInterval(1250); + timer.setSingleShot(true); + QObject::connect(group, &QState::entered, &timer, QOverload<>::of(&QTimer::start)); +//![2] + +//![3] + QState *state1; + QState *state2; + QState *state3; + QState *state4; + QState *state5; + QState *state6; + QState *state7; + + state1 = createGeometryState(button1, QRect(100, 0, 50, 50), + button2, QRect(150, 0, 50, 50), + button3, QRect(200, 0, 50, 50), + button4, QRect(250, 0, 50, 50), + group); +//![3] + state2 = createGeometryState(button1, QRect(250, 100, 50, 50), + button2, QRect(250, 150, 50, 50), + button3, QRect(250, 200, 50, 50), + button4, QRect(250, 250, 50, 50), + group); + state3 = createGeometryState(button1, QRect(150, 250, 50, 50), + button2, QRect(100, 250, 50, 50), + button3, QRect(50, 250, 50, 50), + button4, QRect(0, 250, 50, 50), + group); + state4 = createGeometryState(button1, QRect(0, 150, 50, 50), + button2, QRect(0, 100, 50, 50), + button3, QRect(0, 50, 50, 50), + button4, QRect(0, 0, 50, 50), + group); + state5 = createGeometryState(button1, QRect(100, 100, 50, 50), + button2, QRect(150, 100, 50, 50), + button3, QRect(100, 150, 50, 50), + button4, QRect(150, 150, 50, 50), + group); + state6 = createGeometryState(button1, QRect(50, 50, 50, 50), + button2, QRect(200, 50, 50, 50), + button3, QRect(50, 200, 50, 50), + button4, QRect(200, 200, 50, 50), + group); +//![4] + state7 = createGeometryState(button1, QRect(0, 0, 50, 50), + button2, QRect(250, 0, 50, 50), + button3, QRect(0, 250, 50, 50), + button4, QRect(250, 250, 50, 50), + group); + group->setInitialState(state1); +//![4] + +//![5] + QParallelAnimationGroup animationGroup; + QSequentialAnimationGroup *subGroup; + + QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + animationGroup.addAnimation(anim); +//![5] + +//![6] + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(100); + anim = new QPropertyAnimation(button3, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); +//![6] + + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(150); + anim = new QPropertyAnimation(button2, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); + + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(200); + anim = new QPropertyAnimation(button1, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); + +//![7] + StateSwitcher *stateSwitcher = new StateSwitcher(&machine); + stateSwitcher->setObjectName("stateSwitcher"); + group->addTransition(&timer, &QTimer::timeout, stateSwitcher); + stateSwitcher->addState(state1, &animationGroup); + stateSwitcher->addState(state2, &animationGroup); +//![7] + stateSwitcher->addState(state3, &animationGroup); + stateSwitcher->addState(state4, &animationGroup); + stateSwitcher->addState(state5, &animationGroup); + stateSwitcher->addState(state6, &animationGroup); +//![8] + stateSwitcher->addState(state7, &animationGroup); +//![8] + +//![9] + machine.addState(group); + machine.setInitialState(group); + machine.start(); +//![9] + + window.resize(300, 300); + window.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/widgets/animation/moveblocks/moveblocks.pro b/examples/widgets/animation/moveblocks/moveblocks.pro new file mode 100644 index 0000000..125f7ad --- /dev/null +++ b/examples/widgets/animation/moveblocks/moveblocks.pro @@ -0,0 +1,7 @@ +QT += statemachine widgets + +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/moveblocks +INSTALLS += target diff --git a/examples/widgets/animation/states/CMakeLists.txt b/examples/widgets/animation/states/CMakeLists.txt new file mode 100644 index 0000000..7050edb --- /dev/null +++ b/examples/widgets/animation/states/CMakeLists.txt @@ -0,0 +1,54 @@ +# Generated from states.pro. + +cmake_minimum_required(VERSION 3.14) +project(states LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/states") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(states + main.cpp +) +target_link_libraries(states PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set(states_resource_files + "accessories-dictionary.png" + "akregator.png" + "digikam.png" + "help-browser.png" + "k3b.png" + "kchart.png" +) + +qt6_add_resources(states "states" + PREFIX + "/" + FILES + ${states_resource_files} +) + +install(TARGETS states + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/states/accessories-dictionary.png b/examples/widgets/animation/states/accessories-dictionary.png Binary files differnew file mode 100644 index 0000000..e9bd55d --- /dev/null +++ b/examples/widgets/animation/states/accessories-dictionary.png diff --git a/examples/widgets/animation/states/akregator.png b/examples/widgets/animation/states/akregator.png Binary files differnew file mode 100644 index 0000000..a086f45 --- /dev/null +++ b/examples/widgets/animation/states/akregator.png diff --git a/examples/widgets/animation/states/digikam.png b/examples/widgets/animation/states/digikam.png Binary files differnew file mode 100644 index 0000000..9de9fb2 --- /dev/null +++ b/examples/widgets/animation/states/digikam.png diff --git a/examples/widgets/animation/states/help-browser.png b/examples/widgets/animation/states/help-browser.png Binary files differnew file mode 100644 index 0000000..db92faa --- /dev/null +++ b/examples/widgets/animation/states/help-browser.png diff --git a/examples/widgets/animation/states/k3b.png b/examples/widgets/animation/states/k3b.png Binary files differnew file mode 100644 index 0000000..bbcafcf --- /dev/null +++ b/examples/widgets/animation/states/k3b.png diff --git a/examples/widgets/animation/states/kchart.png b/examples/widgets/animation/states/kchart.png Binary files differnew file mode 100644 index 0000000..1dd115b --- /dev/null +++ b/examples/widgets/animation/states/kchart.png diff --git a/examples/widgets/animation/states/main.cpp b/examples/widgets/animation/states/main.cpp new file mode 100644 index 0000000..bfc0dd2 --- /dev/null +++ b/examples/widgets/animation/states/main.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtStateMachine> +#include <QtWidgets> + +class Pixmap : public QGraphicsObject +{ + Q_OBJECT +public: + Pixmap(const QPixmap &pix) : QGraphicsObject(), p(pix) + { + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override + { + painter->drawPixmap(QPointF(), p); + } + + QRectF boundingRect() const override + { + return QRectF( QPointF(0, 0), p.size()); + } + +private: + QPixmap p; +}; + +class GraphicsView : public QGraphicsView +{ +public: + GraphicsView(QGraphicsScene *scene) : QGraphicsView(scene) + { + } + + void resizeEvent(QResizeEvent *) override + { + fitInView(sceneRect(), Qt::KeepAspectRatio); + } +}; + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(states); + + QApplication app(argc, argv); + + // Text edit and button + QTextEdit *edit = new QTextEdit; + edit->setText("asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy!"); + + QPushButton *button = new QPushButton; + QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget; + buttonProxy->setWidget(button); + QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget; + editProxy->setWidget(edit); + + QGroupBox *box = new QGroupBox; + box->setFlat(true); + box->setTitle("Options"); + + QVBoxLayout *layout2 = new QVBoxLayout; + box->setLayout(layout2); + layout2->addWidget(new QRadioButton("Herring")); + layout2->addWidget(new QRadioButton("Blue Parrot")); + layout2->addWidget(new QRadioButton("Petunias")); + layout2->addStretch(); + + QGraphicsProxyWidget *boxProxy = new QGraphicsProxyWidget; + boxProxy->setWidget(box); + + // Parent widget + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget); + layout->addItem(editProxy); + layout->addItem(buttonProxy); + widget->setLayout(layout); + + Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png")); + Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png")); + Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png")); + Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png")); + Pixmap *p5 = new Pixmap(QPixmap(":/help-browser.png")); + Pixmap *p6 = new Pixmap(QPixmap(":/kchart.png")); + + QGraphicsScene scene(0, 0, 400, 300); + scene.setBackgroundBrush(scene.palette().window()); + scene.addItem(widget); + scene.addItem(boxProxy); + scene.addItem(p1); + scene.addItem(p2); + scene.addItem(p3); + scene.addItem(p4); + scene.addItem(p5); + scene.addItem(p6); + + QStateMachine machine; + QState *state1 = new QState(&machine); + QState *state2 = new QState(&machine); + QState *state3 = new QState(&machine); + machine.setInitialState(state1); + + // State 1 + state1->assignProperty(button, "text", "Switch to state 2"); + state1->assignProperty(widget, "geometry", QRectF(0, 0, 400, 150)); + state1->assignProperty(box, "geometry", QRect(-200, 150, 200, 150)); + state1->assignProperty(p1, "pos", QPointF(68, 200)); // 185)); + state1->assignProperty(p2, "pos", QPointF(168, 200)); // 185)); + state1->assignProperty(p3, "pos", QPointF(268, 200)); // 185)); + state1->assignProperty(p4, "pos", QPointF(68 - 150, 48 - 150)); + state1->assignProperty(p5, "pos", QPointF(168, 48 - 150)); + state1->assignProperty(p6, "pos", QPointF(268 + 150, 48 - 150)); + state1->assignProperty(p1, "rotation", qreal(0)); + state1->assignProperty(p2, "rotation", qreal(0)); + state1->assignProperty(p3, "rotation", qreal(0)); + state1->assignProperty(p4, "rotation", qreal(-270)); + state1->assignProperty(p5, "rotation", qreal(-90)); + state1->assignProperty(p6, "rotation", qreal(270)); + state1->assignProperty(boxProxy, "opacity", qreal(0)); + state1->assignProperty(p1, "opacity", qreal(1)); + state1->assignProperty(p2, "opacity", qreal(1)); + state1->assignProperty(p3, "opacity", qreal(1)); + state1->assignProperty(p4, "opacity", qreal(0)); + state1->assignProperty(p5, "opacity", qreal(0)); + state1->assignProperty(p6, "opacity", qreal(0)); + + // State 2 + state2->assignProperty(button, "text", "Switch to state 3"); + state2->assignProperty(widget, "geometry", QRectF(200, 150, 200, 150)); + state2->assignProperty(box, "geometry", QRect(9, 150, 190, 150)); + state2->assignProperty(p1, "pos", QPointF(68 - 150, 185 + 150)); + state2->assignProperty(p2, "pos", QPointF(168, 185 + 150)); + state2->assignProperty(p3, "pos", QPointF(268 + 150, 185 + 150)); + state2->assignProperty(p4, "pos", QPointF(64, 48)); + state2->assignProperty(p5, "pos", QPointF(168, 48)); + state2->assignProperty(p6, "pos", QPointF(268, 48)); + state2->assignProperty(p1, "rotation", qreal(-270)); + state2->assignProperty(p2, "rotation", qreal(90)); + state2->assignProperty(p3, "rotation", qreal(270)); + state2->assignProperty(p4, "rotation", qreal(0)); + state2->assignProperty(p5, "rotation", qreal(0)); + state2->assignProperty(p6, "rotation", qreal(0)); + state2->assignProperty(boxProxy, "opacity", qreal(1)); + state2->assignProperty(p1, "opacity", qreal(0)); + state2->assignProperty(p2, "opacity", qreal(0)); + state2->assignProperty(p3, "opacity", qreal(0)); + state2->assignProperty(p4, "opacity", qreal(1)); + state2->assignProperty(p5, "opacity", qreal(1)); + state2->assignProperty(p6, "opacity", qreal(1)); + + // State 3 + state3->assignProperty(button, "text", "Switch to state 1"); + state3->assignProperty(p1, "pos", QPointF(0, 5)); + state3->assignProperty(p2, "pos", QPointF(0, 5 + 64 + 5)); + state3->assignProperty(p3, "pos", QPointF(5, 5 + (64 + 5) + 64)); + state3->assignProperty(p4, "pos", QPointF(5 + 64 + 5, 5)); + state3->assignProperty(p5, "pos", QPointF(5 + 64 + 5, 5 + 64 + 5)); + state3->assignProperty(p6, "pos", QPointF(5 + 64 + 5, 5 + (64 + 5) + 64)); + state3->assignProperty(widget, "geometry", QRectF(138, 5, 400 - 138, 200)); + state3->assignProperty(box, "geometry", QRect(5, 205, 400, 90)); + state3->assignProperty(p1, "opacity", qreal(1)); + state3->assignProperty(p2, "opacity", qreal(1)); + state3->assignProperty(p3, "opacity", qreal(1)); + state3->assignProperty(p4, "opacity", qreal(1)); + state3->assignProperty(p5, "opacity", qreal(1)); + state3->assignProperty(p6, "opacity", qreal(1)); + + QAbstractTransition *t1 = state1->addTransition(button, &QAbstractButton::clicked, state2); + QSequentialAnimationGroup *animation1SubGroup = new QSequentialAnimationGroup; + animation1SubGroup->addPause(250); + animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry")); + t1->addAnimation(animation1SubGroup); + t1->addAnimation(new QPropertyAnimation(widget, "geometry")); + t1->addAnimation(new QPropertyAnimation(p1, "pos")); + t1->addAnimation(new QPropertyAnimation(p2, "pos")); + t1->addAnimation(new QPropertyAnimation(p3, "pos")); + t1->addAnimation(new QPropertyAnimation(p4, "pos")); + t1->addAnimation(new QPropertyAnimation(p5, "pos")); + t1->addAnimation(new QPropertyAnimation(p6, "pos")); + t1->addAnimation(new QPropertyAnimation(p1, "rotation")); + t1->addAnimation(new QPropertyAnimation(p2, "rotation")); + t1->addAnimation(new QPropertyAnimation(p3, "rotation")); + t1->addAnimation(new QPropertyAnimation(p4, "rotation")); + t1->addAnimation(new QPropertyAnimation(p5, "rotation")); + t1->addAnimation(new QPropertyAnimation(p6, "rotation")); + t1->addAnimation(new QPropertyAnimation(p1, "opacity")); + t1->addAnimation(new QPropertyAnimation(p2, "opacity")); + t1->addAnimation(new QPropertyAnimation(p3, "opacity")); + t1->addAnimation(new QPropertyAnimation(p4, "opacity")); + t1->addAnimation(new QPropertyAnimation(p5, "opacity")); + t1->addAnimation(new QPropertyAnimation(p6, "opacity")); + + QAbstractTransition *t2 = state2->addTransition(button, &QAbstractButton::clicked, state3); + t2->addAnimation(new QPropertyAnimation(box, "geometry")); + t2->addAnimation(new QPropertyAnimation(widget, "geometry")); + t2->addAnimation(new QPropertyAnimation(p1, "pos")); + t2->addAnimation(new QPropertyAnimation(p2, "pos")); + t2->addAnimation(new QPropertyAnimation(p3, "pos")); + t2->addAnimation(new QPropertyAnimation(p4, "pos")); + t2->addAnimation(new QPropertyAnimation(p5, "pos")); + t2->addAnimation(new QPropertyAnimation(p6, "pos")); + t2->addAnimation(new QPropertyAnimation(p1, "rotation")); + t2->addAnimation(new QPropertyAnimation(p2, "rotation")); + t2->addAnimation(new QPropertyAnimation(p3, "rotation")); + t2->addAnimation(new QPropertyAnimation(p4, "rotation")); + t2->addAnimation(new QPropertyAnimation(p5, "rotation")); + t2->addAnimation(new QPropertyAnimation(p6, "rotation")); + t2->addAnimation(new QPropertyAnimation(p1, "opacity")); + t2->addAnimation(new QPropertyAnimation(p2, "opacity")); + t2->addAnimation(new QPropertyAnimation(p3, "opacity")); + t2->addAnimation(new QPropertyAnimation(p4, "opacity")); + t2->addAnimation(new QPropertyAnimation(p5, "opacity")); + t2->addAnimation(new QPropertyAnimation(p6, "opacity")); + + QAbstractTransition *t3 = state3->addTransition(button, &QAbstractButton::clicked, state1); + t3->addAnimation(new QPropertyAnimation(box, "geometry")); + t3->addAnimation(new QPropertyAnimation(widget, "geometry")); + t3->addAnimation(new QPropertyAnimation(p1, "pos")); + t3->addAnimation(new QPropertyAnimation(p2, "pos")); + t3->addAnimation(new QPropertyAnimation(p3, "pos")); + t3->addAnimation(new QPropertyAnimation(p4, "pos")); + t3->addAnimation(new QPropertyAnimation(p5, "pos")); + t3->addAnimation(new QPropertyAnimation(p6, "pos")); + t3->addAnimation(new QPropertyAnimation(p1, "rotation")); + t3->addAnimation(new QPropertyAnimation(p2, "rotation")); + t3->addAnimation(new QPropertyAnimation(p3, "rotation")); + t3->addAnimation(new QPropertyAnimation(p4, "rotation")); + t3->addAnimation(new QPropertyAnimation(p5, "rotation")); + t3->addAnimation(new QPropertyAnimation(p6, "rotation")); + t3->addAnimation(new QPropertyAnimation(p1, "opacity")); + t3->addAnimation(new QPropertyAnimation(p2, "opacity")); + t3->addAnimation(new QPropertyAnimation(p3, "opacity")); + t3->addAnimation(new QPropertyAnimation(p4, "opacity")); + t3->addAnimation(new QPropertyAnimation(p5, "opacity")); + t3->addAnimation(new QPropertyAnimation(p6, "opacity")); + + machine.start(); + + GraphicsView view(&scene); + + view.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/widgets/animation/states/states.pro b/examples/widgets/animation/states/states.pro new file mode 100644 index 0000000..33e572e --- /dev/null +++ b/examples/widgets/animation/states/states.pro @@ -0,0 +1,8 @@ +QT += statemachine widgets + +SOURCES += main.cpp +RESOURCES += states.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/states +INSTALLS += target diff --git a/examples/widgets/animation/states/states.qrc b/examples/widgets/animation/states/states.qrc new file mode 100644 index 0000000..60ab3f7 --- /dev/null +++ b/examples/widgets/animation/states/states.qrc @@ -0,0 +1,10 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>accessories-dictionary.png</file> + <file>akregator.png</file> + <file>digikam.png</file> + <file>help-browser.png</file> + <file>k3b.png</file> + <file>kchart.png</file> +</qresource> +</RCC> diff --git a/examples/widgets/animation/stickman/CMakeLists.txt b/examples/widgets/animation/stickman/CMakeLists.txt new file mode 100644 index 0000000..dbf49e4 --- /dev/null +++ b/examples/widgets/animation/stickman/CMakeLists.txt @@ -0,0 +1,58 @@ +# Generated from stickman.pro. + +cmake_minimum_required(VERSION 3.14) +project(stickman LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/stickman") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(stickman + animation.cpp animation.h + graphicsview.cpp graphicsview.h + lifecycle.cpp lifecycle.h + main.cpp + node.cpp node.h + rectbutton.cpp rectbutton.h + stickman.cpp stickman.h +) +target_link_libraries(stickman PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set(stickman_resource_files + "animations/chilling.bin" + "animations/dancing.bin" + "animations/dead.bin" + "animations/jumping.bin" +) + +qt6_add_resources(stickman "stickman" + PREFIX + "/" + FILES + ${stickman_resource_files} +) + +install(TARGETS stickman + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/stickman/animation.cpp b/examples/widgets/animation/stickman/animation.cpp new file mode 100644 index 0000000..77a1875 --- /dev/null +++ b/examples/widgets/animation/stickman/animation.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "animation.h" + +#include <QIODevice> +#include <QDataStream> + +class Frame +{ +public: + Frame() = default; + + int nodeCount() const + { + return m_nodePositions.size(); + } + + void setNodeCount(int nodeCount) + { + m_nodePositions.resize(nodeCount); + } + + QPointF nodePos(int idx) const + { + return m_nodePositions.at(idx); + } + + void setNodePos(int idx, const QPointF &pos) + { + m_nodePositions[idx] = pos; + } + +private: + QList<QPointF> m_nodePositions; +}; + +Animation::Animation() : m_currentFrame(0) +{ + m_frames.append(new Frame); +} + +Animation::~Animation() +{ + qDeleteAll(m_frames); +} + +void Animation::setTotalFrames(int totalFrames) +{ + while (m_frames.size() < totalFrames) + m_frames.append(new Frame); + + while (totalFrames < m_frames.size()) + delete m_frames.takeLast(); + + setCurrentFrame(m_currentFrame); +} + +int Animation::totalFrames() const +{ + return m_frames.size(); +} + +void Animation::setCurrentFrame(int currentFrame) +{ + m_currentFrame = qBound(0, currentFrame, totalFrames() - 1); +} + +int Animation::currentFrame() const +{ + return m_currentFrame; +} + +void Animation::setNodeCount(int nodeCount) +{ + Frame *frame = m_frames.at(m_currentFrame); + frame->setNodeCount(nodeCount); +} + +int Animation::nodeCount() const +{ + Frame *frame = m_frames.at(m_currentFrame); + return frame->nodeCount(); +} + +void Animation::setNodePos(int idx, const QPointF &pos) +{ + Frame *frame = m_frames.at(m_currentFrame); + frame->setNodePos(idx, pos); +} + +QPointF Animation::nodePos(int idx) const +{ + Frame *frame = m_frames.at(m_currentFrame); + return frame->nodePos(idx); +} + +QString Animation::name() const +{ + return m_name; +} + +void Animation::setName(const QString &name) +{ + m_name = name; +} + +void Animation::save(QIODevice *device) const +{ + QDataStream stream(device); + stream << m_name; + stream << m_frames.size(); + for (const Frame *frame : qAsConst(m_frames)) { + stream << frame->nodeCount(); + for (int i = 0; i < frame->nodeCount(); ++i) + stream << frame->nodePos(i); + } +} + +void Animation::load(QIODevice *device) +{ + qDeleteAll(m_frames); + m_frames.clear(); + + QDataStream stream(device); + stream >> m_name; + + int frameCount; + stream >> frameCount; + + for (int i = 0; i < frameCount; ++i) { + int nodeCount; + stream >> nodeCount; + + Frame *frame = new Frame; + frame->setNodeCount(nodeCount); + + for (int j = 0; j < nodeCount; ++j) { + QPointF pos; + stream >> pos; + frame->setNodePos(j, pos); + } + + m_frames.append(frame); + } +} diff --git a/examples/widgets/animation/stickman/animation.h b/examples/widgets/animation/stickman/animation.h new file mode 100644 index 0000000..93caff4 --- /dev/null +++ b/examples/widgets/animation/stickman/animation.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef ANIMATION_H +#define ANIMATION_H + +#include <QPointF> +#include <QString> +#include <QList> + +class Frame; +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE +class Animation +{ +public: + Animation(); + ~Animation(); + + void setTotalFrames(int totalFrames); + int totalFrames() const; + + void setCurrentFrame(int currentFrame); + int currentFrame() const; + + void setNodeCount(int nodeCount); + int nodeCount() const; + + void setNodePos(int idx, const QPointF &pos); + QPointF nodePos(int idx) const; + + QString name() const; + void setName(const QString &name); + + void save(QIODevice *device) const; + void load(QIODevice *device); + +private: + QString m_name; + QList<Frame *> m_frames; + int m_currentFrame; +}; + +#endif diff --git a/examples/widgets/animation/stickman/animations/chilling.bin b/examples/widgets/animation/stickman/animations/chilling.bin Binary files differnew file mode 100644 index 0000000..a81fc7a --- /dev/null +++ b/examples/widgets/animation/stickman/animations/chilling.bin diff --git a/examples/widgets/animation/stickman/animations/dancing.bin b/examples/widgets/animation/stickman/animations/dancing.bin Binary files differnew file mode 100644 index 0000000..462f66f --- /dev/null +++ b/examples/widgets/animation/stickman/animations/dancing.bin diff --git a/examples/widgets/animation/stickman/animations/dead.bin b/examples/widgets/animation/stickman/animations/dead.bin Binary files differnew file mode 100644 index 0000000..9859b4b --- /dev/null +++ b/examples/widgets/animation/stickman/animations/dead.bin diff --git a/examples/widgets/animation/stickman/animations/jumping.bin b/examples/widgets/animation/stickman/animations/jumping.bin Binary files differnew file mode 100644 index 0000000..12661a1 --- /dev/null +++ b/examples/widgets/animation/stickman/animations/jumping.bin diff --git a/examples/widgets/animation/stickman/graphicsview.cpp b/examples/widgets/animation/stickman/graphicsview.cpp new file mode 100644 index 0000000..0f5800c --- /dev/null +++ b/examples/widgets/animation/stickman/graphicsview.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "graphicsview.h" +#include "stickman.h" + +#include <QKeyEvent> +#include <QGraphicsScene> + +void GraphicsView::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) + close(); + emit keyPressed(Qt::Key(e->key())); +} + +void GraphicsView::resizeEvent(QResizeEvent *e) +{ + fitInView(scene()->sceneRect()); + QGraphicsView::resizeEvent(e); +} diff --git a/examples/widgets/animation/stickman/graphicsview.h b/examples/widgets/animation/stickman/graphicsview.h new file mode 100644 index 0000000..29f4c62 --- /dev/null +++ b/examples/widgets/animation/stickman/graphicsview.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef GRAPHICSVIEW_H +#define GRAPHICSVIEW_H + +#include <QGraphicsView> + +class GraphicsView: public QGraphicsView +{ + Q_OBJECT +public: + using QGraphicsView::QGraphicsView; + +protected: + void resizeEvent(QResizeEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; + +signals: + void keyPressed(int key); +}; + +#endif diff --git a/examples/widgets/animation/stickman/lifecycle.cpp b/examples/widgets/animation/stickman/lifecycle.cpp new file mode 100644 index 0000000..5ad284c --- /dev/null +++ b/examples/widgets/animation/stickman/lifecycle.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "lifecycle.h" +#include "stickman.h" +#include "node.h" +#include "animation.h" +#include "graphicsview.h" + +#include <QEventTransition> +#include <QFile> +#include <QParallelAnimationGroup> +#include <QPropertyAnimation> +#include <QRandomGenerator> +#include <QSignalTransition> +#include <QState> +#include <QStateMachine> +#include <QTimer> + +class KeyPressTransition: public QSignalTransition +{ +public: + KeyPressTransition(GraphicsView *receiver, Qt::Key key) + : QSignalTransition(receiver, &GraphicsView::keyPressed), m_key(key) + { + } + KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target) + : QSignalTransition(receiver, &GraphicsView::keyPressed), m_key(key) + { + setTargetState(target); + } + + bool eventTest(QEvent *e) override + { + if (QSignalTransition::eventTest(e)) { + QVariant key = static_cast<QStateMachine::SignalEvent*>(e)->arguments().at(0); + return (key.toInt() == int(m_key)); + } + + return false; + } +private: + Qt::Key m_key; +}; + +//! [4] +class LightningStrikesTransition: public QEventTransition +{ +public: + LightningStrikesTransition(QAbstractState *target) + : QEventTransition(this, QEvent::Timer) + { + setTargetState(target); + startTimer(1000); + } + + bool eventTest(QEvent *e) override + { + return QEventTransition::eventTest(e) && QRandomGenerator::global()->bounded(50) == 0; + } +}; +//! [4] + +LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) + : m_stickMan(stickMan), m_keyReceiver(keyReceiver) +{ + // Create animation group to be used for all transitions + m_animationGroup = new QParallelAnimationGroup(); + const int stickManNodeCount = m_stickMan->nodeCount(); + for (int i = 0; i < stickManNodeCount; ++i) { + QPropertyAnimation *pa = new QPropertyAnimation(m_stickMan->node(i), "pos"); + m_animationGroup->addAnimation(pa); + } + + // Set up initial state graph +//! [3] + m_machine = new QStateMachine(); + m_machine->addDefaultAnimation(m_animationGroup); +//! [3] + + m_alive = new QState(m_machine); + m_alive->setObjectName("alive"); + + // Make it blink when lightning strikes before entering dead animation + QState *lightningBlink = new QState(m_machine); + lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", QColor(Qt::white)); + lightningBlink->assignProperty(m_stickMan, "penColor", QColor(Qt::black)); + lightningBlink->assignProperty(m_stickMan, "fillColor", QColor(Qt::white)); + lightningBlink->assignProperty(m_stickMan, "isDead", true); + +//! [5] + QTimer *timer = new QTimer(lightningBlink); + timer->setSingleShot(true); + timer->setInterval(100); + QObject::connect(lightningBlink, &QAbstractState::entered, + timer, QOverload<>::of(&QTimer::start)); + QObject::connect(lightningBlink, &QAbstractState::exited, + timer, &QTimer::stop); +//! [5] + + m_dead = new QState(m_machine); + m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", QColor(Qt::black)); + m_dead->assignProperty(m_stickMan, "penColor", QColor(Qt::white)); + m_dead->assignProperty(m_stickMan, "fillColor", QColor(Qt::black)); + m_dead->setObjectName("dead"); + + // Idle state (sets no properties) + m_idle = new QState(m_alive); + m_idle->setObjectName("idle"); + + m_alive->setInitialState(m_idle); + + // Lightning strikes at random + m_alive->addTransition(new LightningStrikesTransition(lightningBlink)); +//! [0] + lightningBlink->addTransition(timer, &QTimer::timeout, m_dead); +//! [0] + + m_machine->setInitialState(m_alive); +} + +void LifeCycle::setDeathAnimation(const QString &fileName) +{ + QState *deathAnimation = makeState(m_dead, fileName); + m_dead->setInitialState(deathAnimation); +} + +void LifeCycle::start() +{ + m_machine->start(); +} + +void LifeCycle::addActivity(const QString &fileName, Qt::Key key, QObject *sender, const char *signal) +{ + QState *state = makeState(m_alive, fileName); + m_alive->addTransition(new KeyPressTransition(m_keyReceiver, key, state)); + + if (sender && signal) + m_alive->addTransition(sender, signal, state); +} + +QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName) +{ + QState *topLevel = new QState(parentState); + + Animation animation; + { + QFile file(animationFileName); + if (file.open(QIODevice::ReadOnly)) + animation.load(&file); + } + + const int frameCount = animation.totalFrames(); + QState *previousState = nullptr; + for (int i = 0; i < frameCount; ++i) { + animation.setCurrentFrame(i); + +//! [1] + QState *frameState = new QState(topLevel); + const int nodeCount = animation.nodeCount(); + for (int j = 0; j < nodeCount; ++j) + frameState->assignProperty(m_stickMan->node(j), "pos", animation.nodePos(j)); +//! [1] + + frameState->setObjectName(QString::fromLatin1("frame %0").arg(i)); + if (previousState == nullptr) + topLevel->setInitialState(frameState); + else +//! [2] + previousState->addTransition(previousState, &QState::propertiesAssigned, frameState); +//! [2] + + previousState = frameState; + } + + // Loop + previousState->addTransition(previousState, &QState::propertiesAssigned, topLevel->initialState()); + + return topLevel; + +} + +LifeCycle::~LifeCycle() +{ + delete m_machine; + delete m_animationGroup; +} diff --git a/examples/widgets/animation/stickman/lifecycle.h b/examples/widgets/animation/stickman/lifecycle.h new file mode 100644 index 0000000..21ab992 --- /dev/null +++ b/examples/widgets/animation/stickman/lifecycle.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef LIFECYCLE_H +#define LIFECYCLE_H + +#include <Qt> + +QT_BEGIN_NAMESPACE +class QAbstractState; +class QAbstractTransition; +class QAnimationGroup; +class QObject; +class QState; +class QStateMachine; +QT_END_NAMESPACE +class GraphicsView; +class StickMan; +class LifeCycle +{ +public: + LifeCycle(StickMan *stickMan, GraphicsView *keyEventReceiver); + ~LifeCycle(); + + void setDeathAnimation(const QString &fileName); + void addActivity(const QString &fileName, Qt::Key key, + QObject *sender = nullptr, const char *signal = nullptr); + + void start(); + +private: + QState *makeState(QState *parentState, const QString &animationFileName); + + StickMan *m_stickMan; + QStateMachine *m_machine; + QAnimationGroup *m_animationGroup; + GraphicsView *m_keyReceiver; + + QState *m_alive; + QState *m_dead; + QState *m_idle; +}; + +#endif diff --git a/examples/widgets/animation/stickman/main.cpp b/examples/widgets/animation/stickman/main.cpp new file mode 100644 index 0000000..5142c4f --- /dev/null +++ b/examples/widgets/animation/stickman/main.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "animation.h" +#include "node.h" +#include "lifecycle.h" +#include "stickman.h" +#include "graphicsview.h" +#include "rectbutton.h" + +#include <QtCore> +#include <QtWidgets> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(stickman); + QApplication app(argc, argv); + + StickMan *stickMan = new StickMan; + stickMan->setDrawSticks(false); + + QGraphicsTextItem *textItem = new QGraphicsTextItem(); + textItem->setHtml("<font color=\"white\"><b>Stickman</b>" + "<p>" + "Tell the stickman what to do!" + "</p>" + "<p><i>" + "<li>Press <font color=\"purple\">J</font> to make the stickman jump.</li>" + "<li>Press <font color=\"purple\">D</font> to make the stickman dance.</li>" + "<li>Press <font color=\"purple\">C</font> to make him chill out.</li>" + "<li>When you are done, press <font color=\"purple\">Escape</font>.</li>" + "</i></p>" + "<p>If he is unlucky, the stickman will get struck by lightning, and never jump, dance or chill out again." + "</p></font>"); + qreal w = textItem->boundingRect().width(); + QRectF stickManBoundingRect = stickMan->mapToScene(stickMan->boundingRect()).boundingRect(); + textItem->setPos(-w / 2.0, stickManBoundingRect.bottom() + 25.0); + + QGraphicsScene scene; + scene.addItem(stickMan); + + scene.addItem(textItem); + scene.setBackgroundBrush(Qt::black); + + GraphicsView view; + view.setRenderHints(QPainter::Antialiasing); + view.setTransformationAnchor(QGraphicsView::NoAnchor); + view.setScene(&scene); + + QRectF sceneRect = scene.sceneRect(); + // making enough room in the scene for stickman to jump and die + view.resize(sceneRect.width() + 100, sceneRect.height() + 100); + view.setSceneRect(sceneRect); + + view.show(); + view.setFocus(); + + LifeCycle cycle(stickMan, &view); + cycle.setDeathAnimation(":/animations/dead.bin"); + + cycle.addActivity(":/animations/jumping.bin", Qt::Key_J); + cycle.addActivity(":/animations/dancing.bin", Qt::Key_D); + cycle.addActivity(":/animations/chilling.bin", Qt::Key_C); + + cycle.start(); + + + return app.exec(); +} diff --git a/examples/widgets/animation/stickman/node.cpp b/examples/widgets/animation/stickman/node.cpp new file mode 100644 index 0000000..43a9c93 --- /dev/null +++ b/examples/widgets/animation/stickman/node.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "node.h" +#include "stickman.h" + +#include <QRectF> +#include <QPainter> +#include <QGraphicsSceneMouseEvent> + +Node::Node(const QPointF &pos, QGraphicsItem *parent) + : QGraphicsObject(parent), m_dragging(false) +{ + setPos(pos); + setFlag(QGraphicsItem::ItemSendsGeometryChanges); +} + +Node::~Node() +{ +} + +QRectF Node::boundingRect() const +{ + return QRectF(-6.0, -6.0, 12.0, 12.0); +} + +void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setPen(Qt::white); + painter->drawEllipse(QPointF(0.0, 0.0), 5.0, 5.0); +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionChange) + emit positionChanged(); + + return QGraphicsObject::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *) +{ + m_dragging = true; +} + +void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragging) + setPos(mapToParent(event->pos())); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *) +{ + m_dragging = false; +} diff --git a/examples/widgets/animation/stickman/node.h b/examples/widgets/animation/stickman/node.h new file mode 100644 index 0000000..2b393c6 --- /dev/null +++ b/examples/widgets/animation/stickman/node.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef NODE_H +#define NODE_H + +#include <QGraphicsObject> + +class Node: public QGraphicsObject +{ + Q_OBJECT +public: + explicit Node(const QPointF &pos, QGraphicsItem *parent = nullptr); + ~Node(); + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + +signals: + void positionChanged(); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + + void mousePressEvent(QGraphicsSceneMouseEvent *) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent *) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override; + +private: + bool m_dragging; +}; + +#endif diff --git a/examples/widgets/animation/stickman/rectbutton.cpp b/examples/widgets/animation/stickman/rectbutton.cpp new file mode 100644 index 0000000..5174d0a --- /dev/null +++ b/examples/widgets/animation/stickman/rectbutton.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "rectbutton.h" +#include <QPainter> + +RectButton::RectButton(const QString &buttonText) : m_ButtonText(buttonText) +{ +} + + +void RectButton::mousePressEvent (QGraphicsSceneMouseEvent *) +{ + emit clicked(); +} + + +QRectF RectButton::boundingRect() const +{ + return QRectF(0.0, 0.0, 90.0, 40.0); +} + + +void RectButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */) +{ + painter->setBrush(Qt::gray); + painter->drawRoundedRect(boundingRect(), 5, 5); + + painter->setPen(Qt::white); + painter->drawText(20, 25, m_ButtonText); +} diff --git a/examples/widgets/animation/stickman/rectbutton.h b/examples/widgets/animation/stickman/rectbutton.h new file mode 100644 index 0000000..ee6cd3f --- /dev/null +++ b/examples/widgets/animation/stickman/rectbutton.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef RECTBUTTON_H +#define RECTBUTTON_H + +#include <QGraphicsObject> + +class RectButton : public QGraphicsObject +{ + Q_OBJECT +public: + RectButton(const QString &buttonText); + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + +protected: + void mousePressEvent (QGraphicsSceneMouseEvent *event) override; + +signals: + void clicked(); + +private: + QString m_ButtonText; +}; + +#endif // RECTBUTTON_H diff --git a/examples/widgets/animation/stickman/stickman.cpp b/examples/widgets/animation/stickman/stickman.cpp new file mode 100644 index 0000000..3f373b6 --- /dev/null +++ b/examples/widgets/animation/stickman/stickman.cpp @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "stickman.h" +#include "node.h" + +#include <QPainter> +#include <QtMath> + +static constexpr qreal Coords[NodeCount * 2] = { + 0.0, -150.0, // head, #0 + + 0.0, -100.0, // body pentagon, top->bottom, left->right, #1 - 5 + -50.0, -50.0, + 50.0, -50.0, + -25.0, 50.0, + 25.0, 50.0, + + -100.0, 0.0, // right arm, #6 - 7 + -125.0, 50.0, + + 100.0, 0.0, // left arm, #8 - 9 + 125.0, 50.0, + + -35.0, 75.0, // lower body, #10 - 11 + 35.0, 75.0, + + -25.0, 200.0, // right leg, #12 - 13 + -30.0, 300.0, + + 25.0, 200.0, // left leg, #14 - 15 + 30.0, 300.0 + +}; + +static constexpr int Bones[BoneCount * 2] = { + 0, 1, // neck + + 1, 2, // body + 1, 3, + 1, 4, + 1, 5, + 2, 3, + 2, 4, + 2, 5, + 3, 4, + 3, 5, + 4, 5, + + 2, 6, // right arm + 6, 7, + + 3, 8, // left arm + 8, 9, + + 4, 10, // lower body + 4, 11, + 5, 10, + 5, 11, + 10, 11, + + 10, 12, // right leg + 12, 13, + + 11, 14, // left leg + 14, 15 + +}; + +StickMan::StickMan() +{ + // Set up start position of limbs + for (int i = 0; i < NodeCount; ++i) { + m_nodes[i] = new Node(QPointF(Coords[i * 2], Coords[i * 2 + 1]), this); + connect(m_nodes[i], &Node::positionChanged, this, &StickMan::childPositionChanged); + } + + for (int i = 0; i < BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF dist = node1->pos() - node2->pos(); + m_perfectBoneLengths[i] = sqrt(pow(dist.x(), 2) + pow(dist.y(), 2)); + } + + startTimer(10); +} + +void StickMan::childPositionChanged() +{ + prepareGeometryChange(); +} + +void StickMan::setDrawSticks(bool on) +{ + m_sticks = on; + for (int i = 0; i < nodeCount(); ++i) { + Node *node = m_nodes[i]; + node->setVisible(on); + } +} + +QRectF StickMan::boundingRect() const +{ + // account for head radius=50.0 plus pen which is 5.0 + return childrenBoundingRect().adjusted(-55.0, -55.0, 55.0, 55.0); +} + +int StickMan::nodeCount() const +{ + return NodeCount; +} + +Node *StickMan::node(int idx) const +{ + if (idx >= 0 && idx < NodeCount) + return m_nodes[idx]; + return nullptr; +} + +void StickMan::timerEvent(QTimerEvent *) +{ + update(); +} + +void StickMan::stabilize() +{ + static const qreal threshold = 0.001; + + for (int i = 0; i < BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF pos1 = node1->pos(); + QPointF pos2 = node2->pos(); + + QPointF dist = pos1 - pos2; + qreal length = sqrt(pow(dist.x(),2) + pow(dist.y(),2)); + qreal diff = (length - m_perfectBoneLengths[i]) / length; + + QPointF p = dist * (0.5 * diff); + if (p.x() > threshold && p.y() > threshold) { + pos1 -= p; + pos2 += p; + + node1->setPos(pos1); + node2->setPos(pos2); + } + } +} + +QPointF StickMan::posFor(int idx) const +{ + return m_nodes[idx]->pos(); +} + +//#include <QTime> +void StickMan::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + /* static int frames = 0; + static QTime time; + if (frames++ % 100 == 0) { + frames = 1; + time.restart(); + } + + if (time.elapsed() > 0) { + painter->setPen(Qt::white); + painter->drawText(0, 0, QString::number(frames / (time.elapsed() / 1000.0))); + }*/ + + stabilize(); + if (m_sticks) { + painter->setPen(Qt::white); + for (int i = 0; i < BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + painter->drawLine(node1->pos(), node2->pos()); + } + } else { + // first bone is neck and will be used for head + + QPainterPath path; + path.moveTo(posFor(0)); + path.lineTo(posFor(1)); + + // right arm + path.lineTo(posFor(2)); + path.lineTo(posFor(6)); + path.lineTo(posFor(7)); + + // left arm + path.moveTo(posFor(3)); + path.lineTo(posFor(8)); + path.lineTo(posFor(9)); + + // body + path.moveTo(posFor(2)); + path.lineTo(posFor(4)); + path.lineTo(posFor(10)); + path.lineTo(posFor(11)); + path.lineTo(posFor(5)); + path.lineTo(posFor(3)); + path.lineTo(posFor(1)); + + // right leg + path.moveTo(posFor(10)); + path.lineTo(posFor(12)); + path.lineTo(posFor(13)); + + // left leg + path.moveTo(posFor(11)); + path.lineTo(posFor(14)); + path.lineTo(posFor(15)); + + painter->setPen(QPen(m_penColor, 5.0, Qt::SolidLine, Qt::RoundCap)); + painter->drawPath(path); + + { + int n1 = Bones[0]; + int n2 = Bones[1]; + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF dist = node2->pos() - node1->pos(); + + qreal sinAngle = dist.x() / sqrt(pow(dist.x(), 2) + pow(dist.y(), 2)); + qreal angle = qRadiansToDegrees(asin(sinAngle)); + + QPointF headPos = node1->pos(); + painter->translate(headPos); + painter->rotate(-angle); + + painter->setBrush(m_fillColor); + painter->drawEllipse(QPointF(0,0), 50.0, 50.0); + + painter->setBrush(m_penColor); + painter->setPen(QPen(m_penColor, 2.5, Qt::SolidLine, Qt::RoundCap)); + + // eyes + if (m_isDead) { + painter->drawLine(-30.0, -30.0, -20.0, -20.0); + painter->drawLine(-20.0, -30.0, -30.0, -20.0); + + painter->drawLine(20.0, -30.0, 30.0, -20.0); + painter->drawLine(30.0, -30.0, 20.0, -20.0); + } else { + painter->drawChord(QRectF(-30.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16); + painter->drawChord(QRectF(5.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16); + } + + // mouth + if (m_isDead) { + painter->drawLine(-28.0, 2.0, 29.0, 2.0); + } else { + painter->setBrush(QColor(128, 0, 64 )); + painter->drawChord(QRectF(-28.0, 2.0-55.0/2.0, 57.0, 55.0), 0.0, -180.0*16); + } + + // pupils + if (!m_isDead) { + painter->setPen(QPen(m_fillColor, 1.0, Qt::SolidLine, Qt::RoundCap)); + painter->setBrush(m_fillColor); + painter->drawEllipse(QPointF(-12.0, -25.0), 5.0, 5.0); + painter->drawEllipse(QPointF(22.0, -25.0), 5.0, 5.0); + } + } + } +} + + + diff --git a/examples/widgets/animation/stickman/stickman.h b/examples/widgets/animation/stickman/stickman.h new file mode 100644 index 0000000..63c02ab --- /dev/null +++ b/examples/widgets/animation/stickman/stickman.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef STICKMAN_H +#define STICKMAN_H + +#include <QGraphicsObject> + +static const int NodeCount = 16; +static const int BoneCount = 24; + +class Node; +class StickMan: public QGraphicsObject +{ + Q_OBJECT + Q_PROPERTY(QColor penColor WRITE setPenColor READ penColor) + Q_PROPERTY(QColor fillColor WRITE setFillColor READ fillColor) + Q_PROPERTY(bool isDead WRITE setIsDead READ isDead) +public: + StickMan(); + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + + int nodeCount() const; + Node *node(int idx) const; + + void setDrawSticks(bool on); + bool drawSticks() const { return m_sticks; } + + QColor penColor() const { return m_penColor; } + void setPenColor(const QColor &color) { m_penColor = color; } + + QColor fillColor() const { return m_fillColor; } + void setFillColor(const QColor &color) { m_fillColor = color; } + + bool isDead() const { return m_isDead; } + void setIsDead(bool isDead) { m_isDead = isDead; } + +public slots: + void stabilize(); + void childPositionChanged(); + +protected: + void timerEvent(QTimerEvent *e) override; + +private: + + QPointF posFor(int idx) const; + + Node *m_nodes[NodeCount]; + qreal m_perfectBoneLengths[BoneCount]; + + bool m_sticks = true; + bool m_isDead = false; + + QColor m_penColor = Qt::white; + QColor m_fillColor = Qt::black; +}; + +#endif // STICKMAN_H diff --git a/examples/widgets/animation/stickman/stickman.pro b/examples/widgets/animation/stickman/stickman.pro new file mode 100644 index 0000000..7d0eb12 --- /dev/null +++ b/examples/widgets/animation/stickman/stickman.pro @@ -0,0 +1,21 @@ +QT += statemachine widgets + +HEADERS += stickman.h \ + animation.h \ + node.h \ + lifecycle.h \ + graphicsview.h \ + rectbutton.h +SOURCES += main.cpp \ + stickman.cpp \ + animation.cpp \ + node.cpp \ + lifecycle.cpp \ + graphicsview.cpp \ + rectbutton.cpp + +RESOURCES += stickman.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/stickman +INSTALLS += target diff --git a/examples/widgets/animation/stickman/stickman.qrc b/examples/widgets/animation/stickman/stickman.qrc new file mode 100644 index 0000000..4cf3ba3 --- /dev/null +++ b/examples/widgets/animation/stickman/stickman.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>animations/chilling.bin</file> + <file>animations/dancing.bin</file> + <file>animations/dead.bin</file> + <file>animations/jumping.bin</file> +</qresource> +</RCC> diff --git a/examples/widgets/animation/sub-attaq/.prev_CMakeLists.txt b/examples/widgets/animation/sub-attaq/.prev_CMakeLists.txt new file mode 100644 index 0000000..4077a91 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/.prev_CMakeLists.txt @@ -0,0 +1,197 @@ +# Generated from sub-attaq.pro. + +cmake_minimum_required(VERSION 3.14) +project(sub-attaq LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/sub-attaq") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(sub-attaq + animationmanager.cpp animationmanager.h + boat.cpp boat.h boat_p.h + bomb.cpp bomb.h + graphicsscene.cpp graphicsscene.h + main.cpp + mainwindow.cpp mainwindow.h + pixmapitem.cpp pixmapitem.h + progressitem.cpp progressitem.h + qanimationstate.cpp qanimationstate.h + states.cpp states.h + submarine.cpp submarine.h submarine_p.h + textinformationitem.cpp textinformationitem.h + torpedo.cpp torpedo.h +) +target_link_libraries(sub-attaq PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set_source_files_properties("pics/big/background.png" + PROPERTIES QT_RESOURCE_ALIAS "big/background" +) +set_source_files_properties("pics/big/boat.png" + PROPERTIES QT_RESOURCE_ALIAS "big/boat" +) +set_source_files_properties("pics/big/bomb.png" + PROPERTIES QT_RESOURCE_ALIAS "big/bomb" +) +set_source_files_properties("pics/big/explosion/boat/step1.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step1" +) +set_source_files_properties("pics/big/explosion/boat/step2.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step2" +) +set_source_files_properties("pics/big/explosion/boat/step3.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step3" +) +set_source_files_properties("pics/big/explosion/boat/step4.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step4" +) +set_source_files_properties("pics/big/explosion/submarine/step1.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step1" +) +set_source_files_properties("pics/big/explosion/submarine/step2.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step2" +) +set_source_files_properties("pics/big/explosion/submarine/step3.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step3" +) +set_source_files_properties("pics/big/explosion/submarine/step4.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step4" +) +set_source_files_properties("pics/big/submarine.png" + PROPERTIES QT_RESOURCE_ALIAS "big/submarine" +) +set_source_files_properties("pics/big/surface.png" + PROPERTIES QT_RESOURCE_ALIAS "big/surface" +) +set_source_files_properties("pics/big/torpedo.png" + PROPERTIES QT_RESOURCE_ALIAS "big/torpedo" +) +set_source_files_properties("pics/scalable/boat.svg" + PROPERTIES QT_RESOURCE_ALIAS "boat" +) +set_source_files_properties("pics/scalable/sub-attaq.svg" + PROPERTIES QT_RESOURCE_ALIAS "all" +) +set_source_files_properties("pics/scalable/submarine.svg" + PROPERTIES QT_RESOURCE_ALIAS "submarine" +) +set_source_files_properties("pics/scalable/torpedo.svg" + PROPERTIES QT_RESOURCE_ALIAS "torpedo" +) +set_source_files_properties("pics/small/background.png" + PROPERTIES QT_RESOURCE_ALIAS "small/background" +) +set_source_files_properties("pics/small/boat.png" + PROPERTIES QT_RESOURCE_ALIAS "small/boat" +) +set_source_files_properties("pics/small/bomb.png" + PROPERTIES QT_RESOURCE_ALIAS "small/bomb" +) +set_source_files_properties("pics/small/submarine.png" + PROPERTIES QT_RESOURCE_ALIAS "small/submarine" +) +set_source_files_properties("pics/small/surface.png" + PROPERTIES QT_RESOURCE_ALIAS "small/surface" +) +set_source_files_properties("pics/small/torpedo.png" + PROPERTIES QT_RESOURCE_ALIAS "small/torpedo" +) +set_source_files_properties("pics/welcome/logo-a.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-a" +) +set_source_files_properties("pics/welcome/logo-a2.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-a2" +) +set_source_files_properties("pics/welcome/logo-b.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-b" +) +set_source_files_properties("pics/welcome/logo-dash.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-dash" +) +set_source_files_properties("pics/welcome/logo-excl.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-excl" +) +set_source_files_properties("pics/welcome/logo-q.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-q" +) +set_source_files_properties("pics/welcome/logo-s.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-s" +) +set_source_files_properties("pics/welcome/logo-t.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-t" +) +set_source_files_properties("pics/welcome/logo-t2.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-t2" +) +set_source_files_properties("pics/welcome/logo-u.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-u" +) +set(subattaq_resource_files + "data.xml" + "pics/big/background.png" + "pics/big/boat.png" + "pics/big/bomb.png" + "pics/big/explosion/boat/step1.png" + "pics/big/explosion/boat/step2.png" + "pics/big/explosion/boat/step3.png" + "pics/big/explosion/boat/step4.png" + "pics/big/explosion/submarine/step1.png" + "pics/big/explosion/submarine/step2.png" + "pics/big/explosion/submarine/step3.png" + "pics/big/explosion/submarine/step4.png" + "pics/big/submarine.png" + "pics/big/surface.png" + "pics/big/torpedo.png" + "pics/scalable/boat.svg" + "pics/scalable/sub-attaq.svg" + "pics/scalable/submarine.svg" + "pics/scalable/torpedo.svg" + "pics/small/background.png" + "pics/small/boat.png" + "pics/small/bomb.png" + "pics/small/submarine.png" + "pics/small/surface.png" + "pics/small/torpedo.png" + "pics/welcome/logo-a.png" + "pics/welcome/logo-a2.png" + "pics/welcome/logo-b.png" + "pics/welcome/logo-dash.png" + "pics/welcome/logo-excl.png" + "pics/welcome/logo-q.png" + "pics/welcome/logo-s.png" + "pics/welcome/logo-t.png" + "pics/welcome/logo-t2.png" + "pics/welcome/logo-u.png" +) + +qt6_add_resources(sub-attaq "subattaq" + PREFIX + "/" + FILES + ${subattaq_resource_files} +) + +install(TARGETS sub-attaq + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/sub-attaq/CMakeLists.txt b/examples/widgets/animation/sub-attaq/CMakeLists.txt new file mode 100644 index 0000000..00e5df5 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/CMakeLists.txt @@ -0,0 +1,198 @@ +# Generated from sub-attaq.pro. + +cmake_minimum_required(VERSION 3.14) +project(sub-attaq LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/animation/sub-attaq") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) +find_package(Qt6 COMPONENTS OpenGL) # special case + +add_qt_gui_executable(sub-attaq + animationmanager.cpp animationmanager.h + boat.cpp boat.h boat_p.h + bomb.cpp bomb.h + graphicsscene.cpp graphicsscene.h + main.cpp + mainwindow.cpp mainwindow.h + pixmapitem.cpp pixmapitem.h + progressitem.cpp progressitem.h + qanimationstate.cpp qanimationstate.h + states.cpp states.h + submarine.cpp submarine.h submarine_p.h + textinformationitem.cpp textinformationitem.h + torpedo.cpp torpedo.h +) +target_link_libraries(sub-attaq PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set_source_files_properties("pics/big/background.png" + PROPERTIES QT_RESOURCE_ALIAS "big/background" +) +set_source_files_properties("pics/big/boat.png" + PROPERTIES QT_RESOURCE_ALIAS "big/boat" +) +set_source_files_properties("pics/big/bomb.png" + PROPERTIES QT_RESOURCE_ALIAS "big/bomb" +) +set_source_files_properties("pics/big/explosion/boat/step1.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step1" +) +set_source_files_properties("pics/big/explosion/boat/step2.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step2" +) +set_source_files_properties("pics/big/explosion/boat/step3.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step3" +) +set_source_files_properties("pics/big/explosion/boat/step4.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/boat/step4" +) +set_source_files_properties("pics/big/explosion/submarine/step1.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step1" +) +set_source_files_properties("pics/big/explosion/submarine/step2.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step2" +) +set_source_files_properties("pics/big/explosion/submarine/step3.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step3" +) +set_source_files_properties("pics/big/explosion/submarine/step4.png" + PROPERTIES QT_RESOURCE_ALIAS "big/explosion/submarine/step4" +) +set_source_files_properties("pics/big/submarine.png" + PROPERTIES QT_RESOURCE_ALIAS "big/submarine" +) +set_source_files_properties("pics/big/surface.png" + PROPERTIES QT_RESOURCE_ALIAS "big/surface" +) +set_source_files_properties("pics/big/torpedo.png" + PROPERTIES QT_RESOURCE_ALIAS "big/torpedo" +) +set_source_files_properties("pics/scalable/boat.svg" + PROPERTIES QT_RESOURCE_ALIAS "boat" +) +set_source_files_properties("pics/scalable/sub-attaq.svg" + PROPERTIES QT_RESOURCE_ALIAS "all" +) +set_source_files_properties("pics/scalable/submarine.svg" + PROPERTIES QT_RESOURCE_ALIAS "submarine" +) +set_source_files_properties("pics/scalable/torpedo.svg" + PROPERTIES QT_RESOURCE_ALIAS "torpedo" +) +set_source_files_properties("pics/small/background.png" + PROPERTIES QT_RESOURCE_ALIAS "small/background" +) +set_source_files_properties("pics/small/boat.png" + PROPERTIES QT_RESOURCE_ALIAS "small/boat" +) +set_source_files_properties("pics/small/bomb.png" + PROPERTIES QT_RESOURCE_ALIAS "small/bomb" +) +set_source_files_properties("pics/small/submarine.png" + PROPERTIES QT_RESOURCE_ALIAS "small/submarine" +) +set_source_files_properties("pics/small/surface.png" + PROPERTIES QT_RESOURCE_ALIAS "small/surface" +) +set_source_files_properties("pics/small/torpedo.png" + PROPERTIES QT_RESOURCE_ALIAS "small/torpedo" +) +set_source_files_properties("pics/welcome/logo-a.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-a" +) +set_source_files_properties("pics/welcome/logo-a2.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-a2" +) +set_source_files_properties("pics/welcome/logo-b.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-b" +) +set_source_files_properties("pics/welcome/logo-dash.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-dash" +) +set_source_files_properties("pics/welcome/logo-excl.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-excl" +) +set_source_files_properties("pics/welcome/logo-q.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-q" +) +set_source_files_properties("pics/welcome/logo-s.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-s" +) +set_source_files_properties("pics/welcome/logo-t.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-t" +) +set_source_files_properties("pics/welcome/logo-t2.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-t2" +) +set_source_files_properties("pics/welcome/logo-u.png" + PROPERTIES QT_RESOURCE_ALIAS "logo-u" +) +set(subattaq_resource_files + "data.xml" + "pics/big/background.png" + "pics/big/boat.png" + "pics/big/bomb.png" + "pics/big/explosion/boat/step1.png" + "pics/big/explosion/boat/step2.png" + "pics/big/explosion/boat/step3.png" + "pics/big/explosion/boat/step4.png" + "pics/big/explosion/submarine/step1.png" + "pics/big/explosion/submarine/step2.png" + "pics/big/explosion/submarine/step3.png" + "pics/big/explosion/submarine/step4.png" + "pics/big/submarine.png" + "pics/big/surface.png" + "pics/big/torpedo.png" + "pics/scalable/boat.svg" + "pics/scalable/sub-attaq.svg" + "pics/scalable/submarine.svg" + "pics/scalable/torpedo.svg" + "pics/small/background.png" + "pics/small/boat.png" + "pics/small/bomb.png" + "pics/small/submarine.png" + "pics/small/surface.png" + "pics/small/torpedo.png" + "pics/welcome/logo-a.png" + "pics/welcome/logo-a2.png" + "pics/welcome/logo-b.png" + "pics/welcome/logo-dash.png" + "pics/welcome/logo-excl.png" + "pics/welcome/logo-q.png" + "pics/welcome/logo-s.png" + "pics/welcome/logo-t.png" + "pics/welcome/logo-t2.png" + "pics/welcome/logo-u.png" +) + +qt6_add_resources(sub-attaq "subattaq" + PREFIX + "/" + FILES + ${subattaq_resource_files} +) + +install(TARGETS sub-attaq + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/animation/sub-attaq/animationmanager.cpp b/examples/widgets/animation/sub-attaq/animationmanager.cpp new file mode 100644 index 0000000..261cbd1 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/animationmanager.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "animationmanager.h" + +#include <QAbstractAnimation> + +AnimationManager *AnimationManager::self() +{ + // the universe's only animation manager + static AnimationManager s_instance; + return &s_instance; +} + +void AnimationManager::registerAnimation(QAbstractAnimation *anim) +{ + QObject::connect(anim, &QObject::destroyed, this, &AnimationManager::unregisterAnimation_helper); + animations.append(anim); +} + +void AnimationManager::unregisterAnimation_helper(QObject *obj) +{ + unregisterAnimation(static_cast<QAbstractAnimation*>(obj)); +} + +void AnimationManager::unregisterAnimation(QAbstractAnimation *anim) +{ + QObject::disconnect(anim, &QObject::destroyed, this, &AnimationManager::unregisterAnimation_helper); + animations.removeAll(anim); +} + +void AnimationManager::unregisterAllAnimations() +{ + animations.clear(); +} + +void AnimationManager::pauseAll() +{ + for (QAbstractAnimation *animation : qAsConst(animations)) { + if (animation->state() == QAbstractAnimation::Running) + animation->pause(); + } +} +void AnimationManager::resumeAll() +{ + for (QAbstractAnimation *animation : qAsConst(animations)) { + if (animation->state() == QAbstractAnimation::Paused) + animation->resume(); + } +} diff --git a/examples/widgets/animation/sub-attaq/animationmanager.h b/examples/widgets/animation/sub-attaq/animationmanager.h new file mode 100644 index 0000000..a097e75 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/animationmanager.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef ANIMATIONMANAGER_H +#define ANIMATIONMANAGER_H + +#include <QObject> + +QT_BEGIN_NAMESPACE +class QAbstractAnimation; +QT_END_NAMESPACE + +class AnimationManager : public QObject +{ + Q_OBJECT + AnimationManager() = default; + ~AnimationManager() = default; +public: + void registerAnimation(QAbstractAnimation *anim); + void unregisterAnimation(QAbstractAnimation *anim); + void unregisterAllAnimations(); + static AnimationManager *self(); + +public slots: + void pauseAll(); + void resumeAll(); + +private slots: + void unregisterAnimation_helper(QObject *obj); + +private: + QList<QAbstractAnimation *> animations; +}; + +#endif // ANIMATIONMANAGER_H diff --git a/examples/widgets/animation/sub-attaq/boat.cpp b/examples/widgets/animation/sub-attaq/boat.cpp new file mode 100644 index 0000000..d5fa314 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/boat.cpp @@ -0,0 +1,281 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "boat.h" +#include "boat_p.h" +#include "bomb.h" +#include "graphicsscene.h" +#include "animationmanager.h" +#include "qanimationstate.h" + +//Qt +#include <QFinalState> +#include <QHistoryState> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QState> +#include <QStateMachine> + +static QAbstractAnimation *setupDestroyAnimation(Boat *boat) +{ + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(boat); + for (int i = 1; i <= 4; i++) { + PixmapItem *step = new PixmapItem(QString("explosion/boat/step%1").arg(i),GraphicsScene::Big, boat); + step->setZValue(6); + step->setOpacity(0); + + //fade-in + QPropertyAnimation *anim = new QPropertyAnimation(step, "opacity"); + anim->setEndValue(1); + anim->setDuration(100); + group->insertAnimation(i-1, anim); + + //and then fade-out + QPropertyAnimation *anim2 = new QPropertyAnimation(step, "opacity"); + anim2->setEndValue(0); + anim2->setDuration(100); + group->addAnimation(anim2); + } + + AnimationManager::self()->registerAnimation(group); + return group; +} + + + +Boat::Boat() + : PixmapItem(QString("boat"), GraphicsScene::Big), + speed(0), bombsAlreadyLaunched(0), direction(Boat::None) +{ + setZValue(4); + setFlags(QGraphicsItem::ItemIsFocusable); + + //The movement animation used to animate the boat + movementAnimation = new QPropertyAnimation(this, "pos"); + + //The destroy animation used to explode the boat + destroyAnimation = setupDestroyAnimation(this); + + //We setup the state machine of the boat + machine = new QStateMachine(this); + QState *moving = new QState(machine); + StopState *stopState = new StopState(this, moving); + machine->setInitialState(moving); + moving->setInitialState(stopState); + MoveStateRight *moveStateRight = new MoveStateRight(this, moving); + MoveStateLeft *moveStateLeft = new MoveStateLeft(this, moving); + LaunchStateRight *launchStateRight = new LaunchStateRight(this, machine); + LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this, machine); + + //then setup the transitions for the rightMove state + KeyStopTransition *leftStopRight = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Left); + leftStopRight->setTargetState(stopState); + KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Left); + leftMoveRight->setTargetState(moveStateRight); + KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); + rightMoveRight->setTargetState(moveStateRight); + KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); + rightMoveStop->setTargetState(moveStateRight); + + //then setup the transitions for the leftMove state + KeyStopTransition *rightStopLeft = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Right); + rightStopLeft->setTargetState(stopState); + KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); + rightMoveLeft->setTargetState(moveStateLeft); + KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); + leftMoveLeft->setTargetState(moveStateLeft); + KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); + leftMoveStop->setTargetState(moveStateLeft); + + //We set up the right move state + moveStateRight->addTransition(leftStopRight); + moveStateRight->addTransition(leftMoveRight); + moveStateRight->addTransition(rightMoveRight); + stopState->addTransition(rightMoveStop); + + //We set up the left move state + moveStateLeft->addTransition(rightStopLeft); + moveStateLeft->addTransition(leftMoveLeft); + moveStateLeft->addTransition(rightMoveLeft); + stopState->addTransition(leftMoveStop); + + //The animation is finished, it means we reached the border of the screen, the boat is stopped so we move to the stop state + moveStateLeft->addTransition(movementAnimation, &QAbstractAnimation::finished, stopState); + moveStateRight->addTransition(movementAnimation, &QAbstractAnimation::finished, stopState); + + //We set up the keys for dropping bombs + KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); + upFireLeft->setTargetState(launchStateRight); + KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); + upFireRight->setTargetState(launchStateRight); + KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); + upFireStop->setTargetState(launchStateRight); + KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); + downFireLeft->setTargetState(launchStateLeft); + KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); + downFireRight->setTargetState(launchStateLeft); + KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); + downFireMove->setTargetState(launchStateLeft); + + //We set up transitions for fire up + moveStateRight->addTransition(upFireRight); + moveStateLeft->addTransition(upFireLeft); + stopState->addTransition(upFireStop); + + //We set up transitions for fire down + moveStateRight->addTransition(downFireRight); + moveStateLeft->addTransition(downFireLeft); + stopState->addTransition(downFireMove); + + //Finally the launch state should come back to its original state + QHistoryState *historyState = new QHistoryState(moving); + launchStateLeft->addTransition(historyState); + launchStateRight->addTransition(historyState); + + QFinalState *finalState = new QFinalState(machine); + + //This state play the destroyed animation + QAnimationState *destroyedState = new QAnimationState(machine); + destroyedState->setAnimation(destroyAnimation); + + //Play a nice animation when the boat is destroyed + moving->addTransition(this, &Boat::boatDestroyed, destroyedState); + + //Transition to final state when the destroyed animation is finished + destroyedState->addTransition(destroyedState, &QAnimationState::animationFinished, finalState); + + //The machine has finished to be executed, then the boat is dead + connect(machine, &QState::finished, this, &Boat::boatExecutionFinished); + +} + +void Boat::run() +{ + //We register animations + AnimationManager::self()->registerAnimation(movementAnimation); + AnimationManager::self()->registerAnimation(destroyAnimation); + machine->start(); +} + +void Boat::stop() +{ + movementAnimation->stop(); + machine->stop(); +} + +void Boat::updateBoatMovement() +{ + if (speed == 0 || direction == Boat::None) { + movementAnimation->stop(); + return; + } + + movementAnimation->stop(); + + if (direction == Boat::Left) { + movementAnimation->setEndValue(QPointF(0,y())); + movementAnimation->setDuration(x()/speed*15); + } + else /*if (direction == Boat::Right)*/ { + movementAnimation->setEndValue(QPointF(scene()->width()-size().width(),y())); + movementAnimation->setDuration((scene()->width()-size().width()-x())/speed*15); + } + movementAnimation->start(); +} + +void Boat::destroy() +{ + movementAnimation->stop(); + emit boatDestroyed(); +} + +int Boat::bombsLaunched() const +{ + return bombsAlreadyLaunched; +} + +void Boat::setBombsLaunched(int number) +{ + if (number > MAX_BOMB) { + qWarning("Boat::setBombsLaunched : It impossible to launch that number of bombs"); + return; + } + bombsAlreadyLaunched = number; +} + +int Boat::currentSpeed() const +{ + return speed; +} + +void Boat::setCurrentSpeed(int speed) +{ + if (speed > 3 || speed < 0) { + qWarning("Boat::setCurrentSpeed: The boat can't run on that speed"); + return; + } + this->speed = speed; +} + +enum Boat::Movement Boat::currentDirection() const +{ + return direction; +} + +void Boat::setCurrentDirection(Movement direction) +{ + this->direction = direction; +} + +int Boat::type() const +{ + return Type; +} diff --git a/examples/widgets/animation/sub-attaq/boat.h b/examples/widgets/animation/sub-attaq/boat.h new file mode 100644 index 0000000..22f2f0f --- /dev/null +++ b/examples/widgets/animation/sub-attaq/boat.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef BOAT_H +#define BOAT_H + +#include "pixmapitem.h" + +QT_BEGIN_NAMESPACE +class QVariantAnimation; +class QAbstractAnimation; +class QStateMachine; +QT_END_NAMESPACE + +class Boat : public PixmapItem +{ +Q_OBJECT +public: + enum Movement { + None = 0, + Left, + Right + }; + enum { Type = UserType + 2 }; + Boat(); + void destroy(); + void run(); + void stop(); + + int bombsLaunched() const; + void setBombsLaunched(int number); + + int currentSpeed() const; + void setCurrentSpeed(int speed); + + enum Movement currentDirection() const; + void setCurrentDirection(Movement direction); + + void updateBoatMovement(); + + int type() const override; + +signals: + void boatDestroyed(); + void boatExecutionFinished(); + +private: + int speed; + int bombsAlreadyLaunched; + Movement direction; + QVariantAnimation *movementAnimation; + QAbstractAnimation *destroyAnimation; + QStateMachine *machine; +}; + +#endif // BOAT_H diff --git a/examples/widgets/animation/sub-attaq/boat_p.h b/examples/widgets/animation/sub-attaq/boat_p.h new file mode 100644 index 0000000..bb1a783 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/boat_p.h @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef BOAT_P_H +#define BOAT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +//Own +#include "bomb.h" +#include "graphicsscene.h" + +// Qt +#include <QGraphicsRotation> +#include <QKeyEventTransition> +#include <QState> + +static const int MAX_BOMB = 5; + + +//These transtion test if we have to stop the boat (i.e current speed is 1) +class KeyStopTransition : public QKeyEventTransition +{ +public: + KeyStopTransition(Boat *b, QEvent::Type t, int k) + : QKeyEventTransition(b, t, k), boat(b) + { + } +protected: + bool eventTest(QEvent *event) override + { + if (!QKeyEventTransition::eventTest(event)) + return false; + return (boat->currentSpeed() == 1); + } +private: + Boat *boat; +}; + +//These transtion test if we have to move the boat (i.e current speed was 0 or another value) + class KeyMoveTransition : public QKeyEventTransition +{ +public: + KeyMoveTransition(Boat *b, QEvent::Type t, int k) + : QKeyEventTransition(b, t, k), boat(b), key(k) + { + } +protected: + bool eventTest(QEvent *event) override + { + if (!QKeyEventTransition::eventTest(event)) + return false; + return (boat->currentSpeed() >= 0); + } + void onTransition(QEvent *) override + { + //We decrease the speed if needed + if (key == Qt::Key_Left && boat->currentDirection() == Boat::Right) + boat->setCurrentSpeed(boat->currentSpeed() - 1); + else if (key == Qt::Key_Right && boat->currentDirection() == Boat::Left) + boat->setCurrentSpeed(boat->currentSpeed() - 1); + else if (boat->currentSpeed() < 3) + boat->setCurrentSpeed(boat->currentSpeed() + 1); + boat->updateBoatMovement(); + } +private: + Boat *boat; + int key; +}; + +//This transition trigger the bombs launch + class KeyLaunchTransition : public QKeyEventTransition +{ +public: + KeyLaunchTransition(Boat *boat, QEvent::Type type, int key) + : QKeyEventTransition(boat, type, key), boat(boat) + { + } +protected: + bool eventTest(QEvent *event) override + { + if (!QKeyEventTransition::eventTest(event)) + return false; + //We have enough bomb? + return (boat->bombsLaunched() < MAX_BOMB); + } +private: + Boat *boat; +}; + +//This state is describing when the boat is moving right +class MoveStateRight : public QState +{ +public: + explicit MoveStateRight(Boat *boat, QState *parent = nullptr) + : QState(parent), boat(boat) + { + } +protected: + void onEntry(QEvent *) override + { + boat->setCurrentDirection(Boat::Right); + boat->updateBoatMovement(); + } +private: + Boat *boat; +}; + + //This state is describing when the boat is moving left +class MoveStateLeft : public QState +{ +public: + explicit MoveStateLeft(Boat *boat, QState *parent = nullptr) + : QState(parent), boat(boat) + { + } +protected: + void onEntry(QEvent *) override + { + boat->setCurrentDirection(Boat::Left); + boat->updateBoatMovement(); + } +private: + Boat *boat; +}; + +//This state is describing when the boat is in a stand by position +class StopState : public QState +{ +public: + explicit StopState(Boat *boat, QState *parent = nullptr) + : QState(parent), boat(boat) + { + } +protected: + void onEntry(QEvent *) override + { + boat->setCurrentSpeed(0); + boat->setCurrentDirection(Boat::None); + boat->updateBoatMovement(); + } +private: + Boat *boat; +}; + +//This state is describing the launch of the torpedo on the right +class LaunchStateRight : public QState +{ +public: + explicit LaunchStateRight(Boat *boat, QState *parent = nullptr) + : QState(parent), boat(boat) + { + } +protected: + void onEntry(QEvent *) override + { + Bomb *b = new Bomb; + b->setPos(boat->x()+boat->size().width(),boat->y()); + GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene()); + scene->addItem(b); + b->launch(Bomb::Right); + boat->setBombsLaunched(boat->bombsLaunched() + 1); + } +private: + Boat *boat; +}; + +//This state is describing the launch of the torpedo on the left +class LaunchStateLeft : public QState +{ +public: + explicit LaunchStateLeft(Boat *boat, QState *parent = nullptr) + : QState(parent), boat(boat) + { + } +protected: + void onEntry(QEvent *) override + { + Bomb *b = new Bomb; + b->setPos(boat->x() - b->size().width(), boat->y()); + GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene()); + scene->addItem(b); + b->launch(Bomb::Left); + boat->setBombsLaunched(boat->bombsLaunched() + 1); + } +private: + Boat *boat; +}; + +#endif // BOAT_P_H diff --git a/examples/widgets/animation/sub-attaq/bomb.cpp b/examples/widgets/animation/sub-attaq/bomb.cpp new file mode 100644 index 0000000..0b9c365 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/bomb.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "bomb.h" +#include "submarine.h" +#include "animationmanager.h" +#include "qanimationstate.h" + +//Qt +#include <QFinalState> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QStateMachine> + +Bomb::Bomb() : PixmapItem(QString("bomb"), GraphicsScene::Big) +{ + setZValue(2); +} + +void Bomb::launch(Bomb::Direction direction) +{ + QSequentialAnimationGroup *launchAnimation = new QSequentialAnimationGroup; + AnimationManager::self()->registerAnimation(launchAnimation); + qreal delta = direction == Right ? 20 : - 20; + QPropertyAnimation *anim = new QPropertyAnimation(this, "pos"); + anim->setEndValue(QPointF(x() + delta,y() - 20)); + anim->setDuration(150); + launchAnimation->addAnimation(anim); + anim = new QPropertyAnimation(this, "pos"); + anim->setEndValue(QPointF(x() + delta*2, y() )); + anim->setDuration(150); + launchAnimation->addAnimation(anim); + anim = new QPropertyAnimation(this, "pos"); + anim->setEndValue(QPointF(x() + delta*2,scene()->height())); + anim->setDuration(y()/2*60); + launchAnimation->addAnimation(anim); + connect(anim, &QVariantAnimation::valueChanged, this, &Bomb::onAnimationLaunchValueChanged); + connect(this, &Bomb::bombExploded, launchAnimation, &QAbstractAnimation::stop); + //We setup the state machine of the bomb + QStateMachine *machine = new QStateMachine(this); + + //This state is when the launch animation is playing + QAnimationState *launched = new QAnimationState(machine); + launched->setAnimation(launchAnimation); + + //End + QFinalState *finalState = new QFinalState(machine); + + machine->setInitialState(launched); + + //### Add a nice animation when the bomb is destroyed + launched->addTransition(this, &Bomb::bombExploded, finalState); + + //If the animation is finished, then we move to the final state + launched->addTransition(launched, &QAnimationState::animationFinished, finalState); + + //The machine has finished to be executed, then the boat is dead + connect(machine,&QState::finished, this, &Bomb::bombExecutionFinished); + + machine->start(); + +} + +void Bomb::onAnimationLaunchValueChanged(const QVariant &) +{ + const QList<QGraphicsItem *> colItems = + collidingItems(Qt::IntersectsItemBoundingRect); + for (QGraphicsItem *item : colItems) { + if (item->type() == SubMarine::Type) { + SubMarine *s = static_cast<SubMarine *>(item); + destroy(); + s->destroy(); + } + } +} + +void Bomb::destroy() +{ + emit bombExploded(); +} diff --git a/examples/widgets/animation/sub-attaq/bomb.h b/examples/widgets/animation/sub-attaq/bomb.h new file mode 100644 index 0000000..9ae54b4 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/bomb.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef BOMB_H +#define BOMB_H + +#include "pixmapitem.h" + +class Bomb : public PixmapItem +{ +Q_OBJECT +public: + enum Direction { + Left = 0, + Right + }; + Bomb(); + void launch(Direction direction); + void destroy(); + +signals: + void bombExploded(); + void bombExecutionFinished(); + +private slots: + void onAnimationLaunchValueChanged(const QVariant &); +}; + +#endif // BOMB_H diff --git a/examples/widgets/animation/sub-attaq/data.xml b/examples/widgets/animation/sub-attaq/data.xml new file mode 100644 index 0000000..0f30515 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/data.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<subattaq> + <submarines> + <submarine type="0" points="10" name="Q1" /> + <submarine type="1" points="20" name="Q2" /> + </submarines> + <levels> + <level id="0" name="Seaman recruit"> + <subinstance type="0" nb="1"/> + </level> + <level id="1" name="Seaman apprentice"> + <subinstance type="0" nb="2"/> + </level> + <level id="2" name="Seaman"> + <subinstance type="0" nb="4"/> + </level> + <level id="3" name="Petty Officer Third Class"> + <subinstance type="0" nb="6"/> + </level> + <level id="4" name="Petty Officer Second Class"> + <subinstance type="0" nb="6"/> + </level> + <level id="5" name="Petty Officer First Class"> + <subinstance type="0" nb="8"/> + </level> + <level id="6" name="Lieutenant"> + <subinstance type="0" nb="10"/> + </level> + <level id="7" name="Commander"> + <subinstance type="0" nb="15"/> + </level> + <level id="8" name="Captain"> + <subinstance type="0" nb="12"/> + </level> + <level id="9" name="Admiral"> + <subinstance type="0" nb="12"/> + </level> + </levels> +</subattaq> diff --git a/examples/widgets/animation/sub-attaq/graphicsscene.cpp b/examples/widgets/animation/sub-attaq/graphicsscene.cpp new file mode 100644 index 0000000..5248ed9 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/graphicsscene.cpp @@ -0,0 +1,301 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "graphicsscene.h" +#include "states.h" +#include "boat.h" +#include "submarine.h" +#include "torpedo.h" +#include "bomb.h" +#include "animationmanager.h" +#include "qanimationstate.h" +#include "progressitem.h" +#include "textinformationitem.h" + +//Qt +#include <QAction> +#include <QApplication> +#include <QFile> +#include <QFinalState> +#include <QParallelAnimationGroup> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QStateMachine> +#include <QXmlStreamReader> + +GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode, QObject *parent) + : QGraphicsScene(x, y, width, height, parent), mode(mode), boat(new Boat) +{ + PixmapItem *backgroundItem = new PixmapItem(QStringLiteral("background"), mode); + backgroundItem->setZValue(1); + backgroundItem->setPos(0,0); + addItem(backgroundItem); + + PixmapItem *surfaceItem = new PixmapItem(QStringLiteral("surface"), mode); + surfaceItem->setZValue(3); + surfaceItem->setPos(0, sealLevel() - surfaceItem->boundingRect().height() / 2); + addItem(surfaceItem); + + //The item that display score and level + progressItem = new ProgressItem(backgroundItem); + + textInformationItem = new TextInformationItem(backgroundItem); + textInformationItem->hide(); + //We create the boat + addItem(boat); + boat->setPos(this->width()/2, sealLevel() - boat->size().height()); + boat->hide(); + + //parse the xml that contain all data of the game + QXmlStreamReader reader; + QFile file(":data.xml"); + file.open(QIODevice::ReadOnly); + reader.setDevice(&file); + LevelDescription currentLevel; + while (!reader.atEnd()) { + reader.readNext(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == u"submarine") { + SubmarineDescription desc; + desc.name = reader.attributes().value("name").toString(); + desc.points = reader.attributes().value("points").toInt(); + desc.type = reader.attributes().value("type").toInt(); + submarinesData.append(desc); + } else if (reader.name() == u"level") { + currentLevel.id = reader.attributes().value("id").toInt(); + currentLevel.name = reader.attributes().value("name").toString(); + } else if (reader.name() == u"subinstance") { + currentLevel.submarines.append(qMakePair(reader.attributes().value("type").toInt(), + reader.attributes().value("nb").toInt())); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement) { + if (reader.name() == u"level") { + levelsData.insert(currentLevel.id, currentLevel); + currentLevel.submarines.clear(); + } + } + } +} + +qreal GraphicsScene::sealLevel() const +{ + return (mode == Big) ? 220 : 160; +} + +void GraphicsScene::setupScene(QAction *newAction, QAction *quitAction) +{ + static constexpr int nLetters = 10; + static constexpr struct { + char const *pix; + qreal initX, initY; + qreal destX, destY; + } logoData[nLetters] = { + {"s", -1000, -1000, 300, 150 }, + {"u", -800, -1000, 350, 150 }, + {"b", -600, -1000, 400, 120 }, + {"dash", -400, -1000, 460, 150 }, + {"a", 1000, 2000, 350, 250 }, + {"t", 800, 2000, 400, 250 }, + {"t2", 600, 2000, 430, 250 }, + {"a2", 400, 2000, 465, 250 }, + {"q", 200, 2000, 510, 250 }, + {"excl", 0, 2000, 570, 220 } }; + + QSequentialAnimationGroup *lettersGroupMoving = new QSequentialAnimationGroup(this); + QParallelAnimationGroup *lettersGroupFading = new QParallelAnimationGroup(this); + + for (int i = 0; i < nLetters; ++i) { + PixmapItem *logo = new PixmapItem(QLatin1String(":/logo-") + logoData[i].pix, this); + logo->setPos(logoData[i].initX, logoData[i].initY); + logo->setZValue(i + 3); + //creation of the animations for moving letters + QPropertyAnimation *moveAnim = new QPropertyAnimation(logo, "pos", lettersGroupMoving); + moveAnim->setEndValue(QPointF(logoData[i].destX, logoData[i].destY)); + moveAnim->setDuration(200); + moveAnim->setEasingCurve(QEasingCurve::OutElastic); + lettersGroupMoving->addPause(50); + //creation of the animations for fading out the letters + QPropertyAnimation *fadeAnim = new QPropertyAnimation(logo, "opacity", lettersGroupFading); + fadeAnim->setDuration(800); + fadeAnim->setEndValue(0); + fadeAnim->setEasingCurve(QEasingCurve::OutQuad); + } + + QStateMachine *machine = new QStateMachine(this); + + //This state is when the player is playing + PlayState *gameState = new PlayState(this, machine); + + //Final state + QFinalState *finalState = new QFinalState(machine); + + //Animation when the player enter in the game + QAnimationState *lettersMovingState = new QAnimationState(machine); + lettersMovingState->setAnimation(lettersGroupMoving); + + //Animation when the welcome screen disappear + QAnimationState *lettersFadingState = new QAnimationState(machine); + lettersFadingState->setAnimation(lettersGroupFading); + + //if new game then we fade out the welcome screen and start playing + lettersMovingState->addTransition(newAction, &QAction::triggered, lettersFadingState); + lettersFadingState->addTransition(lettersFadingState, &QAnimationState::animationFinished, gameState); + + //New Game is triggered then player start playing + gameState->addTransition(newAction, &QAction::triggered, gameState); + + //Wanna quit, then connect to CTRL+Q + gameState->addTransition(quitAction, &QAction::triggered, finalState); + lettersMovingState->addTransition(quitAction, &QAction::triggered, finalState); + + //Welcome screen is the initial state + machine->setInitialState(lettersMovingState); + + machine->start(); + + //We reach the final state, then we quit + connect(machine, &QStateMachine::finished, qApp, &QApplication::quit); +} + +void GraphicsScene::addItem(Bomb *bomb) +{ + bombs.insert(bomb); + connect(bomb, &Bomb::bombExecutionFinished, + this, &GraphicsScene::onBombExecutionFinished); + QGraphicsScene::addItem(bomb); +} + +void GraphicsScene::addItem(Torpedo *torpedo) +{ + torpedos.insert(torpedo); + connect(torpedo, &Torpedo::torpedoExecutionFinished, + this, &GraphicsScene::onTorpedoExecutionFinished); + QGraphicsScene::addItem(torpedo); +} + +void GraphicsScene::addItem(SubMarine *submarine) +{ + submarines.insert(submarine); + connect(submarine, &SubMarine::subMarineExecutionFinished, + this, &GraphicsScene::onSubMarineExecutionFinished); + QGraphicsScene::addItem(submarine); +} + +void GraphicsScene::addItem(QGraphicsItem *item) +{ + QGraphicsScene::addItem(item); +} + +void GraphicsScene::onBombExecutionFinished() +{ + Bomb *bomb = qobject_cast<Bomb *>(sender()); + if (!bomb) + return; + bombs.remove(bomb); + bomb->deleteLater(); + boat->setBombsLaunched(boat->bombsLaunched() - 1); +} + +void GraphicsScene::onTorpedoExecutionFinished() +{ + Torpedo *torpedo = qobject_cast<Torpedo *>(sender()); + if (!torpedo) + return; + torpedos.remove(torpedo); + torpedo->deleteLater(); +} + +void GraphicsScene::onSubMarineExecutionFinished() +{ + SubMarine *submarine = qobject_cast<SubMarine *>(sender()); + if (!submarine) + return; + submarines.remove(submarine); + if (submarines.count() == 0) + emit allSubMarineDestroyed(submarine->points()); + else + emit subMarineDestroyed(submarine->points()); + submarine->deleteLater(); +} + +void GraphicsScene::clearScene() +{ + for (SubMarine *sub : qAsConst(submarines)) { + // make sure to not go into onSubMarineExecutionFinished + sub->disconnect(this); + sub->destroy(); + sub->deleteLater(); + } + + for (Torpedo *torpedo : qAsConst(torpedos)) { + // make sure to not go into onTorpedoExecutionFinished + torpedo->disconnect(this); + torpedo->destroy(); + torpedo->deleteLater(); + } + + for (Bomb *bomb : qAsConst(bombs)) { + // make sure to not go into onBombExecutionFinished + bomb->disconnect(this); + bomb->destroy(); + bomb->deleteLater(); + } + + submarines.clear(); + bombs.clear(); + torpedos.clear(); + + AnimationManager::self()->unregisterAllAnimations(); + + boat->stop(); + boat->hide(); + boat->setEnabled(true); +} diff --git a/examples/widgets/animation/sub-attaq/graphicsscene.h b/examples/widgets/animation/sub-attaq/graphicsscene.h new file mode 100644 index 0000000..ce9ee11 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/graphicsscene.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef GRAPHICSSCENE_H +#define GRAPHICSSCENE_H + +//Qt +#include <QGraphicsScene> +#include <QSet> + + +class Boat; +class SubMarine; +class Torpedo; +class Bomb; +class PixmapItem; +class ProgressItem; +class TextInformationItem; +QT_BEGIN_NAMESPACE +class QAction; +QT_END_NAMESPACE + +class GraphicsScene : public QGraphicsScene +{ +Q_OBJECT +public: + enum Mode { + Big = 0, + Small + }; + + struct SubmarineDescription { + int type = 0; + int points = 0; + QString name; + }; + + struct LevelDescription { + int id = 0; + QString name; + QList<QPair<int, int>> submarines; + }; + + GraphicsScene(int x, int y, int width, int height, Mode mode, QObject *parent = nullptr); + qreal sealLevel() const; + void setupScene(QAction *newAction, QAction *quitAction); + void addItem(Bomb *bomb); + void addItem(Torpedo *torpedo); + void addItem(SubMarine *submarine); + void addItem(QGraphicsItem *item); + void clearScene(); + +signals: + void subMarineDestroyed(int); + void allSubMarineDestroyed(int); + +private slots: + void onBombExecutionFinished(); + void onTorpedoExecutionFinished(); + void onSubMarineExecutionFinished(); + +private: + Mode mode; + ProgressItem *progressItem; + TextInformationItem *textInformationItem; + Boat *boat; + QSet<SubMarine *> submarines; + QSet<Bomb *> bombs; + QSet<Torpedo *> torpedos; + QList<SubmarineDescription> submarinesData; + QHash<int, LevelDescription> levelsData; + + friend class PauseState; + friend class PlayState; + friend class LevelState; + friend class LostState; + friend class WinState; + friend class WinTransition; + friend class UpdateScoreTransition; +}; + +#endif // GRAPHICSSCENE_H + diff --git a/examples/widgets/animation/sub-attaq/main.cpp b/examples/widgets/animation/sub-attaq/main.cpp new file mode 100644 index 0000000..9b28d8c --- /dev/null +++ b/examples/widgets/animation/sub-attaq/main.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtWidgets> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(subattaq); + + MainWindow w; + w.show(); + + return app.exec(); +} diff --git a/examples/widgets/animation/sub-attaq/mainwindow.cpp b/examples/widgets/animation/sub-attaq/mainwindow.cpp new file mode 100644 index 0000000..0c152c9 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/mainwindow.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "mainwindow.h" +#include "graphicsscene.h" + +//Qt +#include <QGraphicsView> +#include <QApplication> +#include <QMenu> +#include <QMenuBar> +#include <QLayout> + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + QMenu *file = menuBar()->addMenu(tr("&File")); + + QAction *newAction = file->addAction(tr("New Game")); + newAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N)); + QAction *quitAction = file->addAction(tr("Quit")); + quitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); + + if (QApplication::arguments().contains("-fullscreen")) { + scene = new GraphicsScene(0, 0, 750, 400, GraphicsScene::Small, this); + setWindowState(Qt::WindowFullScreen); + } else { + scene = new GraphicsScene(0, 0, 880, 630, GraphicsScene::Big, this); + layout()->setSizeConstraint(QLayout::SetFixedSize); + } + + view = new QGraphicsView(scene, this); + view->setAlignment(Qt::AlignLeft | Qt::AlignTop); + scene->setupScene(newAction, quitAction); + setCentralWidget(view); +} diff --git a/examples/widgets/animation/sub-attaq/mainwindow.h b/examples/widgets/animation/sub-attaq/mainwindow.h new file mode 100644 index 0000000..660acfa --- /dev/null +++ b/examples/widgets/animation/sub-attaq/mainwindow.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +//Qt +#include <QMainWindow> +class GraphicsScene; +QT_BEGIN_NAMESPACE +class QGraphicsView; +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ +Q_OBJECT +public: + MainWindow(QWidget *parent = nullptr); + +private: + GraphicsScene *scene; + QGraphicsView *view; +}; + +#endif // MAINWINDOW_H diff --git a/examples/widgets/animation/sub-attaq/pics/big/background.png b/examples/widgets/animation/sub-attaq/pics/big/background.png Binary files differnew file mode 100644 index 0000000..9f58157 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/background.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/boat.png b/examples/widgets/animation/sub-attaq/pics/big/boat.png Binary files differnew file mode 100644 index 0000000..be82dff --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/boat.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/bomb.png b/examples/widgets/animation/sub-attaq/pics/big/bomb.png Binary files differnew file mode 100644 index 0000000..3af5f2f --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/bomb.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step1.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step1.png Binary files differnew file mode 100644 index 0000000..c9fd8b0 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step1.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step2.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step2.png Binary files differnew file mode 100644 index 0000000..7528f2d --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step2.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step3.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step3.png Binary files differnew file mode 100644 index 0000000..aae9c9c --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step3.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step4.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step4.png Binary files differnew file mode 100644 index 0000000..d697c1b --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/boat/step4.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step1.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step1.png Binary files differnew file mode 100644 index 0000000..88ca514 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step1.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step2.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step2.png Binary files differnew file mode 100644 index 0000000..524f589 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step2.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step3.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step3.png Binary files differnew file mode 100644 index 0000000..2cca1e8 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step3.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step4.png b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step4.png Binary files differnew file mode 100644 index 0000000..82100a8 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/explosion/submarine/step4.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/submarine.png b/examples/widgets/animation/sub-attaq/pics/big/submarine.png Binary files differnew file mode 100644 index 0000000..df435dc --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/submarine.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/surface.png b/examples/widgets/animation/sub-attaq/pics/big/surface.png Binary files differnew file mode 100644 index 0000000..4eba29e --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/surface.png diff --git a/examples/widgets/animation/sub-attaq/pics/big/torpedo.png b/examples/widgets/animation/sub-attaq/pics/big/torpedo.png Binary files differnew file mode 100644 index 0000000..f9c2687 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/big/torpedo.png diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/background-n810.svg b/examples/widgets/animation/sub-attaq/pics/scalable/background-n810.svg new file mode 100644 index 0000000..ece9f7a --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/background-n810.svg @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2588" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="background-n810.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata28"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="1141" + inkscape:window-width="1920" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="1.2399902" + inkscape:cx="375" + inkscape:cy="461.074" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:current-layer="layer1" /> + <defs + id="defs2590"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective30" /> + <linearGradient + id="linearGradient3746"> + <stop + id="stop3748" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3750" + style="stop-color:#0074b7;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + cx="82.966125" + cy="-178.42453" + r="526.79456" + fx="82.966125" + fy="-178.42453" + id="radialGradient3880" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4952094,0.2388475,-0.1040669,0.3734391,-208.61982,418.216)" /> + <linearGradient + id="linearGradient3624"> + <stop + id="stop3626" + style="stop-color:#3a8daf;stop-opacity:1" + offset="0" /> + <stop + id="stop3636" + style="stop-color:#252525;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="552.98486" + y1="390.56842" + x2="549.39465" + y2="702.3479" + id="linearGradient3630" + xlink:href="#linearGradient3624" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.3373776,0,0,1.186038,-986.88716,67.776416)" /> + <linearGradient + id="linearGradient3816"> + <stop + id="stop3818" + style="stop-color:#ad8b00;stop-opacity:1" + offset="0" /> + <stop + id="stop3820" + style="stop-color:#ad8b00;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="573" + y1="755.46222" + x2="573" + y2="700.13464" + id="linearGradient3826" + xlink:href="#linearGradient3816" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2561681,-151.5,-34.518664)" /> + <linearGradient + id="linearGradient5097"> + <stop + id="stop5099" + style="stop-color:#19a2db;stop-opacity:0" + offset="0" /> + <stop + id="stop5109" + style="stop-color:#1379a7;stop-opacity:0.49803922" + offset="0.30000001" /> + <stop + id="stop5101" + style="stop-color:#0e5173;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="590.84674" + y1="274.57559" + x2="590.84674" + y2="334.01376" + id="linearGradient5103" + xlink:href="#linearGradient5097" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-151.5,156.75229)" + spreadMethod="pad" /> + </defs> + <g + id="layer1"> + <rect + width="1053.5891" + height="206.64989" + x="-151.79456" + y="330.16019" + id="rect3638" + style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="1054.4708" + height="364.81519" + x="-152.23541" + y="533.48895" + id="rect3622" + style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -152.5,877.11847 C 120.5,865.81296 -202.86309,769.3663 109.5,871.29717 C 172.96247,892.00636 243.5,872.55334 297.5,871.29717 C 351.5,870.041 311.5,859.80335 358.5,876.13354 C 405.5,892.46372 553.5,861.09903 598.5,854.8182 C 643.5,848.53736 756.5,841.79698 795.5,853.10249 C 834.5,864.408 904.5,866.2725 904.5,866.2725 L 901.5,903.95754 L -154.5,902.70137 L -152.5,877.11847 z" + id="path3814" + style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 902.20121,894.16261 C 632.01828,889.43035 756.73005,860.2801 614.20403,894.1311 C 596.58819,898.315 408.23621,883.21212 400.43291,894.1311 C 376.86263,927.11261 75.265447,868.1243 34.250926,886.79082 C 31.281885,888.14209 12.514878,884.22134 -12.264082,889.72008 C -48.555335,897.77353 -64.717178,885.62471 -103.31472,890.35697 C -141.91229,895.08922 -145.87102,891.93439 -145.87102,891.93439 L -152.79879,903.10131 L 892.3044,902.5755 L 902.20121,894.16261 z" + id="path3828" + style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/background.svg b/examples/widgets/animation/sub-attaq/pics/scalable/background.svg new file mode 100644 index 0000000..0be2680 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/background.svg @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2588" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="background.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata28"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="1141" + inkscape:window-width="1920" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="0.93884027" + inkscape:cx="473.72605" + inkscape:cy="538.63678" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:current-layer="layer1" /> + <defs + id="defs2590"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective30" /> + <linearGradient + id="linearGradient3746"> + <stop + id="stop3748" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3750" + style="stop-color:#0074b7;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + cx="82.966125" + cy="-178.42453" + r="526.79456" + fx="82.966125" + fy="-178.42453" + id="radialGradient3880" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-208.61982,282.52272)" /> + <linearGradient + id="linearGradient3624"> + <stop + id="stop3626" + style="stop-color:#3a8daf;stop-opacity:1" + offset="0" /> + <stop + id="stop3636" + style="stop-color:#252525;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="552.98486" + y1="390.56842" + x2="549.39465" + y2="702.3479" + id="linearGradient3630" + xlink:href="#linearGradient3624" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.3373776,0,0,1.5004634,-986.88716,-154.07447)" /> + <linearGradient + id="linearGradient3816"> + <stop + id="stop3818" + style="stop-color:#ad8b00;stop-opacity:1" + offset="0" /> + <stop + id="stop3820" + style="stop-color:#ad8b00;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="573" + y1="755.46222" + x2="573" + y2="700.13464" + id="linearGradient3826" + xlink:href="#linearGradient3816" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.6033628,-151.5,-294.0167)" /> + <linearGradient + id="linearGradient5097"> + <stop + id="stop5099" + style="stop-color:#19a2db;stop-opacity:0" + offset="0" /> + <stop + id="stop5109" + style="stop-color:#1379a7;stop-opacity:0.49803922" + offset="0.30000001" /> + <stop + id="stop5101" + style="stop-color:#0e5173;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="590.84674" + y1="274.57559" + x2="590.84674" + y2="334.01376" + id="linearGradient5103" + xlink:href="#linearGradient5097" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-151.5,156.75229)" + spreadMethod="pad" /> + </defs> + <g + id="layer1"> + <rect + width="1053.5891" + height="291.32797" + x="-151.79456" + y="158.38464" + id="rect3638" + style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="1054.4708" + height="461.52972" + x="-152.23541" + y="435.10107" + id="rect3622" + style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -152.5,869.5896 C 120.5,855.15934 -202.86309,732.0556 109.5,862.15934 C 172.96247,888.59238 243.5,863.7627 297.5,862.15934 C 351.5,860.55598 311.5,847.48872 358.5,868.33244 C 405.5,889.17615 553.5,849.14252 598.5,841.12571 C 643.5,833.1089 756.5,824.50553 795.5,838.9358 C 834.5,853.36606 904.5,855.74589 904.5,855.74589 L 901.5,903.84677 L -154.5,902.24341 L -152.5,869.5896 z" + id="path3814" + style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 902.20121,891.3446 C 632.01828,885.30439 756.73005,848.09724 614.20403,891.30439 C 596.58819,896.64468 408.23621,877.36748 400.43291,891.30439 C 376.86263,933.40172 75.265447,858.10952 34.250926,881.93531 C 31.281885,883.66006 12.514878,878.65564 -12.264082,885.67419 C -48.555335,895.95355 -64.717178,880.4469 -103.31472,886.48711 C -141.91229,892.52732 -145.87102,888.50052 -145.87102,888.50052 L -152.79879,902.75389 L 892.3044,902.08275 L 902.20121,891.3446 z" + id="path3828" + style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/boat.svg b/examples/widgets/animation/sub-attaq/pics/scalable/boat.svg new file mode 100644 index 0000000..5298821 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/boat.svg @@ -0,0 +1,279 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2584"> + <defs + id="defs2666"> + <linearGradient + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + id="linearGradient3387" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-110.6791,190.19124)" /> + <linearGradient + id="linearGradient3167"> + <stop + id="stop3169" + style="stop-color:#464646;stop-opacity:1" + offset="0" /> + <stop + id="stop3345" + style="stop-color:#848788;stop-opacity:1" + offset="0.44021741" /> + <stop + id="stop3347" + style="stop-color:#9ca0a2;stop-opacity:1" + offset="0.56799388" /> + <stop + id="stop3171" + style="stop-color:#b5babd;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="474.23065" + y1="229.92336" + x2="474.1944" + y2="218.27365" + id="linearGradient3416" + xlink:href="#linearGradient3167" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-125.98032,185.95625)" /> + <linearGradient + id="linearGradient3692"> + <stop + id="stop3694" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3696" + style="stop-color:#b6b6b6;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="573.5" + y1="244.2056" + x2="578.25" + y2="216.9556" + id="linearGradient3972" + xlink:href="#linearGradient3692" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-126.5541,188.56624)" /> + <linearGradient + id="linearGradient3438"> + <stop + id="stop3440" + style="stop-color:#939393;stop-opacity:1" + offset="0" /> + <stop + id="stop3444" + style="stop-color:#d6d6d6;stop-opacity:1" + offset="0.12354442" /> + <stop + id="stop3446" + style="stop-color:#dadada;stop-opacity:1" + offset="0.74055624" /> + <stop + id="stop3442" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="660.29303" + y1="256.53284" + x2="444.79303" + y2="255.62085" + id="linearGradient3948" + xlink:href="#linearGradient3438" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-126.5541,185.56624)" /> + <linearGradient + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + id="linearGradient3990" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-132.8041,190.19124)" /> + <linearGradient + id="linearGradient3746"> + <stop + id="stop3748" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3750" + style="stop-color:#0074b7;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + id="linearGradient3994" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-88.054101,190.19124)" /> + <linearGradient + id="linearGradient3428"> + <stop + id="stop3430" + style="stop-color:#464646;stop-opacity:1" + offset="0" /> + <stop + id="stop3432" + style="stop-color:#848788;stop-opacity:1" + offset="0.18306103" /> + <stop + id="stop3434" + style="stop-color:#9ca0a2;stop-opacity:1" + offset="0.66368055" /> + <stop + id="stop3436" + style="stop-color:#b5babd;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="592.92798" + y1="199.43727" + x2="557.05743" + y2="196.5448" + id="linearGradient3426" + xlink:href="#linearGradient3428" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-102.5217,149.09845)" /> + </defs> + <g + id="layer1"> + <g + id="boat"> + <path + d="M 296.669,434.15623 C 376.12538,436.50959 448.282,436.46711 542.42304,434.15623 C 542.42304,434.15623 544.22253,425.03531 542.42304,422.57953 C 432.90655,403.86953 296.669,418.12547 296.669,422.57953 L 296.669,434.15623 z" + id="path3469" + style="fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3.4975698;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" /> + <rect + width="3.4280596" + height="29.611124" + x="647.59613" + y="173.91156" + transform="matrix(0.9327494,0.3605254,-0.3633626,0.9316478,0,0)" + id="rect3408" + style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="48.499989" + height="8.5" + x="318.48221" + y="405.82172" + transform="matrix(0.9999952,3.0887777e-3,-3.0887777e-3,0.9999952,0,0)" + id="rect3376" + style="opacity:1;fill:url(#linearGradient3416);fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 382.4459,430.66072 C 382.4459,430.66072 420.85999,388.74829 397.4459,385.66072 L 488.4459,397.66072 L 488.4459,432.66072 L 382.4459,430.66072 z" + id="path3952" + style="fill:url(#linearGradient3972);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 301.4459,429.66072 C 301.4459,429.66072 330.46329,468.66072 343.4459,468.66072 C 355.42851,471.91072 507.57644,473.70653 525.4459,465.91072 C 534.58031,461.59104 537.90602,455.58662 539.4459,429.66072 C 473.70193,439.43306 371.2651,439.78219 301.4459,429.66072 z" + id="path3938" + style="fill:url(#linearGradient3948);fill-opacity:1;fill-rule:evenodd;stroke:#545454;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 339.44863,416.12222 L 357.69854,416.17859 L 368.1622,427.96097 L 339.41234,427.87217 L 339.44863,416.12222 z" + id="rect3378" + style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" /> + <rect + width="13.5" + height="17" + x="411.19589" + y="404.28574" + id="rect3974" + style="opacity:1;fill:url(#linearGradient3990);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="13.5" + height="17" + x="455.94589" + y="404.28574" + id="rect3992" + style="opacity:1;fill:url(#linearGradient3994);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 295.6959,421.91072 C 360.77923,430.41072 446.61257,432.91072 541.9459,421.91072 C 541.9459,421.91072 543.74902,428.6076 541.9459,430.41072 C 432.20839,444.14823 295.6959,433.68104 295.6959,430.41072 L 295.6959,421.91072 z" + id="rect2558" + style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" /> + <rect + width="94.427879" + height="7.236649" + x="437.10614" + y="342.2645" + transform="matrix(0.9947793,0.1020501,-0.1079723,0.9941539,0,0)" + id="rect2569" + style="opacity:1;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.0365274;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="13.5" + height="17" + x="433.32089" + y="404.28574" + id="rect3385" + style="opacity:1;fill:url(#linearGradient3387);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 402.86916,380.21847 L 489.80407,388.85485 L 491.52271,394.54919 L 397.58781,384.91281 L 402.86916,380.21847 z" + id="rect3466" + style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.03650045;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" /> + <rect + width="34.5" + height="14.5" + x="456.4783" + y="336.94293" + transform="matrix(0.997157,7.5351915e-2,-7.5351915e-2,0.997157,0,0)" + id="rect3418" + style="opacity:1;fill:url(#linearGradient3426);fill-opacity:1;fill-rule:nonzero;stroke:#494949;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + transform="matrix(0.9246214,0.3808874,-0.3808874,0.9246214,-13.252851,-40.129692)" + id="flag"> + <rect + width="19.75" + height="27.75" + x="193.34448" + y="-709" + transform="matrix(0,1,-1,0,0,0)" + id="rect3389" + style="opacity:1;fill:#b20000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="27.25" + height="5.75" + x="681.5" + y="200.59448" + id="rect3393" + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="5.75" + height="19.5" + x="691.25" + y="193.59448" + id="rect3395" + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="27.75" + height="2.5" + x="681.5" + y="202.34448" + id="rect3397" + style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + width="3" + height="19.25" + x="692.5" + y="193.59448" + id="rect3399" + style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/bomb.svg b/examples/widgets/animation/sub-attaq/pics/scalable/bomb.svg new file mode 100644 index 0000000..294771a --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/bomb.svg @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg3121"> + <defs + id="defs3123"> + <radialGradient + cx="-135.625" + cy="148.71948" + r="7.625" + fx="-135.625" + fy="148.71948" + id="radialGradient3439" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="-132.85063" + y1="173.6969" + x2="-145.3662" + y2="177.59828" + id="linearGradient3418" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.2134297,-0.5943658,0.6658882,-0.2391126,-274.53441,123.00067)" /> + <linearGradient + x1="-141.85466" + y1="181.49153" + x2="-144.95044" + y2="175.90179" + id="linearGradient3414" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2134297,-0.5943658,-0.6658882,-0.2391126,-15.893355,122.67824)" /> + <linearGradient + x1="-149.5" + y1="177.59448" + x2="-145.7928" + y2="180.05936" + id="linearGradient3410" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.6315243,0,0,0.7075182,-227.03781,54.321514)" /> + <linearGradient + x1="-140.46242" + y1="177.40488" + x2="-147.04802" + y2="172.66473" + id="linearGradient3406" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.6315243,0,0,-0.7075182,-226.40365,274.91611)" /> + <linearGradient + x1="-147.2406" + y1="180.95567" + x2="-140.01878" + y2="175.57777" + id="linearGradient3402" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.6315243,0,0,-0.7075182,-64.045217,275.07466)" /> + <linearGradient + x1="-146.98956" + y1="174.00922" + x2="-142.60332" + y2="179.38712" + id="linearGradient3398" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.6315243,0,0,0.7075182,-62.683611,54.187362)" /> + <linearGradient + id="linearGradient3366"> + <stop + id="stop3368" + style="stop-color:#bcbcbc;stop-opacity:1" + offset="0" /> + <stop + id="stop3370" + style="stop-color:#191b1c;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + cx="-208.95004" + cy="173.10576" + r="31.667252" + fx="-208.95004" + fy="173.10576" + id="radialGradient3364" + xlink:href="#linearGradient3366" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + id="layer1"> + <g + transform="translate(419.4996,488.13454)" + id="mine"> + <path + d="M -167.5843,186.54079 A 31.466251,31.466251 0 1 1 -230.5168,186.54079 A 31.466251,31.466251 0 1 1 -167.5843,186.54079 z" + transform="matrix(0.6341613,0,0,0.6341613,-18.521242,45.718192)" + id="path2586" + style="opacity:1;fill:url(#radialGradient3364);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -155.20193,175.4167 C -157.60085,176.6451 -156.78074,184.26068 -156.78074,184.26068 C -156.78074,184.26068 -148.33787,181.58301 -148.57092,178.60053 C -148.74283,176.40051 -153.23774,174.41092 -155.20193,175.4167 z" + id="path3382" + style="fill:url(#linearGradient3398);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -156.56354,153.84532 C -158.96246,152.61693 -158.14235,145.00135 -158.14235,145.00135 C -158.14235,145.00135 -149.69948,147.67902 -149.93253,150.66149 C -150.10444,152.86151 -154.59935,154.85111 -156.56354,153.84532 z" + id="path3400" + style="fill:url(#linearGradient3402);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -133.88532,153.68678 C -131.48641,152.45838 -132.30652,144.8428 -132.30652,144.8428 C -132.30652,144.8428 -140.74938,147.52047 -140.51633,150.50295 C -140.34442,152.70297 -135.84951,154.69256 -133.88532,153.68678 z" + id="path3404" + style="fill:url(#linearGradient3406);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -134.51948,175.55085 C -132.12057,176.77925 -132.94068,184.39483 -132.94068,184.39483 C -132.94068,184.39483 -141.38355,181.71716 -141.15049,178.73469 C -140.97858,176.53467 -136.48367,174.54507 -134.51948,175.55085 z" + id="path3408" + style="fill:url(#linearGradient3410);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -161.25709,168.78221 C -163.22395,170.62484 -170.11427,165.85236 -170.11427,165.85236 C -170.11427,165.85236 -164.7408,160.23808 -162.01257,161.46538 C -160.00011,162.37068 -159.64667,167.27352 -161.25709,168.78221 z" + id="path3412" + style="fill:url(#linearGradient3414);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -129.17068,169.10464 C -127.20382,170.94727 -120.3135,166.17478 -120.3135,166.17478 C -120.3135,166.17478 -125.68697,160.5605 -128.41519,161.7878 C -130.42766,162.69311 -130.7811,167.59595 -129.17068,169.10464 z" + id="path3416" + style="fill:url(#linearGradient3418);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M -126,151.21948 A 6.625,6.625 0 1 1 -139.25,151.21948 A 6.625,6.625 0 1 1 -126,151.21948 z" + transform="matrix(0.6341613,0,0,0.6341613,-61.039517,68.324922)" + id="path3426" + style="opacity:1;fill:url(#radialGradient3439);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/sand.svg b/examples/widgets/animation/sub-attaq/pics/scalable/sand.svg new file mode 100644 index 0000000..8af11b7 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/sand.svg @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2596"> + <defs + id="defs2598"> + <linearGradient + id="linearGradient3708"> + <stop + id="stop3710" + style="stop-color:#202020;stop-opacity:1" + offset="0" /> + <stop + id="stop3712" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="518.26996" + y1="497.31476" + x2="533.02924" + y2="497.31476" + id="linearGradient3794" + xlink:href="#linearGradient3708" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3718"> + <stop + id="stop3720" + style="stop-color:#bcbcbc;stop-opacity:0.28169015" + offset="0" /> + <stop + id="stop3722" + style="stop-color:#bcbcbc;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="516.89508" + y1="503.50137" + x2="516.89508" + y2="543.80646" + id="linearGradient3792" + xlink:href="#linearGradient3718" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" /> + <linearGradient + id="linearGradient3692"> + <stop + id="stop3694" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3696" + style="stop-color:#b6b6b6;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="506.95975" + y1="469.73706" + x2="525.41608" + y2="469.73706" + id="linearGradient3790" + xlink:href="#linearGradient3692" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3816"> + <stop + id="stop3818" + style="stop-color:#ad8b00;stop-opacity:1" + offset="0" /> + <stop + id="stop3820" + style="stop-color:#ad8b00;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="573" + y1="755.46222" + x2="573" + y2="700.13464" + id="linearGradient3826" + xlink:href="#linearGradient3816" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.6033628,-150.63569,-350.3846)" /> + </defs> + <g + id="layer1"> + <path + d="M -151.63569,813.2217 C 121.3643,798.79144 -201.99878,675.6877 110.3643,805.79144 C 173.82677,832.22448 244.3643,807.3948 298.3643,805.79144 C 352.3643,804.18808 312.3643,791.12082 359.3643,811.96454 C 406.3643,832.80825 554.3643,792.77462 599.3643,784.75781 C 644.3643,776.741 757.36426,768.13763 796.36426,782.5679 C 835.36426,796.99816 905.36426,799.37799 905.36426,799.37799 L 902.36426,847.47887 L -153.63569,845.87551 L -151.63569,813.2217 z" + id="path3814" + style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 908.86426,836.95812 C 635.8643,830.91791 761.87636,793.71076 617.8643,836.91791 C 600.0648,842.2582 409.74894,822.981 401.8643,836.91791 C 378.04825,879.01524 73.306465,803.72304 31.864305,827.54883 C 28.864305,829.27358 9.9016246,824.26916 -15.135695,831.28771 C -51.805335,841.56707 -68.135695,826.06042 -107.1357,832.10063 C -146.1357,838.14084 -150.13569,834.11404 -150.13569,834.11404 L -157.13569,848.36741 L 898.86426,847.69627 L 908.86426,836.95812 z" + id="path3828" + style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/see.svg b/examples/widgets/animation/sub-attaq/pics/scalable/see.svg new file mode 100644 index 0000000..0666691 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/see.svg @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2650"> + <defs + id="defs2652"> + <linearGradient + id="linearGradient3624"> + <stop + id="stop3626" + style="stop-color:#3a8daf;stop-opacity:1" + offset="0" /> + <stop + id="stop3636" + style="stop-color:#252525;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="552.98486" + y1="390.56842" + x2="549.39465" + y2="702.3479" + id="linearGradient3630" + xlink:href="#linearGradient3624" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.3373776,0,0,1.5004634,-996.17287,-279.00679)" /> + </defs> + <g + id="layer1"> + <rect + width="1054.4708" + height="461.52972" + x="-161.52115" + y="310.16876" + id="rect3622" + style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/sky.svg b/examples/widgets/animation/sub-attaq/pics/scalable/sky.svg new file mode 100644 index 0000000..1546c08 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/sky.svg @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2721"> + <defs + id="defs2723"> + <linearGradient + id="linearGradient3746"> + <stop + id="stop3748" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3750" + style="stop-color:#0074b7;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + cx="82.966125" + cy="-178.42453" + r="526.79456" + fx="82.966125" + fy="-178.42453" + id="radialGradient3880" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-235.04839,425.12197)" /> + </defs> + <g + id="layer1"> + <rect + width="1053.5891" + height="291.32797" + x="-178.22313" + y="300.98392" + id="rect3638" + style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/sub-attaq.svg b/examples/widgets/animation/sub-attaq/pics/scalable/sub-attaq.svg new file mode 100644 index 0000000..b075179 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/sub-attaq.svg @@ -0,0 +1,1473 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1052.3622" + height="744.09448" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + version="1.0" + sodipodi:docname="sub-attaq.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="radialGradient3439" + cx="-135.625" + cy="148.71948" + fx="-135.625" + fy="148.71948" + r="7.625" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3418" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.2134297,-0.5943658,0.6658882,-0.2391126,-274.53441,123.00067)" + x1="-132.85063" + y1="173.6969" + x2="-145.3662" + y2="177.59828" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3414" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2134297,-0.5943658,-0.6658882,-0.2391126,-15.893355,122.67824)" + x1="-141.85466" + y1="181.49153" + x2="-144.95044" + y2="175.90179" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3410" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.6315243,0,0,0.7075182,-227.03781,54.321514)" + x1="-149.5" + y1="177.59448" + x2="-145.7928" + y2="180.05936" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3406" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.6315243,0,0,-0.7075182,-226.40365,274.91611)" + x1="-140.46242" + y1="177.40488" + x2="-147.04802" + y2="172.66473" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3402" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.6315243,0,0,-0.7075182,-64.045217,275.07466)" + x1="-147.2406" + y1="180.95567" + x2="-140.01878" + y2="175.57777" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="linearGradient3398" + x1="-146.98956" + y1="174.00922" + x2="-142.60332" + y2="179.38712" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.6315243,0,0,0.7075182,-62.683611,54.187362)" /> + <linearGradient + id="linearGradient3366"> + <stop + id="stop3368" + offset="0" + style="stop-color:#bcbcbc;stop-opacity:1;" /> + <stop + id="stop3370" + offset="1" + style="stop-color:#191b1c;stop-opacity:1;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3366" + id="radialGradient3364" + cx="-208.95004" + cy="173.10576" + fx="-208.95004" + fy="173.10576" + r="31.667252" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient5097"> + <stop + style="stop-color:#19a2db;stop-opacity:0;" + offset="0" + id="stop5099" /> + <stop + id="stop5109" + offset="0.30000001" + style="stop-color:#1379a7;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#0e5173;stop-opacity:1;" + offset="1" + id="stop5101" /> + </linearGradient> + <linearGradient + id="linearGradient3523" + inkscape:collect="always"> + <stop + id="stop3525" + offset="0" + style="stop-color:#b9b9b9;stop-opacity:1" /> + <stop + id="stop3527" + offset="1" + style="stop-color:#444444;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient3438"> + <stop + style="stop-color:#939393;stop-opacity:1;" + offset="0" + id="stop3440" /> + <stop + id="stop3444" + offset="0.12354442" + style="stop-color:#d6d6d6;stop-opacity:1;" /> + <stop + style="stop-color:#dadada;stop-opacity:1;" + offset="0.74055624" + id="stop3446" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop3442" /> + </linearGradient> + <linearGradient + id="linearGradient3428"> + <stop + id="stop3430" + offset="0" + style="stop-color:#464646;stop-opacity:1;" /> + <stop + style="stop-color:#848788;stop-opacity:1;" + offset="0.18306103" + id="stop3432" /> + <stop + id="stop3434" + offset="0.66368055" + style="stop-color:#9ca0a2;stop-opacity:1;" /> + <stop + id="stop3436" + offset="1" + style="stop-color:#b5babd;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient4034"> + <stop + id="stop4036" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.49803922;" + offset="0.5" + id="stop4038" /> + <stop + id="stop4040" + offset="0.63705367" + style="stop-color:#ffffff;stop-opacity:0.24705882;" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.12156863;" + offset="0.79425853" + id="stop4042" /> + <stop + id="stop4044" + offset="1" + style="stop-color:#a0a0a0;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4016"> + <stop + style="stop-color:#283e6a;stop-opacity:1;" + offset="0" + id="stop4018" /> + <stop + style="stop-color:#283e6a;stop-opacity:0;" + offset="1" + id="stop4020" /> + </linearGradient> + <linearGradient + id="linearGradient4004"> + <stop + style="stop-color:#dbdbdb;stop-opacity:1;" + offset="0" + id="stop4010" /> + <stop + style="stop-color:#c4c9cb;stop-opacity:1;" + offset="1" + id="stop4012" /> + </linearGradient> + <linearGradient + id="linearGradient3998"> + <stop + id="stop4000" + offset="0" + style="stop-color:#adadad;stop-opacity:1;" /> + <stop + id="stop4002" + offset="1" + style="stop-color:#ffffff;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3864"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3866" /> + <stop + id="stop4028" + offset="0.5" + style="stop-color:#ffffff;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.24705882;" + offset="0.75" + id="stop4030" /> + <stop + id="stop4032" + offset="0.875" + style="stop-color:#ffffff;stop-opacity:0.12156863;" /> + <stop + style="stop-color:#a0a0a0;stop-opacity:1;" + offset="1" + id="stop3868" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3816"> + <stop + style="stop-color:#ad8b00;stop-opacity:1;" + offset="0" + id="stop3818" /> + <stop + style="stop-color:#ad8b00;stop-opacity:0;" + offset="1" + id="stop3820" /> + </linearGradient> + <linearGradient + id="linearGradient3746"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3748" /> + <stop + style="stop-color:#0074b7;stop-opacity:1;" + offset="1" + id="stop3750" /> + </linearGradient> + <linearGradient + id="linearGradient3718"> + <stop + style="stop-color:#bcbcbc;stop-opacity:0.28169015;" + offset="0" + id="stop3720" /> + <stop + style="stop-color:#bcbcbc;stop-opacity:0;" + offset="1" + id="stop3722" /> + </linearGradient> + <linearGradient + id="linearGradient3708"> + <stop + style="stop-color:#202020;stop-opacity:1;" + offset="0" + id="stop3710" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop3712" /> + </linearGradient> + <linearGradient + id="linearGradient3692"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3694" /> + <stop + style="stop-color:#b6b6b6;stop-opacity:1;" + offset="1" + id="stop3696" /> + </linearGradient> + <linearGradient + id="linearGradient3656"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3658" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3660" /> + </linearGradient> + <linearGradient + id="linearGradient3624"> + <stop + style="stop-color:#3a8daf;stop-opacity:1;" + offset="0" + id="stop3626" /> + <stop + id="stop3636" + offset="1" + style="stop-color:#252525;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3532"> + <stop + id="stop3534" + offset="0" + style="stop-color:#545454;stop-opacity:1;" /> + <stop + style="stop-color:#848788;stop-opacity:1;" + offset="0.44021741" + id="stop3536" /> + <stop + id="stop3538" + offset="0.56799388" + style="stop-color:#9ca0a2;stop-opacity:1;" /> + <stop + id="stop3540" + offset="1" + style="stop-color:#565d60;stop-opacity:1" /> + </linearGradient> + <linearGradient + id="linearGradient3345"> + <stop + id="stop3348" + offset="0" + style="stop-color:#898989;stop-opacity:1;" /> + <stop + style="stop-color:#9ea1a2;stop-opacity:1;" + offset="0.44021741" + id="stop3350" /> + <stop + id="stop3352" + offset="0.56799388" + style="stop-color:#bbbdbf;stop-opacity:1;" /> + <stop + id="stop3354" + offset="1" + style="stop-color:#f0f1f2;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3227"> + <stop + style="stop-color:#444444;stop-opacity:1;" + offset="0" + id="stop3229" /> + <stop + style="stop-color:#b0b0b0;stop-opacity:1;" + offset="1" + id="stop3232" /> + </linearGradient> + <linearGradient + id="linearGradient3435"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3437" /> + <stop + style="stop-color:#c0c0c0;stop-opacity:0;" + offset="1" + id="stop3439" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3421"> + <stop + style="stop-color:#444444;stop-opacity:1;" + offset="0" + id="stop3423" /> + <stop + style="stop-color:#444444;stop-opacity:0;" + offset="1" + id="stop3425" /> + </linearGradient> + <linearGradient + id="linearGradient3293"> + <stop + style="stop-color:#c4b434;stop-opacity:1;" + offset="0" + id="stop3295" /> + <stop + style="stop-color:#9b5500;stop-opacity:1;" + offset="1" + id="stop3297" /> + </linearGradient> + <linearGradient + id="linearGradient3229"> + <stop + style="stop-color:#125a7a;stop-opacity:1;" + offset="0" + id="stop3231" /> + <stop + style="stop-color:#308fc0;stop-opacity:1;" + offset="1" + id="stop3233" /> + </linearGradient> + <linearGradient + id="linearGradient3219"> + <stop + id="stop3221" + offset="0" + style="stop-color:#a55b00;stop-opacity:1;" /> + <stop + id="stop3223" + offset="1" + style="stop-color:#f4e45e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3189"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3191" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3193" /> + </linearGradient> + <linearGradient + id="linearGradient3167"> + <stop + style="stop-color:#464646;stop-opacity:1;" + offset="0" + id="stop3169" /> + <stop + id="stop3345" + offset="0.44021741" + style="stop-color:#848788;stop-opacity:1;" /> + <stop + style="stop-color:#9ca0a2;stop-opacity:1;" + offset="0.56799388" + id="stop3347" /> + <stop + style="stop-color:#b5babd;stop-opacity:1;" + offset="1" + id="stop3171" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3167" + id="linearGradient3175" + x1="443.95602" + y1="315.31854" + x2="443.95602" + y2="247.85609" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.4908502,0,0,0.4579593,350.98557,542.12189)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3253" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3255" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3321" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3323" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3331" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3333" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3293" + id="linearGradient3343" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.3292883,0,0,1.10796,1.5038593,-24.232315)" + x1="359.5589" + y1="258.84247" + x2="370.88239" + y2="258.84247" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3365" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3367" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3369" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3371" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3379" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3381" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3293" + id="linearGradient3385" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.3267302,0,0,1.1332782,-1.5786343,-29.194748)" + x1="371.79858" + y1="258.84247" + x2="364.49646" + y2="258.84247" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3293" + id="linearGradient3401" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.9807835,0,0,1.1280701,-361.45126,-28.553769)" + x1="371.79858" + y1="258.84247" + x2="364.49646" + y2="258.84247" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3421" + id="radialGradient3431" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1862613,0,0,0.3638703,-186.86143,179.02055)" + cx="432.3343" + cy="233.80295" + fx="432.3343" + fy="233.80295" + r="59.056834" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3435" + id="radialGradient3441" + cx="290.5" + cy="244.34448" + fx="290.5" + fy="244.34448" + r="37.5" + gradientTransform="matrix(0.8202102,0.8202102,-0.7960458,0.7960458,246.73838,-189.686)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3345" + id="linearGradient3311" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.466978,0,0,0.4500435,352.00841,540.25044)" + x1="510.99884" + y1="161.99408" + x2="396.48914" + y2="161.99408" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3421" + id="radialGradient3339" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.4181493,0,0,0.1282619,386.09461,620.15777)" + cx="432.3343" + cy="233.80295" + fx="432.3343" + fy="233.80295" + r="59.056834" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3219" + id="linearGradient3434" + gradientUnits="userSpaceOnUse" + x1="325.57214" + y1="280.13632" + x2="312.84424" + y2="257.60013" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3229" + id="linearGradient3436" + gradientUnits="userSpaceOnUse" + x1="310.01578" + y1="255.47881" + x2="325.92572" + y2="280.13632" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3532" + id="linearGradient3520" + x1="525" + y1="371.09448" + x2="525" + y2="395.09448" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.5865192,0,0,0.2518015,339.73218,572.99479)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3624" + id="linearGradient3630" + x1="552.98486" + y1="390.56842" + x2="549.39465" + y2="702.3479" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.3373776,0,0,1.5004634,-835.38716,-310.82676)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3662" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3668" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3672" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3676" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3692" + id="linearGradient3772" + gradientUnits="userSpaceOnUse" + x1="506.95975" + y1="469.73706" + x2="525.41608" + y2="469.73706" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3718" + id="linearGradient3774" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" + x1="516.89508" + y1="503.50137" + x2="516.89508" + y2="543.80646" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3708" + id="linearGradient3776" + gradientUnits="userSpaceOnUse" + x1="518.26993" + y1="497.31477" + x2="533.02923" + y2="497.31477" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3692" + id="linearGradient3790" + gradientUnits="userSpaceOnUse" + x1="506.95975" + y1="469.73706" + x2="525.41608" + y2="469.73706" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3718" + id="linearGradient3792" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" + x1="516.89508" + y1="503.50137" + x2="516.89508" + y2="543.80646" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3708" + id="linearGradient3794" + gradientUnits="userSpaceOnUse" + x1="518.26993" + y1="497.31477" + x2="533.02923" + y2="497.31477" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3804" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3656" + id="radialGradient3808" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)" + cx="656.19507" + cy="534.45917" + fx="656.19507" + fy="534.45917" + r="13.227922" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3227" + id="linearGradient3812" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1223608,0,0,0.3849769,-17.516054,565.40983)" + x1="543.5" + y1="205.19257" + x2="587.52001" + y2="205.19257" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="linearGradient3826" + x1="573" + y1="755.46222" + x2="573" + y2="700.13464" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.6033628,0,-450.76899)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3864" + id="radialGradient3874" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.9674693,0.8647541,-0.8726553,1.0212484,-15.308759,-74.232772)" + cx="94.273849" + cy="89.893486" + fx="94.273849" + fy="89.893486" + r="74.397521" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3746" + id="radialGradient3880" + cx="82.966125" + cy="-178.42453" + fx="82.966125" + fy="-178.42453" + r="526.79456" + gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-57.119818,125.77043)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3438" + id="linearGradient3948" + x1="660.29303" + y1="256.53284" + x2="444.79303" + y2="255.62085" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,32.526912)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3692" + id="linearGradient3972" + x1="573.5" + y1="244.2056" + x2="578.25" + y2="216.9556" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,35.526912)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3746" + id="linearGradient3990" + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-6.25,37.151912)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3746" + id="linearGradient3994" + gradientUnits="userSpaceOnUse" + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + gradientTransform="translate(38.5,37.151912)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4016" + id="linearGradient4022" + x1="639" + y1="262.09448" + x2="667" + y2="262.09448" + gradientUnits="userSpaceOnUse" /> + <inkscape:perspective + id="perspective2578" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 526.18109 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3746" + id="linearGradient3387" + gradientUnits="userSpaceOnUse" + x1="542.5" + y1="222.59448" + x2="559" + y2="222.59448" + gradientTransform="translate(15.875,37.151912)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3167" + id="linearGradient3416" + x1="474.23065" + y1="229.92336" + x2="474.1944" + y2="218.27365" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.1004684,32.526757)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3428" + id="linearGradient3426" + x1="592.92798" + y1="199.43727" + x2="557.05743" + y2="196.5448" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(12.140805,-13.041887)" /> + <filter + inkscape:collect="always" + id="filter3507"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="3.0523171" + id="feGaussianBlur3509" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3523" + id="linearGradient3521" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,-0.7291751,0,521.83983)" + x1="562.55634" + y1="285.89896" + x2="562.55634" + y2="244.09448" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5097" + id="linearGradient5103" + x1="590.84674" + y1="274.57559" + x2="590.84674" + y2="334.01376" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3864" + id="radialGradient5107" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.9674693,0.8647541,-0.8726553,1.0212484,-15.308759,-74.232772)" + cx="94.273849" + cy="89.893486" + fx="94.273849" + fy="89.893486" + r="74.397521" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.70710678" + inkscape:cx="532.91407" + inkscape:cy="457.84365" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1674" + inkscape:window-height="1000" + inkscape:window-x="2" + inkscape:window-y="14" + showguides="false" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3638" + width="1053.5891" + height="291.32797" + x="-0.29455566" + y="1.6323624" /> + <path + style="fill:url(#radialGradient3874);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3507)" + d="M 158.37853,75.817898 C 130.95894,49.483192 82.14552,74.615971 85.85382,95.15981 C 49.691853,94.8009 50.214842,139.36083 83.29101,132.16343 C 144.66465,163.16454 159.26268,129.80212 164.6863,136.51386 C 225.60448,157.97672 246.34362,130.65438 265.24417,127.0714 C 294.43981,137.91859 337.16986,121.78798 297.03636,102.77604 C 331.73096,64.597047 277.96882,60.229366 253.07028,70.400868 C 191.09597,33.610112 168.89234,63.292037 158.37853,75.817898 z" + id="path3872" + sodipodi:nodetypes="cccccccc" + transform="matrix(1.5062893,0,0,1.1720951,618.04001,132.36768)" /> + <rect + style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3622" + width="1054.4708" + height="461.52972" + x="-0.7354126" + y="278.34879" /> + <path + style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M -0.99999999,712.83731 C 272,698.40705 -51.363087,575.30331 261,705.40705 C 324.46247,731.84009 395,707.01041 449,705.40705 C 503,703.80369 463,690.73643 510,711.58015 C 557,732.42386 705,692.39023 750,684.37342 C 795,676.35661 908,667.75324 947,682.18351 C 986,696.61377 1056,698.9936 1056,698.9936 L 1053,747.09448 L -3,745.49112 L -0.99999999,712.83731 z" + id="path3814" + sodipodi:nodetypes="cssssscccc" /> + <rect + style="opacity:1;fill:url(#linearGradient3520);fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:0.56879884;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3512" + width="10.557344" + height="6.0432386" + x="642.3761" + y="666.43695" /> + <use + x="0" + y="0" + xlink:href="#path2455" + id="use3258" + transform="matrix(0.869168,0,0,-0.869168,81.98751,1246.5374)" + width="1052.3622" + height="744.09448" /> + <path + style="fill:url(#linearGradient3812);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77744257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 593.04822,651.68104 C 593.04822,651.68104 653.65569,615.49321 639.065,637.05192 C 624.47431,658.61061 624.47431,658.61061 624.47431,658.61061 L 593.04822,651.68104 z" + id="path2455" /> + <path + style="fill:url(#linearGradient3175);fill-opacity:1;fill-rule:evenodd;stroke:#393939;stroke-width:1.90693891;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 485.26939,643.71814 C 443.15507,651.66437 458.5319,680.53556 502.21486,686.27814 C 551.68229,692.78115 568.45042,691.0115 605.34827,686.27814 C 657.60843,679.57406 657.68143,651.78445 605.34827,643.25553 C 553.98131,634.88408 516.10913,637.89923 485.26939,643.71814 z" + id="path2385" + sodipodi:nodetypes="cssss" /> + <path + style="fill:url(#radialGradient3339);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 542.18031,648.1112 C 548.56327,665.42741 608.42397,656.72745 586.93551,642.57104 C 586.93551,642.57104 543.33293,648.61096 542.18031,648.1112 z" + id="path3403" + sodipodi:nodetypes="ccc" /> + <path + style="fill:url(#linearGradient3311);fill-opacity:1;fill-rule:evenodd;stroke:#2d2d2d;stroke-width:2.07042313;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 537.39402,641.90906 C 537.39402,656.7605 583.62247,656.30589 583.62247,641.45445 L 583.62247,636.06071 C 583.62247,621.21003 537.39402,613.87461 537.39402,628.72529 L 537.39402,641.90906 z" + id="path3291" + sodipodi:nodetypes="cssss" /> + <g + id="g3235" + transform="matrix(1.4016868,0,0,1.1319742,112.22001,-99.678822)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#radialGradient3441);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3433" + sodipodi:cx="303.5" + sodipodi:cy="263.09448" + sodipodi:rx="37.5" + sodipodi:ry="40" + d="M 341,263.09448 A 37.5,40 0 1 1 266,263.09448 A 37.5,40 0 1 1 341,263.09448 z" + transform="matrix(0.692163,0,1.4106583e-2,0.289185,275.31394,582.37251)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.06500006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3458" + sodipodi:cx="369.5" + sodipodi:cy="316.09448" + sodipodi:rx="27.5" + sodipodi:ry="7" + d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z" + transform="matrix(0.5642633,0,0,0.5642633,348.03095,450.47113)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:4.23126984;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3510" + sodipodi:cx="369.5" + sodipodi:cy="316.09448" + sodipodi:rx="27.5" + sodipodi:ry="7" + d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z" + transform="matrix(0,0.30778,-0.5642633,0,828.66499,563.5944)" /> + <use + x="0" + y="0" + xlink:href="#path3510" + id="use3544" + transform="translate(0.5000005,-17.23511)" + width="1052.3622" + height="744.09448" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:2.38492584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3584" + sodipodi:cx="237.5" + sodipodi:cy="366.09448" + sodipodi:rx="8.5" + sodipodi:ry="8" + d="M 246,366.09448 A 8.5,8 0 1 1 229,366.09448 A 8.5,8 0 1 1 246,366.09448 z" + transform="matrix(1.7798114,-4.2997512e-2,1.3318941e-2,0.5513151,196.65666,476.1443)" /> + <path + style="fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3.49756980000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" + d="M 423.2231,281.1169 C 502.67948,283.47026 574.8361,283.42778 668.97714,281.1169 C 668.97714,281.1169 670.77663,271.99598 668.97714,269.5402 C 559.46065,250.8302 423.2231,265.08614 423.2231,269.5402 L 423.2231,281.1169 z" + id="path3469" + sodipodi:nodetypes="cccsc" /> + <rect + style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3408" + width="3.4280596" + height="29.611124" + x="709.89148" + y="-14.462622" + transform="matrix(0.9327494,0.3605254,-0.3633626,0.9316478,0,0)" /> + <rect + style="opacity:1;fill:url(#linearGradient3416);fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3376" + width="48.499989" + height="8.5" + x="444.56302" + y="252.39224" + transform="matrix(0.9999952,3.0887776e-3,-3.0887776e-3,0.9999952,0,0)" /> + <path + style="fill:url(#linearGradient3972);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 509,277.62139 C 509,277.62139 547.41409,235.70896 524,232.62139 L 615,244.62139 L 615,279.62139 L 509,277.62139 z" + id="path3952" + sodipodi:nodetypes="csccc" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#radialGradient3662);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3654" + sodipodi:cx="656.19507" + sodipodi:cy="541.15485" + sodipodi:rx="12.727922" + sodipodi:ry="16.263456" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + transform="matrix(0.5187874,0,0,0.3968421,374.8524,387.30025)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#radialGradient3668);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3666" + sodipodi:cx="656.19507" + sodipodi:cy="541.15485" + sodipodi:rx="12.727922" + sodipodi:ry="16.263456" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + transform="matrix(0.5734968,0,0,0.4386917,316.52295,315.62837)" /> + <path + transform="matrix(0.8598866,0,0,0.5637407,192.52282,220.77351)" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + sodipodi:ry="16.263456" + sodipodi:rx="12.727922" + sodipodi:cy="541.15485" + sodipodi:cx="656.19507" + id="path3670" + style="opacity:1;fill:url(#radialGradient3672);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.90000010000000020;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#radialGradient3676);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.90000010000000020;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3674" + sodipodi:cx="656.19507" + sodipodi:cy="541.15485" + sodipodi:rx="12.727922" + sodipodi:ry="16.263456" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + transform="matrix(0.7435991,0,0,0.6264519,225.8301,127.83701)" /> + <g + id="g3759" + transform="matrix(0.8830571,0,0,0.8830571,104.83144,103.2985)"> + <path + d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z" + sodipodi:ry="34.648232" + sodipodi:rx="7.7781744" + sodipodi:cy="469.73706" + sodipodi:cx="516.18793" + id="path3682" + style="opacity:1;fill:url(#linearGradient3772);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <g + id="g3754"> + <rect + style="opacity:1;fill:url(#linearGradient3774);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3716" + width="33.58757" + height="59.927299" + x="498.86386" + y="497.84454" /> + <path + style="fill:url(#linearGradient3776);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z" + id="path3704" + sodipodi:nodetypes="cscsc" /> + <path + sodipodi:nodetypes="cscsc" + id="path3706" + d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z" + style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + <g + transform="matrix(0.8830571,0,0,0.8830571,192.45885,-66.370546)" + id="g3778"> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#linearGradient3790);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3780" + sodipodi:cx="516.18793" + sodipodi:cy="469.73706" + sodipodi:rx="7.7781744" + sodipodi:ry="34.648232" + d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z" /> + <g + id="g3782"> + <rect + y="497.84454" + x="498.86386" + height="59.927299" + width="33.58757" + id="rect3784" + style="opacity:1;fill:url(#linearGradient3792);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cscsc" + id="path3786" + d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z" + style="fill:url(#linearGradient3794);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z" + id="path3788" + sodipodi:nodetypes="cscsc" /> + </g> + </g> + <path + transform="matrix(0.4292897,0,0,0.3283816,384.32775,481.20689)" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + sodipodi:ry="16.263456" + sodipodi:rx="12.727922" + sodipodi:cy="541.15485" + sodipodi:cx="656.19507" + id="path3802" + style="opacity:1;fill:url(#radialGradient3804);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:url(#radialGradient3808);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3806" + sodipodi:cx="656.19507" + sodipodi:cy="541.15485" + sodipodi:rx="12.727922" + sodipodi:ry="16.263456" + d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z" + transform="matrix(0.5842998,0,0,0.4469553,299.7804,369.91514)" /> + <path + style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 1059.5,736.57373 C 786.5,730.53352 912.51207,693.32637 768.5,736.53352 C 750.7005,741.87381 560.38464,722.59661 552.5,736.53352 C 528.68395,778.63085 223.94216,703.33865 182.5,727.16444 C 179.5,728.88919 160.53732,723.88477 135.5,730.90332 C 98.830356,741.18268 82.5,725.67603 43.5,731.71624 C 4.5,737.75645 0.5,733.72965 0.5,733.72965 L -6.5,747.98302 L 1049.5,747.31188 L 1059.5,736.57373 z" + id="path3828" + sodipodi:nodetypes="cssssscccc" /> + <rect + style="opacity:1;fill:url(#linearGradient5103);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3448" + width="1053.5891" + height="67.882248" + x="-0.29455566" + y="274.57559" /> + <path + sodipodi:nodetypes="ccccc" + id="path3519" + d="M 428,343.85222 C 428,343.85222 457.01739,315.41439 470,315.41439 C 481.98261,313.04457 634.13054,311.73511 652,317.41962 C 661.13441,320.56943 664.46012,324.9477 666,343.85222 C 600.25603,336.72647 497.8192,336.4719 428,343.85222 z" + style="opacity:0.43933058;fill:url(#linearGradient3521);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:url(#linearGradient3948);fill-opacity:1;fill-rule:evenodd;stroke:#545454;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 428,276.62139 C 428,276.62139 457.01739,315.62139 470,315.62139 C 481.98261,318.87139 634.13054,320.6672 652,312.87139 C 661.13441,308.55171 664.46012,302.54729 666,276.62139 C 600.25603,286.39373 497.8192,286.74286 428,276.62139 z" + id="path3938" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" + d="M 466.00273,263.08289 L 484.25264,263.13926 L 494.7163,274.92164 L 465.96644,274.83284 L 466.00273,263.08289 z" + id="rect3378" + sodipodi:nodetypes="ccccc" /> + <rect + style="opacity:1;fill:url(#linearGradient3990);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3974" + width="13.5" + height="17" + x="537.75" + y="251.2464" + inkscape:transform-center-x="30" /> + <rect + inkscape:transform-center-x="30" + y="251.2464" + x="582.5" + height="17" + width="13.5" + id="rect3992" + style="opacity:1;fill:url(#linearGradient3994);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" + d="M 422.25,268.87139 C 487.33333,277.37139 573.16667,279.87139 668.5,268.87139 C 668.5,268.87139 670.30312,275.56827 668.5,277.37139 C 558.76249,291.1089 422.25,280.64171 422.25,277.37139 L 422.25,268.87139 z" + id="rect2558" + sodipodi:nodetypes="cccsc" /> + <rect + style="opacity:1;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.0365274;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2569" + width="94.427879" + height="7.236649" + x="546.39832" + y="177.10637" + transform="matrix(0.9947793,0.1020501,-0.1079723,0.9941539,0,0)" /> + <rect + inkscape:transform-center-x="30" + y="251.2464" + x="559.875" + height="17" + width="13.5" + id="rect3385" + style="opacity:1;fill:url(#linearGradient3387);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + id="g3401" + transform="matrix(0.9246214,0.3808874,-0.3808874,0.9246214,113.30125,-193.16902)" + inkscape:transform-center-x="17.590385" + inkscape:transform-center-y="-15.415449"> + <rect + inkscape:transform-center-y="-43.888889" + transform="matrix(0,1,-1,0,0,0)" + style="opacity:1;fill:#b20000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3389" + width="19.75" + height="27.75" + x="193.34448" + y="-709" /> + <rect + y="200.59448" + x="681.5" + height="5.75" + width="27.25" + id="rect3393" + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + y="193.59448" + x="691.25" + height="19.5" + width="5.75" + id="rect3395" + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + y="202.34448" + x="681.5" + height="2.5" + width="27.75" + id="rect3397" + style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + y="193.59448" + x="692.5" + height="19.25" + width="3" + id="rect3399" + style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <path + style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.03650045;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" + d="M 529.42326,227.17914 L 616.35817,235.81552 L 618.07681,241.50986 L 524.14191,231.87348 L 529.42326,227.17914 z" + id="rect3466" + sodipodi:nodetypes="ccccc" /> + <rect + style="opacity:1;fill:url(#linearGradient3426);fill-opacity:1;fill-rule:nonzero;stroke:#494949;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3418" + width="34.5" + height="14.5" + x="571.14081" + y="174.8026" + transform="matrix(0.997157,7.5351915e-2,-7.5351915e-2,0.997157,0,0)" + inkscape:transform-center-x="-8" + inkscape:transform-center-y="2" /> + <g + id="mine" + transform="translate(971.11461,237.62715)" + inkscape:label="#g3441"> + <path + transform="matrix(0.6341613,0,0,0.6341613,-18.521242,45.718192)" + d="M -167.5843,186.54079 A 31.466251,31.466251 0 1 1 -230.5168,186.54079 A 31.466251,31.466251 0 1 1 -167.5843,186.54079 z" + sodipodi:ry="31.466251" + sodipodi:rx="31.466251" + sodipodi:cy="186.54079" + sodipodi:cx="-199.05055" + id="path2586" + style="opacity:1;fill:url(#radialGradient3364);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:nodetypes="ccss" + id="path3382" + d="M -155.20193,175.4167 C -157.60085,176.6451 -156.78074,184.26068 -156.78074,184.26068 C -156.78074,184.26068 -148.33787,181.58301 -148.57092,178.60053 C -148.74283,176.40051 -153.23774,174.41092 -155.20193,175.4167 z" + style="fill:url(#linearGradient3398);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccss" + id="path3400" + d="M -156.56354,153.84532 C -158.96246,152.61693 -158.14235,145.00135 -158.14235,145.00135 C -158.14235,145.00135 -149.69948,147.67902 -149.93253,150.66149 C -150.10444,152.86151 -154.59935,154.85111 -156.56354,153.84532 z" + style="fill:url(#linearGradient3402);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccss" + id="path3404" + d="M -133.88532,153.68678 C -131.48641,152.45838 -132.30652,144.8428 -132.30652,144.8428 C -132.30652,144.8428 -140.74938,147.52047 -140.51633,150.50295 C -140.34442,152.70297 -135.84951,154.69256 -133.88532,153.68678 z" + style="fill:url(#linearGradient3406);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccss" + id="path3408" + d="M -134.51948,175.55085 C -132.12057,176.77925 -132.94068,184.39483 -132.94068,184.39483 C -132.94068,184.39483 -141.38355,181.71716 -141.15049,178.73469 C -140.97858,176.53467 -136.48367,174.54507 -134.51948,175.55085 z" + style="fill:url(#linearGradient3410);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccss" + id="path3412" + d="M -161.25709,168.78221 C -163.22395,170.62484 -170.11427,165.85236 -170.11427,165.85236 C -170.11427,165.85236 -164.7408,160.23808 -162.01257,161.46538 C -160.00011,162.37068 -159.64667,167.27352 -161.25709,168.78221 z" + style="fill:url(#linearGradient3414);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccss" + id="path3416" + d="M -129.17068,169.10464 C -127.20382,170.94727 -120.3135,166.17478 -120.3135,166.17478 C -120.3135,166.17478 -125.68697,160.5605 -128.41519,161.7878 C -130.42766,162.69311 -130.7811,167.59595 -129.17068,169.10464 z" + style="fill:url(#linearGradient3418);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + transform="matrix(0.6341613,0,0,0.6341613,-61.039517,68.324922)" + d="M -126,151.21948 A 6.625,6.625 0 1 1 -139.25,151.21948 A 6.625,6.625 0 1 1 -126,151.21948 z" + sodipodi:ry="6.625" + sodipodi:rx="6.625" + sodipodi:cy="151.21948" + sodipodi:cx="-132.625" + id="path3426" + style="opacity:1;fill:url(#radialGradient3439);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + </g> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/submarine.svg b/examples/widgets/animation/sub-attaq/pics/scalable/submarine.svg new file mode 100644 index 0000000..8a0ffdd --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/submarine.svg @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2594"> + <defs + id="defs2596"> + <linearGradient + id="linearGradient3345"> + <stop + id="stop3348" + style="stop-color:#898989;stop-opacity:1" + offset="0" /> + <stop + id="stop3350" + style="stop-color:#9ea1a2;stop-opacity:1" + offset="0.44021741" /> + <stop + id="stop3352" + style="stop-color:#bbbdbf;stop-opacity:1" + offset="0.56799388" /> + <stop + id="stop3354" + style="stop-color:#f0f1f2;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="510.99884" + y1="161.99408" + x2="396.48914" + y2="161.99408" + id="linearGradient3311" + xlink:href="#linearGradient3345" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.466978,0,0,0.4500435,231.58508,159.95135)" /> + <linearGradient + id="linearGradient3532"> + <stop + id="stop3534" + style="stop-color:#545454;stop-opacity:1" + offset="0" /> + <stop + id="stop3536" + style="stop-color:#848788;stop-opacity:1" + offset="0.44021741" /> + <stop + id="stop3538" + style="stop-color:#9ca0a2;stop-opacity:1" + offset="0.56799388" /> + <stop + id="stop3540" + style="stop-color:#565d60;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="525" + y1="371.09448" + x2="525" + y2="395.09448" + id="linearGradient3520" + xlink:href="#linearGradient3532" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.5865192,0,0,0.2518015,219.30885,192.6957)" /> + <linearGradient + id="linearGradient3227"> + <stop + id="stop3229" + style="stop-color:#444444;stop-opacity:1" + offset="0" /> + <stop + id="stop3232" + style="stop-color:#b0b0b0;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="543.5" + y1="205.19257" + x2="587.52002" + y2="205.19257" + id="linearGradient3812" + xlink:href="#linearGradient3227" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1223608,0,0,0.3849769,-137.93938,185.11074)" /> + <linearGradient + id="linearGradient3167"> + <stop + id="stop3169" + style="stop-color:#464646;stop-opacity:1" + offset="0" /> + <stop + id="stop3345" + style="stop-color:#848788;stop-opacity:1" + offset="0.44021741" /> + <stop + id="stop3347" + style="stop-color:#9ca0a2;stop-opacity:1" + offset="0.56799388" /> + <stop + id="stop3171" + style="stop-color:#b5babd;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="443.95602" + y1="315.31854" + x2="443.95602" + y2="247.85609" + id="linearGradient3175" + xlink:href="#linearGradient3167" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.4908502,0,0,0.4579593,230.56224,161.8228)" /> + <linearGradient + id="linearGradient3421"> + <stop + id="stop3423" + style="stop-color:#444444;stop-opacity:1" + offset="0" /> + <stop + id="stop3425" + style="stop-color:#444444;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + cx="432.33429" + cy="233.80295" + r="59.056835" + fx="432.33429" + fy="233.80295" + id="radialGradient3339" + xlink:href="#linearGradient3421" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.4181493,0,0,0.1282619,265.67128,239.85868)" /> + <linearGradient + id="linearGradient3435"> + <stop + id="stop3437" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3439" + style="stop-color:#c0c0c0;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + cx="290.5" + cy="244.34448" + r="37.5" + fx="290.5" + fy="244.34448" + id="radialGradient3441" + xlink:href="#linearGradient3435" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.8202102,0.8202102,-0.7960458,0.7960458,246.73838,-189.686)" /> + </defs> + <g + id="submarine"> + <rect + width="10.557344" + height="6.0432386" + x="521.95276" + y="286.13785" + id="rect3512" + style="opacity:1;fill:url(#linearGradient3520);fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:0.56879884;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 472.62489,271.38195 C 472.62489,271.38195 533.23236,235.19412 518.64167,256.75283 C 504.05098,278.31152 504.05098,278.31152 504.05098,278.31152 L 472.62489,271.38195 z" + id="path2455" + style="fill:url(#linearGradient3812);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77744257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 364.84606,263.41905 C 322.73174,271.36528 338.10857,300.23647 381.79153,305.97905 C 431.25896,312.48206 448.02709,310.71241 484.92494,305.97905 C 537.1851,299.27497 537.2581,271.48536 484.92494,262.95644 C 433.55798,254.58499 395.6858,257.60014 364.84606,263.41905 z" + id="path2385" + style="fill:url(#linearGradient3175);fill-opacity:1;fill-rule:evenodd;stroke:#393939;stroke-width:1.90693891;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 421.75698,267.81211 C 428.13994,285.12832 488.00064,276.42836 466.51218,262.27195 C 466.51218,262.27195 422.9096,268.31187 421.75698,267.81211 z" + id="path3403" + style="fill:url(#radialGradient3339);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 416.97069,261.60997 C 416.97069,276.46141 463.19914,276.0068 463.19914,261.15536 L 463.19914,255.76162 C 463.19914,240.91094 416.97069,233.57552 416.97069,248.4262 L 416.97069,261.60997 z" + id="path3291" + style="fill:url(#linearGradient3311);fill-opacity:1;fill-rule:evenodd;stroke:#2d2d2d;stroke-width:2.07042313;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 341,263.09448 A 37.5,40 0 1 1 266,263.09448 A 37.5,40 0 1 1 341,263.09448 z" + transform="matrix(0.692163,0,1.4106583e-2,0.289185,154.89061,202.07342)" + id="path3433" + style="opacity:1;fill:url(#radialGradient3441);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z" + transform="matrix(0.5642633,0,0,0.5642633,227.60762,70.172035)" + id="path3458" + style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.06500006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z" + transform="matrix(0,0.30778,-0.5642633,0,708.24166,183.29531)" + id="path3510" + style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:4.23126984;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <use + transform="translate(0.5000044,-17.235115)" + id="use3544" + x="0" + y="0" + width="1052.3622" + height="744.09448" + xlink:href="#path3510" /> + <path + d="M 246,366.09448 A 8.5,8 0 1 1 229,366.09448 A 8.5,8 0 1 1 246,366.09448 z" + transform="matrix(1.7798114,-4.2997512e-2,1.3318941e-2,0.5513151,76.233334,95.845205)" + id="path3584" + style="opacity:1;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:2.38492584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/surface.svg b/examples/widgets/animation/sub-attaq/pics/scalable/surface.svg new file mode 100644 index 0000000..40ed239 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/surface.svg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2685"> + <defs + id="defs2687"> + <linearGradient + id="linearGradient5097"> + <stop + id="stop5099" + style="stop-color:#19a2db;stop-opacity:0" + offset="0" /> + <stop + id="stop5109" + style="stop-color:#1379a7;stop-opacity:0.49803922" + offset="0.30000001" /> + <stop + id="stop5101" + style="stop-color:#0e5173;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="590.84674" + y1="274.57559" + x2="590.84674" + y2="334.01376" + id="linearGradient5103" + xlink:href="#linearGradient5097" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-172.21428,209.55976)" + spreadMethod="pad" /> + </defs> + <g + id="layer1"> + <rect + width="1053.5891" + height="67.882248" + x="-172.50883" + y="484.13535" + id="rect3448" + style="opacity:1;fill:url(#linearGradient5103);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/scalable/torpedo.svg b/examples/widgets/animation/sub-attaq/pics/scalable/torpedo.svg new file mode 100644 index 0000000..48e429d --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/scalable/torpedo.svg @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2584"> + <defs + id="defs2586"> + <linearGradient + id="linearGradient3708"> + <stop + id="stop3710" + style="stop-color:#202020;stop-opacity:1" + offset="0" /> + <stop + id="stop3712" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="518.26996" + y1="497.31476" + x2="533.02924" + y2="497.31476" + id="linearGradient3776" + xlink:href="#linearGradient3708" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3718"> + <stop + id="stop3720" + style="stop-color:#bcbcbc;stop-opacity:0.28169015" + offset="0" /> + <stop + id="stop3722" + style="stop-color:#bcbcbc;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="516.89508" + y1="503.50137" + x2="516.89508" + y2="543.80646" + id="linearGradient3774" + xlink:href="#linearGradient3718" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" /> + <linearGradient + id="linearGradient3692"> + <stop + id="stop3694" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3696" + style="stop-color:#b6b6b6;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="506.95975" + y1="469.73706" + x2="525.41608" + y2="469.73706" + id="linearGradient3772" + xlink:href="#linearGradient3692" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="506.95975" + y1="469.73706" + x2="525.41608" + y2="469.73706" + id="linearGradient2403" + xlink:href="#linearGradient3692" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="516.89508" + y1="503.50137" + x2="516.89508" + y2="543.80646" + id="linearGradient2405" + xlink:href="#linearGradient3718" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" /> + <linearGradient + x1="518.26996" + y1="497.31476" + x2="533.02924" + y2="497.31476" + id="linearGradient2407" + xlink:href="#linearGradient3708" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + transform="translate(-128.69958,6.6568748)" + id="torpedo"> + <g + transform="matrix(0.8830571,0,0,0.8830571,-119.78327,177.67947)" + id="g3525"> + <path + d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z" + id="path3682" + style="opacity:1;fill:url(#linearGradient2403);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + id="g3754"> + <rect + width="33.58757" + height="59.927299" + x="498.86386" + y="497.84454" + id="rect3716" + style="opacity:1;fill:url(#linearGradient2405);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z" + id="path3704" + style="fill:url(#linearGradient2407);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z" + id="path3706" + style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + </g> +</svg> diff --git a/examples/widgets/animation/sub-attaq/pics/small/background.png b/examples/widgets/animation/sub-attaq/pics/small/background.png Binary files differnew file mode 100644 index 0000000..5ad3db6 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/background.png diff --git a/examples/widgets/animation/sub-attaq/pics/small/boat.png b/examples/widgets/animation/sub-attaq/pics/small/boat.png Binary files differnew file mode 100644 index 0000000..114ccc3 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/boat.png diff --git a/examples/widgets/animation/sub-attaq/pics/small/bomb.png b/examples/widgets/animation/sub-attaq/pics/small/bomb.png Binary files differnew file mode 100644 index 0000000..3af5f2f --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/bomb.png diff --git a/examples/widgets/animation/sub-attaq/pics/small/submarine.png b/examples/widgets/animation/sub-attaq/pics/small/submarine.png Binary files differnew file mode 100644 index 0000000..0c0c350 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/submarine.png diff --git a/examples/widgets/animation/sub-attaq/pics/small/surface.png b/examples/widgets/animation/sub-attaq/pics/small/surface.png Binary files differnew file mode 100644 index 0000000..06d0e47 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/surface.png diff --git a/examples/widgets/animation/sub-attaq/pics/small/torpedo.png b/examples/widgets/animation/sub-attaq/pics/small/torpedo.png Binary files differnew file mode 100644 index 0000000..f9c2687 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/small/torpedo.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-a.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-a.png Binary files differnew file mode 100644 index 0000000..67dd76d --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-a.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-a2.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-a2.png Binary files differnew file mode 100644 index 0000000..17668b0 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-a2.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-b.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-b.png Binary files differnew file mode 100644 index 0000000..cf6c045 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-b.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-dash.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-dash.png Binary files differnew file mode 100644 index 0000000..219233c --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-dash.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-excl.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-excl.png Binary files differnew file mode 100644 index 0000000..8dd0a2e --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-excl.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-q.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-q.png Binary files differnew file mode 100644 index 0000000..86e588d --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-q.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-s.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-s.png Binary files differnew file mode 100644 index 0000000..7b6a36e --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-s.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-t.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-t.png Binary files differnew file mode 100644 index 0000000..b2e3526 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-t.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-t2.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-t2.png Binary files differnew file mode 100644 index 0000000..b11a778 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-t2.png diff --git a/examples/widgets/animation/sub-attaq/pics/welcome/logo-u.png b/examples/widgets/animation/sub-attaq/pics/welcome/logo-u.png Binary files differnew file mode 100644 index 0000000..24eede8 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pics/welcome/logo-u.png diff --git a/examples/widgets/animation/sub-attaq/pixmapitem.cpp b/examples/widgets/animation/sub-attaq/pixmapitem.cpp new file mode 100644 index 0000000..a8581d8 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pixmapitem.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "pixmapitem.h" + +//Qt +#include <QPainter> + +PixmapItem::PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem *parent) + : QGraphicsObject(parent) +{ + if (mode == GraphicsScene::Big) + pix = QPixmap(QStringLiteral(":/big/") + fileName); + else + pix = QPixmap(QStringLiteral(":/small/") + fileName); +} + +PixmapItem::PixmapItem(const QString &fileName, QGraphicsScene *scene) + : QGraphicsObject(), pix(fileName) +{ + scene->addItem(this); +} + +QSizeF PixmapItem::size() const +{ + return pix.size(); +} + +QRectF PixmapItem::boundingRect() const +{ + return QRectF(QPointF(0, 0), pix.size()); +} + +void PixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->drawPixmap(0, 0, pix); +} + + diff --git a/examples/widgets/animation/sub-attaq/pixmapitem.h b/examples/widgets/animation/sub-attaq/pixmapitem.h new file mode 100644 index 0000000..45e2ca8 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/pixmapitem.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef PIXMAPITEM_H +#define PIXMAPITEM_H + +//Own +#include "graphicsscene.h" + +//Qt +#include <QGraphicsObject> + +class PixmapItem : public QGraphicsObject +{ +public: + PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem *parent = nullptr); + PixmapItem(const QString &fileName, QGraphicsScene *scene); + QSizeF size() const; + QRectF boundingRect() const override; + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; +private: + QPixmap pix; +}; + +#endif // PIXMAPITEM_H diff --git a/examples/widgets/animation/sub-attaq/progressitem.cpp b/examples/widgets/animation/sub-attaq/progressitem.cpp new file mode 100644 index 0000000..350dbb7 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/progressitem.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "progressitem.h" + +#include <QFont> + +ProgressItem::ProgressItem(QGraphicsItem *parent) + : QGraphicsTextItem(parent) +{ + setFont(QFont("Comic Sans MS")); + setPos(parentItem()->boundingRect().topRight() - QPointF(180, -5)); +} + +void ProgressItem::setLevel(int level) +{ + currentLevel = level; + updateProgress(); +} + +void ProgressItem::setScore(int score) +{ + currentScore = score; + updateProgress(); +} + +void ProgressItem::updateProgress() +{ + setHtml(QString("Level : %1 Score : %2").arg(currentLevel).arg(currentScore)); +} diff --git a/examples/widgets/animation/sub-attaq/progressitem.h b/examples/widgets/animation/sub-attaq/progressitem.h new file mode 100644 index 0000000..f76b168 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/progressitem.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef PROGRESSITEM_H +#define PROGRESSITEM_H + +//Qt +#include <QGraphicsTextItem> + +class ProgressItem : public QGraphicsTextItem +{ +public: + ProgressItem(QGraphicsItem *parent = nullptr); + void setLevel(int level); + void setScore(int score); + +private: + void updateProgress(); + int currentLevel = 1; + int currentScore = 0; +}; + +#endif // PROGRESSITEM_H diff --git a/examples/widgets/animation/sub-attaq/qanimationstate.cpp b/examples/widgets/animation/sub-attaq/qanimationstate.cpp new file mode 100644 index 0000000..6da0855 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/qanimationstate.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 "qanimationstate.h" + +#include <QAbstractAnimation> + +QT_BEGIN_NAMESPACE + +/*! +\class QAnimationState + +\brief The QAnimationState class provides state that handle an animation and emit +a signal when this animation is finished. + +\ingroup statemachine + +QAnimationState provides a state that handle an animation. It will start this animation +when the state is entered and stop it when it is leaved. When the animation has finished the +state emit animationFinished signal. +QAnimationState is part of \l{The State Machine Framework}. + +\code +QStateMachine machine; +QAnimationState *s = new QAnimationState(machine->rootState()); +QPropertyAnimation *animation = new QPropertyAnimation(obj, "pos"); +s->setAnimation(animation); +QState *s2 = new QState(machine->rootState()); +s->addTransition(s, &QAnimationState::animationFinished, s2); +machine.start(); +\endcode + +\sa QState, {The Animation Framework} +*/ + +/*! + Constructs a new state with the given \a parent state. +*/ +QAnimationState::QAnimationState(QState *parent) + : QState(parent), m_animation(nullptr) +{ +} + +/*! + Destroys the animation state. +*/ +QAnimationState::~QAnimationState() +{ +} + +/*! + Set an \a animation for this QAnimationState. If an animation was previously handle by this + state then it won't emit animationFinished for the old animation. The QAnimationState doesn't + take the ownership of the animation. +*/ +void QAnimationState::setAnimation(QAbstractAnimation *animation) +{ + if (animation == m_animation) + return; + + //Disconnect from the previous animation if exist + if (m_animation) + disconnect(m_animation, &QAbstractAnimation::finished, this, &QAnimationState::animationFinished); + + m_animation = animation; + + if (m_animation) { + //connect the new animation + connect(m_animation, &QAbstractAnimation::finished, this, &QAnimationState::animationFinished); + } +} + +/*! + Returns the animation handle by this animation state, or \nullptr if there is no animation. +*/ +QAbstractAnimation* QAnimationState::animation() const +{ + return m_animation; +} + +/*! + \reimp +*/ +void QAnimationState::onEntry(QEvent *) +{ + if (m_animation) + m_animation->start(); +} + +/*! + \reimp +*/ +void QAnimationState::onExit(QEvent *) +{ + if (m_animation) + m_animation->stop(); +} + +/*! + \reimp +*/ +bool QAnimationState::event(QEvent *e) +{ + return QState::event(e); +} + +QT_END_NAMESPACE diff --git a/examples/widgets/animation/sub-attaq/qanimationstate.h b/examples/widgets/animation/sub-attaq/qanimationstate.h new file mode 100644 index 0000000..2475985 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/qanimationstate.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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$ +** +****************************************************************************/ + +#ifndef QANIMATIONSTATE_H +#define QANIMATIONSTATE_H + +#include <QState> + +QT_BEGIN_NAMESPACE + +class QAbstractAnimation; + +class QAnimationState : public QState +{ + Q_OBJECT +public: + QAnimationState(QState *parent = nullptr); + ~QAnimationState(); + + void setAnimation(QAbstractAnimation *animation); + QAbstractAnimation* animation() const; + +signals: + void animationFinished(); + +protected: + void onEntry(QEvent *) override; + void onExit(QEvent *) override; + bool event(QEvent *e) override; + +private: + Q_DISABLE_COPY(QAnimationState) + QAbstractAnimation *m_animation; +}; + +QT_END_NAMESPACE + +#endif // QANIMATIONSTATE_H diff --git a/examples/widgets/animation/sub-attaq/states.cpp b/examples/widgets/animation/sub-attaq/states.cpp new file mode 100644 index 0000000..c7e2738 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/states.cpp @@ -0,0 +1,335 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "states.h" +#include "graphicsscene.h" +#include "boat.h" +#include "submarine.h" +#include "torpedo.h" +#include "animationmanager.h" +#include "progressitem.h" +#include "textinformationitem.h" + +//Qt +#include <QFinalState> +#include <QGraphicsView> +#include <QKeyEventTransition> +#include <QMessageBox> +#include <QRandomGenerator> +#include <QStateMachine> + +PlayState::PlayState(GraphicsScene *scene, QState *parent) + : QState(parent), scene(scene), machine(nullptr), + currentLevel(0), score(0) +{ +} + +PlayState::~PlayState() +{ + delete machine; +} + +void PlayState::onEntry(QEvent *) +{ + //We are now playing? + if (machine) { + machine->stop(); + //we hide the information + scene->textInformationItem->hide(); + scene->clearScene(); + currentLevel = 0; + score = 0; + delete machine; + } + + machine = new QStateMachine; + + //This state is when player is playing + LevelState *levelState = new LevelState(scene, this, machine); + + //This state is when the player is actually playing but the game is not paused + QState *playingState = new QState(levelState); + levelState->setInitialState(playingState); + + //This state is when the game is paused + PauseState *pauseState = new PauseState(scene, levelState); + + //We have one view, it receive the key press event + QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); + pressPplay->setTargetState(pauseState); + QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); + pressPpause->setTargetState(playingState); + + //Pause "P" is triggered, the player pause the game + playingState->addTransition(pressPplay); + + //To get back playing when the game has been paused + pauseState->addTransition(pressPpause); + + //This state is when player have lost + LostState *lostState = new LostState(scene, this, machine); + + //This state is when player have won + WinState *winState = new WinState(scene, this, machine); + + //The boat has been destroyed then the game is finished + levelState->addTransition(scene->boat, &Boat::boatExecutionFinished,lostState); + + //This transition check if we won or not + WinTransition *winTransition = new WinTransition(scene, this, winState); + + //The boat has been destroyed then the game is finished + levelState->addTransition(winTransition); + + //This state is an animation when the score changed + UpdateScoreState *scoreState = new UpdateScoreState(levelState); + + //This transition update the score when a submarine die + UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, levelState); + scoreTransition->setTargetState(scoreState); + + //The boat has been destroyed then the game is finished + playingState->addTransition(scoreTransition); + + //We go back to play state + scoreState->addTransition(playingState); + + //We start playing!!! + machine->setInitialState(levelState); + + //Final state + QFinalState *finalState = new QFinalState(machine); + + //This transition is triggered when the player press space after completing a level + CustomSpaceTransition *spaceTransition = new CustomSpaceTransition(scene->views().at(0), this, QEvent::KeyPress, Qt::Key_Space); + spaceTransition->setTargetState(levelState); + winState->addTransition(spaceTransition); + + //We lost we should reach the final state + lostState->addTransition(lostState, &QState::finished, finalState); + + machine->start(); +} + +LevelState::LevelState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) +{ +} +void LevelState::onEntry(QEvent *) +{ + initializeLevel(); +} + +void LevelState::initializeLevel() +{ + //we re-init the boat + scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height()); + scene->boat->setCurrentSpeed(0); + scene->boat->setCurrentDirection(Boat::None); + scene->boat->setBombsLaunched(0); + scene->boat->show(); + scene->setFocusItem(scene->boat, Qt::OtherFocusReason); + scene->boat->run(); + + scene->progressItem->setScore(game->score); + scene->progressItem->setLevel(game->currentLevel + 1); + + const GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(game->currentLevel); + for (const QPair<int,int> &subContent : currentLevelDescription.submarines) { + + GraphicsScene::SubmarineDescription submarineDesc = scene->submarinesData.at(subContent.first); + + for (int j = 0; j < subContent.second; ++j ) { + SubMarine *sub = new SubMarine(submarineDesc.type, submarineDesc.name, submarineDesc.points); + scene->addItem(sub); + int random = QRandomGenerator::global()->bounded(15) + 1; + qreal x = random == 13 || random == 5 ? 0 : scene->width() - sub->size().width(); + qreal y = scene->height() -(QRandomGenerator::global()->bounded(150) + 1) - sub->size().height(); + sub->setPos(x,y); + sub->setCurrentDirection(x == 0 ? SubMarine::Right : SubMarine::Left); + sub->setCurrentSpeed(QRandomGenerator::global()->bounded(3) + 1); + } + } +} + +/** Pause State */ +PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent), scene(scene) +{ +} + +void PauseState::onEntry(QEvent *) +{ + AnimationManager::self()->pauseAll(); + scene->boat->setEnabled(false); +} +void PauseState::onExit(QEvent *) +{ + AnimationManager::self()->resumeAll(); + scene->boat->setEnabled(true); + scene->boat->setFocus(); +} + +/** Lost State */ +LostState::LostState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) +{ +} + +void LostState::onEntry(QEvent *) +{ + //The message to display + QString message = QString("You lose on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); + + //We set the level back to 0 + game->currentLevel = 0; + + //We set the score back to 0 + game->score = 0; + + //We clear the scene + scene->clearScene(); + + //We inform the player + scene->textInformationItem->setMessage(message); + scene->textInformationItem->show(); +} + +void LostState::onExit(QEvent *) +{ + //we hide the information + scene->textInformationItem->hide(); +} + +/** Win State */ +WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) +{ +} + +void WinState::onEntry(QEvent *) +{ + //We clear the scene + scene->clearScene(); + + QString message; + if (scene->levelsData.size() - 1 != game->currentLevel) { + message = QString("You win the level %1. Your score is %2.\nPress Space to continue.").arg(game->currentLevel+1).arg(game->score); + //We increment the level number + game->currentLevel++; + } else { + message = QString("You finish the game on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); + //We set the level back to 0 + game->currentLevel = 0; + //We set the score back to 0 + game->score = 0; + } + + //We inform the player + scene->textInformationItem->setMessage(message); + scene->textInformationItem->show(); +} + +void WinState::onExit(QEvent *) +{ + //we hide the information + scene->textInformationItem->hide(); +} + +/** UpdateScore State */ +UpdateScoreState::UpdateScoreState(QState *parent) : QState(parent) +{ +} + +/** Win transition */ +UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) + : QSignalTransition(scene, &GraphicsScene::subMarineDestroyed), + game(game), scene(scene) +{ + setTargetState(target); +} + +bool UpdateScoreTransition::eventTest(QEvent *event) +{ + if (!QSignalTransition::eventTest(event)) + return false; + QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event); + game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); + return true; +} + +/** Win transition */ +WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) + : QSignalTransition(scene, &GraphicsScene::allSubMarineDestroyed), + game(game), scene(scene) +{ + setTargetState(target); +} + +bool WinTransition::eventTest(QEvent *event) +{ + if (!QSignalTransition::eventTest(event)) + return false; + QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(event); + game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); + return true; +} + +/** Space transition */ +CustomSpaceTransition::CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key) + : QKeyEventTransition(widget, type, key), game(game) +{ +} + +bool CustomSpaceTransition::eventTest(QEvent *event) +{ + if (!QKeyEventTransition::eventTest(event)) + return false; + return (game->currentLevel != 0); +} diff --git a/examples/widgets/animation/sub-attaq/states.h b/examples/widgets/animation/sub-attaq/states.h new file mode 100644 index 0000000..b3651e1 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/states.h @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef STATES_H +#define STATES_H + +//Qt +#include <QKeyEventTransition> +#include <QSignalTransition> +#include <QState> + +class GraphicsScene; +QT_BEGIN_NAMESPACE +class QStateMachine; +QT_END_NAMESPACE + +class PlayState : public QState +{ +public: + explicit PlayState(GraphicsScene *scene, QState *parent = nullptr); + ~PlayState(); + + protected: + void onEntry(QEvent *) override; + +private : + GraphicsScene *scene; + QStateMachine *machine; + int currentLevel; + int score; + + friend class UpdateScoreState; + friend class UpdateScoreTransition; + friend class WinTransition; + friend class CustomSpaceTransition; + friend class WinState; + friend class LostState; + friend class LevelState; +}; + +class LevelState : public QState +{ +public: + LevelState(GraphicsScene *scene, PlayState *game, QState *parent = nullptr); +protected: + void onEntry(QEvent *) override; +private : + void initializeLevel(); + GraphicsScene *scene; + PlayState *game; +}; + +class PauseState : public QState +{ +public: + explicit PauseState(GraphicsScene *scene, QState *parent = nullptr); + +protected: + void onEntry(QEvent *) override; + void onExit(QEvent *) override; +private : + GraphicsScene *scene; +}; + +class LostState : public QState +{ +public: + LostState(GraphicsScene *scene, PlayState *game, QState *parent = nullptr); + +protected: + void onEntry(QEvent *) override; + void onExit(QEvent *) override; +private : + GraphicsScene *scene; + PlayState *game; +}; + +class WinState : public QState +{ +public: + WinState(GraphicsScene *scene, PlayState *game, QState *parent = nullptr); + +protected: + void onEntry(QEvent *) override; + void onExit(QEvent *) override; +private : + GraphicsScene *scene; + PlayState *game; +}; + +class UpdateScoreState : public QState +{ +public: + UpdateScoreState(QState *parent); +private: +}; + +//These transtion is used to update the score +class UpdateScoreTransition : public QSignalTransition +{ +public: + UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target); +protected: + bool eventTest(QEvent *event) override; +private: + PlayState *game; + GraphicsScene *scene; +}; + +//These transtion test if we have won the game +class WinTransition : public QSignalTransition +{ +public: + WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target); +protected: + bool eventTest(QEvent *event) override; +private: + PlayState *game; + GraphicsScene *scene; +}; + +//These transtion is true if one level has been completed and the player want to continue + class CustomSpaceTransition : public QKeyEventTransition +{ +public: + CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key); +protected: + bool eventTest(QEvent *event) override; +private: + PlayState *game; +}; + +#endif // STATES_H diff --git a/examples/widgets/animation/sub-attaq/sub-attaq.pro b/examples/widgets/animation/sub-attaq/sub-attaq.pro new file mode 100644 index 0000000..925678b --- /dev/null +++ b/examples/widgets/animation/sub-attaq/sub-attaq.pro @@ -0,0 +1,33 @@ +QT += statemachine widgets +HEADERS += boat.h \ + bomb.h \ + mainwindow.h \ + submarine.h \ + torpedo.h \ + pixmapitem.h \ + graphicsscene.h \ + animationmanager.h \ + states.h \ + boat_p.h \ + submarine_p.h \ + qanimationstate.h \ + progressitem.h \ + textinformationitem.h +SOURCES += boat.cpp \ + bomb.cpp \ + main.cpp \ + mainwindow.cpp \ + submarine.cpp \ + torpedo.cpp \ + pixmapitem.cpp \ + graphicsscene.cpp \ + animationmanager.cpp \ + states.cpp \ + qanimationstate.cpp \ + progressitem.cpp \ + textinformationitem.cpp +RESOURCES += subattaq.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/sub-attaq +INSTALLS += target diff --git a/examples/widgets/animation/sub-attaq/subattaq.qrc b/examples/widgets/animation/sub-attaq/subattaq.qrc new file mode 100644 index 0000000..80a3af1 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/subattaq.qrc @@ -0,0 +1,39 @@ +<RCC> + <qresource prefix="/" > + <file alias="all" >pics/scalable/sub-attaq.svg</file> + <file alias="submarine" >pics/scalable/submarine.svg</file> + <file alias="boat" >pics/scalable/boat.svg</file> + <file alias="torpedo" >pics/scalable/torpedo.svg</file> + <file alias="logo-s" >pics/welcome/logo-s.png</file> + <file alias="logo-u" >pics/welcome/logo-u.png</file> + <file alias="logo-b" >pics/welcome/logo-b.png</file> + <file alias="logo-dash" >pics/welcome/logo-dash.png</file> + <file alias="logo-a" >pics/welcome/logo-a.png</file> + <file alias="logo-t" >pics/welcome/logo-t.png</file> + <file alias="logo-t2" >pics/welcome/logo-t2.png</file> + <file alias="logo-a2" >pics/welcome/logo-a2.png</file> + <file alias="logo-q" >pics/welcome/logo-q.png</file> + <file alias="logo-excl" >pics/welcome/logo-excl.png</file> + <file alias="big/background" >pics/big/background.png</file> + <file alias="big/boat" >pics/big/boat.png</file> + <file alias="big/bomb" >pics/big/bomb.png</file> + <file alias="big/submarine" >pics/big/submarine.png</file> + <file alias="big/surface" >pics/big/surface.png</file> + <file alias="big/torpedo" >pics/big/torpedo.png</file> + <file alias="small/background" >pics/small/background.png</file> + <file alias="small/boat" >pics/small/boat.png</file> + <file alias="small/bomb" >pics/small/bomb.png</file> + <file alias="small/submarine" >pics/small/submarine.png</file> + <file alias="small/surface" >pics/small/surface.png</file> + <file alias="small/torpedo" >pics/small/torpedo.png</file> + <file alias="big/explosion/boat/step1" >pics/big/explosion/boat/step1.png</file> + <file alias="big/explosion/boat/step2" >pics/big/explosion/boat/step2.png</file> + <file alias="big/explosion/boat/step3" >pics/big/explosion/boat/step3.png</file> + <file alias="big/explosion/boat/step4" >pics/big/explosion/boat/step4.png</file> + <file alias="big/explosion/submarine/step1" >pics/big/explosion/submarine/step1.png</file> + <file alias="big/explosion/submarine/step2" >pics/big/explosion/submarine/step2.png</file> + <file alias="big/explosion/submarine/step3" >pics/big/explosion/submarine/step3.png</file> + <file alias="big/explosion/submarine/step4" >pics/big/explosion/submarine/step4.png</file> + <file>data.xml</file> + </qresource> +</RCC> diff --git a/examples/widgets/animation/sub-attaq/submarine.cpp b/examples/widgets/animation/sub-attaq/submarine.cpp new file mode 100644 index 0000000..a4ca376 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/submarine.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "submarine.h" +#include "submarine_p.h" +#include "torpedo.h" +#include "graphicsscene.h" +#include "animationmanager.h" +#include "qanimationstate.h" + +#include <QFinalState> +#include <QPropertyAnimation> +#include <QStateMachine> +#include <QSequentialAnimationGroup> + +static QAbstractAnimation *setupDestroyAnimation(SubMarine *sub) +{ + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(sub); + for (int i = 1; i <= 4; ++i) { + PixmapItem *step = new PixmapItem(QString::fromLatin1("explosion/submarine/step%1").arg(i), GraphicsScene::Big, sub); + step->setZValue(6); + step->setOpacity(0); + QPropertyAnimation *anim = new QPropertyAnimation(step, "opacity", group); + anim->setDuration(100); + anim->setEndValue(1); + } + AnimationManager::self()->registerAnimation(group); + return group; +} + + +SubMarine::SubMarine(int type, const QString &name, int points) : PixmapItem(QString("submarine"), GraphicsScene::Big), + subType(type), subName(name), subPoints(points), speed(0), direction(SubMarine::None) +{ + setZValue(5); + setTransformOriginPoint(boundingRect().center()); + + graphicsRotation = new QGraphicsRotation(this); + graphicsRotation->setAxis(Qt::YAxis); + graphicsRotation->setOrigin(QVector3D(size().width() / 2, size().height() / 2, 0)); + QList<QGraphicsTransform *> r({graphicsRotation}); + setTransformations(r); + + //We setup the state machine of the submarine + QStateMachine *machine = new QStateMachine(this); + + //This state is when the boat is moving/rotating + QState *moving = new QState(machine); + + //This state is when the boat is moving from left to right + MovementState *movement = new MovementState(this, moving); + + //This state is when the boat is moving from left to right + ReturnState *rotation = new ReturnState(this, moving); + + //This is the initial state of the moving root state + moving->setInitialState(movement); + + movement->addTransition(this, &SubMarine::subMarineStateChanged, moving); + + //This is the initial state of the machine + machine->setInitialState(moving); + + //End + QFinalState *finalState = new QFinalState(machine); + + //If the moving animation is finished we move to the return state + movement->addTransition(movement, &QAnimationState::animationFinished, rotation); + + //If the return animation is finished we move to the moving state + rotation->addTransition(rotation, &QAnimationState::animationFinished, movement); + + //This state play the destroyed animation + QAnimationState *destroyedState = new QAnimationState(machine); + destroyedState->setAnimation(setupDestroyAnimation(this)); + + //Play a nice animation when the submarine is destroyed + moving->addTransition(this, &SubMarine::subMarineDestroyed, destroyedState); + + //Transition to final state when the destroyed animation is finished + destroyedState->addTransition(destroyedState, &QAnimationState::animationFinished, finalState); + + //The machine has finished to be executed, then the submarine is dead + connect(machine,&QState::finished,this, &SubMarine::subMarineExecutionFinished); + + machine->start(); +} + +int SubMarine::points() const +{ + return subPoints; +} + +void SubMarine::setCurrentDirection(SubMarine::Movement direction) +{ + if (this->direction == direction) + return; + if (direction == SubMarine::Right && this->direction == SubMarine::None) + graphicsRotation->setAngle(180); + this->direction = direction; +} + +enum SubMarine::Movement SubMarine::currentDirection() const +{ + return direction; +} + +void SubMarine::setCurrentSpeed(int speed) +{ + if (speed < 0 || speed > 3) + qWarning("SubMarine::setCurrentSpeed : The speed is invalid"); + this->speed = speed; + emit subMarineStateChanged(); +} + +int SubMarine::currentSpeed() const +{ + return speed; +} + +void SubMarine::launchTorpedo(int speed) +{ + Torpedo *torp = new Torpedo; + GraphicsScene *scene = static_cast<GraphicsScene *>(this->scene()); + scene->addItem(torp); + torp->setPos(pos()); + torp->setCurrentSpeed(speed); + torp->launch(); +} + +void SubMarine::destroy() +{ + emit subMarineDestroyed(); +} + +int SubMarine::type() const +{ + return Type; +} diff --git a/examples/widgets/animation/sub-attaq/submarine.h b/examples/widgets/animation/sub-attaq/submarine.h new file mode 100644 index 0000000..256683e --- /dev/null +++ b/examples/widgets/animation/sub-attaq/submarine.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef SUBMARINE_H +#define SUBMARINE_H + +#include "pixmapitem.h" + +#include <QGraphicsRotation> + +class SubMarine : public PixmapItem +{ +Q_OBJECT +public: + enum Movement { + None = 0, + Left, + Right + }; + enum { Type = UserType + 1 }; + SubMarine(int type, const QString &name, int points); + + int points() const; + + void setCurrentDirection(Movement direction); + enum Movement currentDirection() const; + + void setCurrentSpeed(int speed); + int currentSpeed() const; + + void launchTorpedo(int speed); + void destroy(); + + int type() const override; + + QGraphicsRotation *rotation() const { return graphicsRotation; } + +signals: + void subMarineDestroyed(); + void subMarineExecutionFinished(); + void subMarineStateChanged(); + +private: + int subType; + QString subName; + int subPoints; + int speed; + Movement direction; + QGraphicsRotation *graphicsRotation; +}; + +#endif // SUBMARINE_H diff --git a/examples/widgets/animation/sub-attaq/submarine_p.h b/examples/widgets/animation/sub-attaq/submarine_p.h new file mode 100644 index 0000000..36807da --- /dev/null +++ b/examples/widgets/animation/sub-attaq/submarine_p.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef SUBMARINE_P_H +#define SUBMARINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +//Own +#include "animationmanager.h" +#include "submarine.h" +#include "qanimationstate.h" + +//Qt +#include <QPropertyAnimation> +#include <QRandomGenerator> + +//This state is describing when the boat is moving right +class MovementState : public QAnimationState +{ +Q_OBJECT +public: + explicit MovementState(SubMarine *submarine, QState *parent = nullptr) : QAnimationState(parent) + { + movementAnimation = new QPropertyAnimation(submarine, "pos"); + connect(movementAnimation, &QPropertyAnimation::valueChanged, + this, &MovementState::onAnimationMovementValueChanged); + setAnimation(movementAnimation); + AnimationManager::self()->registerAnimation(movementAnimation); + this->submarine = submarine; + } + +protected slots: + void onAnimationMovementValueChanged(const QVariant &) + { + if (QRandomGenerator::global()->bounded(200) + 1 == 3) + submarine->launchTorpedo(QRandomGenerator::global()->bounded(3) + 1); + } + +protected: + void onEntry(QEvent *e) override + { + if (submarine->currentDirection() == SubMarine::Left) { + movementAnimation->setEndValue(QPointF(0,submarine->y())); + movementAnimation->setDuration(submarine->x()/submarine->currentSpeed()*12); + } + else /*if (submarine->currentDirection() == SubMarine::Right)*/ { + movementAnimation->setEndValue(QPointF(submarine->scene()->width()-submarine->size().width(),submarine->y())); + movementAnimation->setDuration((submarine->scene()->width()-submarine->size().width()-submarine->x())/submarine->currentSpeed()*12); + } + QAnimationState::onEntry(e); + } + +private: + SubMarine *submarine; + QPropertyAnimation *movementAnimation; +}; + +//This state is describing when the boat is moving right +class ReturnState : public QAnimationState +{ +public: + explicit ReturnState(SubMarine *submarine, QState *parent = nullptr) : QAnimationState(parent) + { + returnAnimation = new QPropertyAnimation(submarine->rotation(), "angle"); + returnAnimation->setDuration(500); + AnimationManager::self()->registerAnimation(returnAnimation); + setAnimation(returnAnimation); + this->submarine = submarine; + } + +protected: + void onEntry(QEvent *e) override + { + returnAnimation->stop(); + returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.); + QAnimationState::onEntry(e); + } + + void onExit(QEvent *e) override + { + submarine->currentDirection() == SubMarine::Right ? submarine->setCurrentDirection(SubMarine::Left) : submarine->setCurrentDirection(SubMarine::Right); + QAnimationState::onExit(e); + } + +private: + SubMarine *submarine; + QPropertyAnimation *returnAnimation; +}; + +#endif // SUBMARINE_P_H diff --git a/examples/widgets/animation/sub-attaq/textinformationitem.cpp b/examples/widgets/animation/sub-attaq/textinformationitem.cpp new file mode 100644 index 0000000..4d4934f --- /dev/null +++ b/examples/widgets/animation/sub-attaq/textinformationitem.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "textinformationitem.h" +#include "pixmapitem.h" + +TextInformationItem::TextInformationItem (QGraphicsItem *parent) + : QGraphicsTextItem(parent) +{ + setFont(QFont("Comic Sans MS", 15)); +} + +void TextInformationItem::setMessage(const QString &text) +{ + setHtml(text); + setPos(parentItem()->boundingRect().center().x() - boundingRect().size().width() / 2, + parentItem()->boundingRect().center().y()); +} diff --git a/examples/widgets/animation/sub-attaq/textinformationitem.h b/examples/widgets/animation/sub-attaq/textinformationitem.h new file mode 100644 index 0000000..0a0b618 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/textinformationitem.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef TEXTINFORMATIONITEM_H +#define TEXTINFORMATIONITEM_H + +//Qt +#include <QGraphicsTextItem> + +class TextInformationItem : public QGraphicsTextItem +{ +public: + TextInformationItem(QGraphicsItem *parent = nullptr); + void setMessage(const QString &text); +}; + +#endif // TEXTINFORMATIONITEM_H diff --git a/examples/widgets/animation/sub-attaq/torpedo.cpp b/examples/widgets/animation/sub-attaq/torpedo.cpp new file mode 100644 index 0000000..7395aa3 --- /dev/null +++ b/examples/widgets/animation/sub-attaq/torpedo.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +//Own +#include "torpedo.h" +#include "boat.h" +#include "graphicsscene.h" +#include "animationmanager.h" +#include "qanimationstate.h" + +#include <QPropertyAnimation> +#include <QStateMachine> +#include <QFinalState> + +Torpedo::Torpedo() : PixmapItem(QString::fromLatin1("torpedo"),GraphicsScene::Big), + currentSpeed(0) +{ + setZValue(2); +} + +void Torpedo::launch() +{ + QPropertyAnimation *launchAnimation = new QPropertyAnimation(this, "pos"); + AnimationManager::self()->registerAnimation(launchAnimation); + launchAnimation->setEndValue(QPointF(x(), qobject_cast<GraphicsScene *>(scene())->sealLevel() - 15)); + launchAnimation->setEasingCurve(QEasingCurve::InQuad); + launchAnimation->setDuration(y() / currentSpeed * 10); + connect(launchAnimation, &QVariantAnimation::valueChanged, this, &Torpedo::onAnimationLaunchValueChanged); + connect(this, &Torpedo::torpedoExploded, launchAnimation, &QAbstractAnimation::stop); + + //We setup the state machine of the torpedo + QStateMachine *machine = new QStateMachine(this); + + //This state is when the launch animation is playing + QAnimationState *launched = new QAnimationState(machine); + launched->setAnimation(launchAnimation); + + //End + QFinalState *finalState = new QFinalState(machine); + + machine->setInitialState(launched); + + //### Add a nice animation when the torpedo is destroyed + launched->addTransition(this, &Torpedo::torpedoExploded, finalState); + + //If the animation is finished, then we move to the final state + launched->addTransition(launched, &QAnimationState::animationFinished, finalState); + + //The machine has finished to be executed, then the boat is dead + connect(machine, &QState::finished, this, &Torpedo::torpedoExecutionFinished); + + machine->start(); +} + +void Torpedo::setCurrentSpeed(int speed) +{ + if (speed < 0) { + qWarning("Torpedo::setCurrentSpeed : The speed is invalid"); + return; + } + currentSpeed = speed; +} + +void Torpedo::onAnimationLaunchValueChanged(const QVariant &) +{ + const QList<QGraphicsItem *> colItems = + collidingItems(Qt::IntersectsItemBoundingRect); + for (QGraphicsItem *item : colItems) { + if (Boat *b = qgraphicsitem_cast<Boat*>(item)) + b->destroy(); + } +} + +void Torpedo::destroy() +{ + emit torpedoExploded(); +} diff --git a/examples/widgets/animation/sub-attaq/torpedo.h b/examples/widgets/animation/sub-attaq/torpedo.h new file mode 100644 index 0000000..7ac853d --- /dev/null +++ b/examples/widgets/animation/sub-attaq/torpedo.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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$ +** +****************************************************************************/ + +#ifndef TORPEDO_H +#define TORPEDO_H + +#include "pixmapitem.h" + +class Torpedo : public PixmapItem +{ +Q_OBJECT +public: + Torpedo(); + void launch(); + void setCurrentSpeed(int speed); + void destroy(); + +signals: + void torpedoExploded(); + void torpedoExecutionFinished(); + +private slots: + void onAnimationLaunchValueChanged(const QVariant &); + +private: + int currentSpeed; +}; + +#endif // TORPEDO_H diff --git a/examples/widgets/doc/images/factorial-example.png b/examples/widgets/doc/images/factorial-example.png Binary files differnew file mode 100644 index 0000000..8fb1cc6 --- /dev/null +++ b/examples/widgets/doc/images/factorial-example.png diff --git a/examples/widgets/doc/images/pingpong-example.png b/examples/widgets/doc/images/pingpong-example.png Binary files differnew file mode 100644 index 0000000..af707e4 --- /dev/null +++ b/examples/widgets/doc/images/pingpong-example.png diff --git a/examples/widgets/doc/images/trafficlight-example1.png b/examples/widgets/doc/images/trafficlight-example1.png Binary files differnew file mode 100644 index 0000000..ec8c7ff --- /dev/null +++ b/examples/widgets/doc/images/trafficlight-example1.png diff --git a/examples/widgets/doc/images/trafficlight-example2.png b/examples/widgets/doc/images/trafficlight-example2.png Binary files differnew file mode 100644 index 0000000..a12e4db --- /dev/null +++ b/examples/widgets/doc/images/trafficlight-example2.png diff --git a/examples/widgets/doc/src/animatedtiles.qdoc b/examples/widgets/doc/src/animatedtiles.qdoc new file mode 100644 index 0000000..9f1d912 --- /dev/null +++ b/examples/widgets/doc/src/animatedtiles.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example animation/animatedtiles + \title Animated Tiles Example + + \brief The Animated Tiles example animates items in a graphics scene. + + \image animatedtiles-example.png +*/ + diff --git a/examples/widgets/doc/src/eventtransitions.qdoc b/examples/widgets/doc/src/eventtransitions.qdoc new file mode 100644 index 0000000..e74831b --- /dev/null +++ b/examples/widgets/doc/src/eventtransitions.qdoc @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/eventtransitions + \title Event Transitions Example + + \brief The Event Transitions example shows how to use event transitions, + a feature of \l{The State Machine Framework}. + + The Event Transitions Example illustrates how states change when a + user enters or leaves the area of a button. The states are handled by + a QStateMachine object. The screen consists of a QVBoxLayout with a + central button. + + When the mouse is outside the button, the text in the button displays + "Outside". When the mouse enters the button, it displays "Inside". + + \borderedimage transitions.png + + \snippet statemachine/eventtransitions/main.cpp 0 + + The \c Window class's constructors begins by creating a button. + This button is added to \c layout, which is a QVBoxLayout object. + Then two states are created: \c s1 is the state + "Outside", and \c s2 is the state "Inside". + + \snippet statemachine/eventtransitions/main.cpp 1 + + State \c s1 is the state "Outside" and state \c s2 is state "Inside". + + \snippet statemachine/eventtransitions/main.cpp 2 + + When the button receives an event of type QEvent::Enter and the state + machine is in state \c s1, the machine will transition to state \c s2. + + \snippet statemachine/eventtransitions/main.cpp 3 + + When the button receives an event of type QEvent::Leave and the state + machine is in state \c s2, the machine will transition back to state \c + s1. + + \snippet statemachine/eventtransitions/main.cpp 4 + + Next, state \c s3 is created. \c s3 will be entered when the button + receives an event of type QEvent::MouseButtonPress and the state machine + is in state \c s2. When the button receives an event of type + QEvent::MouseButtonRelease and the state machine is in state \c s3, the + machine will revert to state \c s2. + + \snippet statemachine/eventtransitions/main.cpp 5 + + Finally, the states are added to the machine as top-level states, the + initial state is set to be \c s1 ("Outside"), and the machine is started. + + \snippet statemachine/eventtransitions/main.cpp 6 + + The main() function constructs a Window object that displays the QVBoxLayout + object \c layout with its \c button. + +*/ diff --git a/examples/widgets/doc/src/factorial.qdoc b/examples/widgets/doc/src/factorial.qdoc new file mode 100644 index 0000000..a0ace96 --- /dev/null +++ b/examples/widgets/doc/src/factorial.qdoc @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/factorial + \title Factorial States Example + + \brief The Factorial States example shows how to use \l{The State Machine + Framework} to calculate the factorial of an integer. + + The statechart for calculating the factorial looks as follows: + + \image factorial-example.png + \omit + \caption This is a caption + \endomit + + In other words, the state machine calculates the factorial of 6 and prints + the result. + + \snippet statemachine/factorial/main.cpp 0 + + The Factorial class is used to hold the data of the computation, \c x and + \c fac. It also provides a signal that's emitted whenever the value of \c + x changes. + + \snippet statemachine/factorial/main.cpp 1 + + The FactorialLoopTransition class implements the guard (\c x > 1) and + calculations (\c fac = \c x * \c fac; \c x = \c x - 1) of the factorial + loop. + + \snippet statemachine/factorial/main.cpp 2 + + The FactorialDoneTransition class implements the guard (\c x <= 1) that + terminates the factorial computation. It also prints the final result to + standard output. + + \snippet statemachine/factorial/main.cpp 3 + + The application's main() function first creates the application object, a + Factorial object and a state machine. + + \snippet statemachine/factorial/main.cpp 4 + + The \c compute state is created, and the initial values of \c x and \c fac + are defined. A FactorialLoopTransition object is created and added to the + state. + + \snippet statemachine/factorial/main.cpp 5 + + A final state, \c done, is created, and a FactorialDoneTransition object + is created with \c done as its target state. The transition is then added + to the \c compute state. + + \snippet statemachine/factorial/main.cpp 6 + + The machine's initial state is set to be the \c compute state. We connect + the QStateMachine::finished() signal to the QCoreApplication::quit() slot, + so the application will quit when the state machine's work is + done. Finally, the state machine is started, and the application's event + loop is entered. + + */ diff --git a/examples/widgets/doc/src/moveblocks.qdoc b/examples/widgets/doc/src/moveblocks.qdoc new file mode 100644 index 0000000..64045f1 --- /dev/null +++ b/examples/widgets/doc/src/moveblocks.qdoc @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example animation/moveblocks + \title Move Blocks Example + + \brief The Move Blocks example shows how to animate items in a + QGraphicsScene using a QStateMachine with a custom transition. + + \image moveblocks-example.png + + The example animates the blue blocks that you can see in the image + above. The animation moves the blocks between four preset positions. + + The example consists of the following classes: + + \list + \li \c StateSwitcher inherits QState and can add + \c {StateSwitchTransition}s to other states. + When entered, it will randomly transition to one of these + states. + \li \c StateSwitchTransition is a custom transition that + triggers on \c{StateSwitchEvent}s. + \li \c StateSwitchEvent is a QEvent that triggers \c{StateSwitchTransition}s. + \li \c QGraphicsRectWidget is a QGraphicsWidget that simply + paints its background in a solid \l{Qt::}{blue} color. + \endlist + + The blocks are instances of \c QGraphicsRectWidget and are + animated in a QGraphicsScene. We do this by building a state + graph, which we insert animations into. The graph is then executed + in a QStateMachine. All this is done in \c main(). + Let's look at the \c main() function first. + + \section1 The \c main() Function + + After QApplication has been initialized, we set up the + QGraphicsScene with its \c{QGraphicsRectWidget}s. + + \snippet animation/moveblocks/main.cpp 1 + + After adding the scene to a QGraphicsView, it is time to build the + state graph. Let's first look at a statechart of what we are + trying to build. + + \image move-blocks-chart.png + + Note that the \c group has seven sub states, but we have only + included three of them in the diagram. The code that builds this + graph will be examined line-by-line, and will show how the graph + works. First off, we construct the \c group state: + + \snippet animation/moveblocks/main.cpp 2 + + The timer is used to add a delay between each time the blocks are + moved. The timer is started when \c group is entered. As we will + see later, \c group has a transition back to the \c StateSwitcher + when the timer times out. \c group is the initial state in the + machine, so an animation will be scheduled when the example is + started. + + \snippet animation/moveblocks/main.cpp 3 + \dots + \snippet animation/moveblocks/main.cpp 4 + + \c createGeometryState() returns a QState that will set the + geometry of our items upon entry. It also assigns \c group as the + parent of this state. + + A QPropertyAnimation inserted into a transition will use the + values assigned to a QState (with QState::assignProperty()), i.e., + the animation will interpolate between the current values of the + properties and the values in the target state. We add animated + transitions to the state graph later. + + \snippet animation/moveblocks/main.cpp 5 + + We move the items in parallel. Each item is added to \c + animationGroup, which is the animation that is inserted into the + transitions. + + \snippet animation/moveblocks/main.cpp 6 + + The sequential animation group, \c subGroup, helps us insert a + delay between the animation of each item. + + \snippet animation/moveblocks/main.cpp 7 + \dots + \snippet animation/moveblocks/main.cpp 8 + + A StateSwitchTransition is added to the state switcher + in \c StateSwitcher::addState(). We also add the animation in this + function. Since QPropertyAnimation uses the values from the + states, we can insert the same QPropertyAnimation instance in all + \c {StateSwitchTransition}s. + + As mentioned previously, we add a transition to the state switcher + that triggers when the timer times out. + + \snippet animation/moveblocks/main.cpp 9 + + Finally, we can create the state machine, add our initial state, + and start execution of the state graph. + + \section2 The \c createGeometryState() Function + + In \c createGeometryState(), we set up the geometry for each + graphics item. + + \snippet animation/moveblocks/main.cpp 13 + + As mentioned before, QAbstractTransition will set up an animation + added with \l{QAbstractTransition::}{addAnimation()} using + property values set with \l{QState::}{assignProperty()}. + + \section1 The StateSwitcher Class + + \c StateSwitcher has state switch transitions to each \l{QState}s + we created with \c createGeometryState(). Its job is to transition + to one of these states at random when it is entered. + + All functions in \c StateSwitcher are inlined. We'll step through + its definition. + + \snippet animation/moveblocks/main.cpp 10 + + \c StateSwitcher is a state designed for a particular purpose and + will always be a top-level state. We use \c m_stateCount to keep + track of how many states we are managing, and \c m_lastIndex to + remember which state was the last state to which we transitioned. + + \snippet animation/moveblocks/main.cpp 11 + + We select the next state we are going to transition to, and post a + \c StateSwitchEvent, which we know will trigger the \c + StateSwitchTransition to the selected state. + + \snippet animation/moveblocks/main.cpp 12 + + This is where the magic happens. We assign a number to each state + added. This number is given to both a StateSwitchTransition and to + StateSwitchEvents. As we have seen, state switch events will + trigger a transition with the same number. + + \section1 The StateSwitchTransition Class + + \c StateSwitchTransition inherits QAbstractTransition and triggers + on \c{StateSwitchEvent}s. It contains only inline functions, so + let's take a look at its \l{QAbstractTransition::}{eventTest()} + function, which is the only function that we define.. + + \snippet animation/moveblocks/main.cpp 14 + + \c eventTest is called by QStateMachine when it checks whether a + transition should be triggered--a return value of true means that + it will. We simply check if our assigned number is equal to the + event's number (in which case we fire away). + + \section1 The StateSwitchEvent Class + + \c StateSwitchEvent inherits QEvent, and holds a number that has + been assigned to a state and state switch transition by + \c StateSwitcher. We have already seen how it is used to trigger + \c{StateSwitchTransition}s in \c StateSwitcher. + + \snippet animation/moveblocks/main.cpp 15 + + We only have inlined functions in this class, so a look at its + definition will do. + + \section1 The QGraphicsRectWidget Class + + QGraphicsRectWidget inherits QGraphicsWidget and simply paints its + \l{QWidget::}{rect()} blue. We inline \l{QWidget::}{paintEvent()}, + which is the only function we define. Here is the + QGraphicsRectWidget class definition: + + \snippet animation/moveblocks/main.cpp 16 + + \section1 Moving On + + The technique shown in this example works equally well for all + \l{QPropertyAnimation}s. As long as the value to be animated is a + Qt property, you can insert an animation of it into a state graph. + + QState::addAnimation() takes a QAbstractAnimation, so any type + of animation can be inserted into the graph. +*/ + diff --git a/examples/widgets/doc/src/padnavigator.qdoc b/examples/widgets/doc/src/padnavigator.qdoc new file mode 100644 index 0000000..31440b6 --- /dev/null +++ b/examples/widgets/doc/src/padnavigator.qdoc @@ -0,0 +1,586 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example graphicsview/padnavigator + \title Pad Navigator Example + \ingroup examples-graphicsview + \brief Demonstrates how to create animated user interface. + + The Pad Navigator Example shows how you can use Graphics View together with + embedded widgets and Qt's \l{The State Machine Framework}{state machine + framework} to create a simple but useful, dynamic, animated user interface. + + \image padnavigator-example.png + + The interface consists of a flippable, rotating pad with icons that can be + selected using the arrow keys on your keyboard or keypad. Pressing enter + will flip the pad around and reveal its back side, which has a form + embedded into a QGraphicsProxyWidget. You can interact with the form, and + press the enter key to flip back to the front side of the pad at any time. + + Graphics View provides the QGraphicsScene class for managing and + interacting with a large number of custom-made 2D graphical items derived + from the QGraphicsItem class, and a QGraphicsView widget for visualizing + the items, with support for zooming and rotation. + + This example consists of a \c RoundRectItem class, a \c FlippablePad class, + a \c PadNavigator class, a \c SplashItem class, and a \c main() function. + + \section1 RoundRectItem Class Definition + + The \c RoundRectItem class is used by itself to display the icons on the + pad, and as a base class for \c FlippablePad, the class for the pad itself. + The role of the class is to paint a round rectangle of a specified size and + gradient color, and optionally to paint a pixmap icon on top. To support \c + FlippablePad it also allows filling its contents with a plain window + background color. + + Let's start by reviewing the \c RoundRectItem class declaration. + + \snippet graphicsview/padnavigator/roundrectitem.h 0 + + \c RoundRectItem inherits QGraphicsObject, which makes it easy to control + its properties using QPropertyAnimation. Its constructor takes a rectangle + to determine its bounds, and a color. + + Besides implementing the mandatory \l{QGraphicsItem::paint()}{paint()} and + \l{QGraphicsItem::boundingRect()}{boundingRect()} pure virtual functions, + it also provides the \c pixmap and \c fill properties. + + The \c pixmap property sets an optional pixmap that is drawn on top of the + round rectangle. The \c fill property will, when true, fill the round + rectangle contents with a fixed QPalette::Window background color. + Otherwise the contents are filled using a gradient based on the color + passed to \c RoundRectItem's constructor. + + \snippet graphicsview/padnavigator/roundrectitem.h 1 + + The private data members are: + + \list + \li \c pix: The optional pixmap that is drawn on top of the rectangle. + \li \c fillRect: Corresponds to the \c fill property. + \li \c color: The configurable gradient color fill of the rectangle. + \li \c bounds: The bounds of the rectangle. + \li \c gradient: A precalculated gradient used to fill the rectangle. + \endlist + + We will now review the \c RoundRectItem implementation. Let's start by + looking at its constructor: + + \snippet graphicsview/padnavigator/roundrectitem.cpp 0 + + The constructor initializes its member variables and forwards the \c parent + argument to QGraphicsObject's constructor. It then constructs the linear + gradient that is used in \l{QGraphicsItem::paint()}{paint()} to draw the + round rectangle's gradient background. The linear gradient's starting point + is at the top-left corner of the bounds, and the end is at the bottom-left + corner. The start color is identical to the color passed as an argument, + and a slightly darker color is chosen for the final stop. + + We store this gradient as a member variable to avoid having to recreate the + gradient every time the item is repainted. + + Finally we set the cache mode + \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache}. This mode + causes the item's rendering to be cached into an off-screen pixmap that + remains persistent as we move and transform the item. This mode is ideal + for this example, and works particularly well with OpenGL and OpenGL ES. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 1 + + The \c pixmap property implementation simple returns the member pixmap, or + sets it and then calls \l{QGraphicsItem::update()}{update()}. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 2 + + As the \l{QGraphicsItem::paint()}{paint()} implementation below draws a + simple drop shadow down and to the right of the item, we return a slightly + adjusted rectangle from \l{QGraphicsItem::boundingRect()}{boundingRect()}. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 3 + + The \l{QGraphicsItem::paint()}{paint()} implementation starts by rendering + a semi transparent black round rectangle drop shadow, two units down and to + the right of the main item. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 4 + + We then draw the "foreground" round rectangle itself. The fill depends on + the \c fill property; if true, we will with a plain QPalette::Window color. + We get the current brush from QApplication::palette(). We assign a single + unit wide pen for the stroke, assign the brush, and then draw the + rectangle. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 5 + + If a pixmap has been assigned to the \e pixmap property, we draw this + pixmap in the center of the rectangle item. The pixmaps are scaled to match + the size of the icons; in arguably a better approach would have been to + store the icons with the right size in the first places. + + \snippet graphicsview/padnavigator/roundrectitem.cpp 6 + + Finally, for completeness we include the \c fill property implementation. + It returns the \c fill member variable's value, and when assigned to, it + calls \l{QGraphicsItem::update()}{update()}. + + As mentioned already, \c RoundRectItem is the base class for \c + FlippablePad, which is the class representing the tilting pad itself. We + will proceed to reviewing \c FlippablePad. + + \section1 FlippablePad Class Definition + + \c FlippablePad is, in addition to its inherited \c RoundRectItem + responsibilities, responsible for creating and managing a grid of icons. + + \snippet graphicsview/padnavigator/flippablepad.h 0 + + Its declaration is very simple: It inherits \c RoundRectItem and does not + need any special polymorphic behavior. It's suitable to declare its own + constructor, and a getter-function that allows \c PadNavigator to access + the icons in the grid by (row, column). + + The example has no "real" behavior or logic of any kind, and because of + that, the icons do not need to provide any \e behavior or special + interactions management. In a real application, however, it would be + natural for the \c FlippablePad and its icons to handle more of the + navigation logic. In this example, we have chosen to leave this to + the \c PadNavigator class, which we will get back to below. + + We will now review the \c FlippablePad implementation. This implementation + starts with two helper functions: \c boundsFromSize() and \c + posForLocation(): + + \snippet graphicsview/padnavigator/flippablepad.cpp 0 + + \c boundsForSize() takes a QSize argument, and returns the bounding + rectangle of the flippable pad item. The QSize determines how many rows and + columns the icon grid should have. Each icon is given 150x150 units of + space, and this determines the bounds. + + \snippet graphicsview/padnavigator/flippablepad.cpp 1 + + \c posForLocation() returns the position of an icon given its row and + column position. Like \c boundsForSize(), the function assumes each icon is + given 150x150 units of space, and that all icons are centered around the + flippable pad item's origin (0, 0). + + \snippet graphicsview/padnavigator/flippablepad.cpp 2 + + The \c FlippablePad constructor passes suitable bounds (using \c + boundsForSize()) and specific color to \c RoundRectItem's constructor. + + \snippet graphicsview/padnavigator/flippablepad.cpp 3 + + It then loads pixmaps from compiled-in resources to use for its icons. + QDirIterator is very useful in this context, as it allows us to fetch all + resource "*.png" files inside the \c :/images directory without explicitly + naming the files. + + We also make sure not to load more pixmaps than we need. + + \snippet graphicsview/padnavigator/flippablepad.cpp 4 + + Now that we have the pixmaps, we can create icons, position then and assign + pixmaps. We start by finding a suitable size and color for the icons, and + initializing a convenient grid structure for storing the icons. This \c + iconGrid is also used later to find the icon for a specific (column, row) + location. + + For each row and column in our grid, we proceed to constructing each icon + as an instance of \c RoundRectItem. The item is placed by using the \c + posForLocation() helper function. To make room for the slip-behind + selection item, we give each icon a \l{QGraphicsItem::zValue()}{Z-value} of + 1. The pixmaps are distributed to the icons in round-robin fasion. + + Again, this approach is only suitable for example purposes. In a real-life + application where each icon represents a specific action, it would be more + natural to assign the pixmaps directly, or that the icons themselves + provide suitable pixmaps. + + \snippet graphicsview/padnavigator/flippablepad.cpp 5 + + Finally, the \c iconAt() function returns a pointer to the icon at a + specific row and column. It makes a somewhat bold assumption that the input + is valid, which is fair because the \c PadNavigator class only calls this + function with correct input. + + We will now review the \c SplashItem class. + + \section1 SplashItem Class Definition + + The \c SplashItem class represents the "splash window", a semitransparent + white overlay with text that appears immediately after the application has + started, and disappears after pressing any key. The animation is controlled + by \c PadNavigator; this class is very simple by itself. + + \snippet graphicsview/padnavigator/splashitem.h 0 + + The class declaration shows that \c SplashItem inherits QGraphicsObject to + allow it to be controlled by QPropertyAnimation. It reimplements the + mandatory \l{QGraphicsItem::paint()}{paint()} and + \l{QGraphicsItem::boundingRect()}{boundingRect()} pure virtual functions, + and keeps a \c text member variable which will contain the information text + displayed on this splash item. + + Let's look at its implementation. + + \snippet graphicsview/padnavigator/splashitem.cpp 0 + + The constructor forwards to QGraphicsObject as expected, assigns a text + message to the \c text member variable, and enables + \l{QGraphicsItem::DeviceCoordinateCache}{DeviceCoordinateCache}. This cache + mode is suitable because the splash item only moves and is never + transformed, and because it contains text, it's important that it has a + pixel perfect visual appearance (in constrast to + \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache}, where the + visual appearance is not as good). + + We use caching to avoid having to relayout and rerender the text for each + frame. An alterative approach would be to use the new QStaticText class. + + \snippet graphicsview/padnavigator/splashitem.cpp 1 + + \c SplashItem's bounding rectangle is fixed at (400x175). + + \snippet graphicsview/padnavigator/splashitem.cpp 2 + + The \l{QGraphicsItem::paint()}{paint()} implementation draws a clipped + round rectangle with a thick 2-unit border and a semi-transparent white + background. It proceeds to finding a suitable text area by adjusting the + splash item's bounding rectangle with 10 units in each side. The text is + rendered inside this rectangle, with top-left alignment, and with word + wrapping enabled. + + The main class now remains. We will proceed to reviewing \c PadNavigator. + + \section1 PadNavigator Class Definition + + \c PadNavigator represents the main window of our Pad Navigator Example + application. It creates and controls a somewhat complex state machine, and + several animations. Its class declaration is very simple: + + \snippet graphicsview/padnavigator/padnavigator.h 0 + + It inherits QGraphicsView and reimplements only one function: + \l{QGraphicsView::resizeEvent()}{resizeEvent()}, to ensure the scene is + scaled to fit inside the view when resizing the main window. + + The \c PadNavigator constructor takes a QSize argument that determines the + number or rows and columns in the grid. + + It also keeps a private member instance, \c form, which is the generated + code for the pad's back side item's QGraphicsProxyWidget-embedded form. + + \snippet graphicsview/padnavigator/padnavigator.cpp 0 + + \c PadNavigator's constructor is a bit long. In short, its job is to create + all items, including the \c FlippablePad, the \c SplashItem and the + QGraphicsProxyWidget \c backItem, and then to set up all animations, states + and transitions that control the behavior of the application. + + It starts out simple, by forwarding to QGraphicsView's constructor. + + \snippet graphicsview/padnavigator/padnavigator.cpp 1 + + The first item to be created is \c SplashItem. This is going to be a top-level + item in the scene, next to \c FlippablePad, and stacked on top of it, so we + assign it a \l{QGraphicsItem::zValue()}{Z-value} of 1. + + \snippet graphicsview/padnavigator/padnavigator.cpp 2 + + Now we construct the \c FlippablePad item, passing its column-row count to + its constructor. + + The pad is controlled by three transformations, and we create one + QGraphicsRotation object for each of these. + + \list + \li \c flipRotation: Rotates the grid around its Qt::YAxis. This rotation is + animated from 0 to 180, and eventually back, when enter is pressed on the + keyboard, flipping the pad around. + \li \c xRotation: Rotates the grid around its Qt::XAxis. This is used to + tilt the pad vertically corresponding to which item is currently selected. + This way, the selected item is always kept in front. + \li \c yRotation: Rotates the grid around its Qt::YAxis. This is used to + tilt the pad horizontally corresponding to which item is selected. This + way, the selected item is always kept in front. + \endlist + + The combination of all three rotations is assigned via + QGraphicsItem::setTransformations(). + + \snippet graphicsview/padnavigator/padnavigator.cpp 3 + + Now we construct the QGraphicsProxyWidget-embedded \c backItem. The proxy + widget is created as a child of the pad. We create a new QWidget and + populate it with the \c form member. To ensure the \c hostName line edit is + the first to receive input focus when this item is shown, we call + \l{QWidget::setFocus()}{setFocus()} immediately. This will not give the + widget focus right away; it will only prepare the item to automatically + receive focus once it is shown. + + The QWidget based form is embedded into the proxy widget. The proxy is + hidden initially; we only want to show it when the pad is rotated at least + 90 degrees, and we also rotate the proxy itself by 180 degrees. This way we + give the impression that the proxy widget is "behind" the flipped pad, when + in fact, it's actually \e{on top of it}. + + We enable \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache} to + ensure the flip animation can run smoothly. + + \snippet graphicsview/padnavigator/padnavigator.cpp 4 + + We now create the selection item. This is simply another instance of \c + RoundRectItem that is slightly larger than the icons on the pad. We create + it as an immediate child of the \c FlippablePad, so the selection item is a + sibling to all the icons. By giving it a + \l{QGraphicsItem::zValue()}{Z-value} of 0.5 we ensure it will slide between + the pad and its icons. + + What follows now is a series of animation initializations. + + \snippet graphicsview/padnavigator/padnavigator.cpp 5 + + We begin with the animations that apply to the splash item. The first + animation, \c smoothSplashMove, ensures that the "y" property of \c splash + will be animated with a 250-millisecond duration + \l{QEasingCurve::InQuad}{InQuad} easing function. \c smoothSplashOpacity + ensures the opacity of \c splash eases in and out in 250 milliseconds. + + The values are assigned by \c PadNavigator's state machine, which is + created later. + + \snippet graphicsview/padnavigator/padnavigator.cpp 6 + + These are the animations that control the selection item's movement and the + \c xRotation and \c yRotation QGraphicsRotation objects that tilt the pad. + All animations have a duration of 125 milliseconds, and they all use the + \l{QEasingCurve::InOutQuad}{InOutQuad} easing function. + + \snippet graphicsview/padnavigator/padnavigator.cpp 7 + + We now create the animations that control the flip-effect when you press + the enter key. The main goal is to rotate the pad by 180 degrees or back. + + \list + \li \c smoothFlipRotation: Animates the main 180 degree rotation of the pad. + \li \c smoothFlipScale: Scales the pad out and then in again while the pad is rotating. + \li \c flipAnimation: A parallel animation group that ensures the above animations are run in parallel. + \endlist + + All animations are given a 500 millisecond duration and an + \l{QEasingCurve::InOutQuad}{InOutQuad} easing function. + + It's worth taking a close look at \c smoothFlipScale. This animation's + start and end values are both 1.0, but at animation step 0.5 the + animation's value is 0.7. This means that after 50% of the animation's + duration, or 250 milliseconds, the pad will be scaled down to 0.7x of its + original size, which gives a great visual effect while flipping. + + \snippet graphicsview/padnavigator/padnavigator.cpp 8 + + This section uses a trick to ensure that certain properties are assigned + precisely when the flip animation passes 50%, or 90 degrees, rotation. In + short, the pad's icons and selection item are all hidden, the pad's \c fill + property is enabled, and \c backItem is shown when flipping over. When + flipping back, the reverse properties are applied. + + The way this is achieved is by running a sequential animation in parallel + to the other animations. This sequence, dubbed \c setVariablesSequence, + starts with a 250 millisecond pause, and then executes several animations + with a duration of 0. Each animation will ensure that properties are set + immediate at this point. + + This approach can also be used to call functions or set any other + properties at a specific time while an animation is running. + + \snippet graphicsview/padnavigator/padnavigator.cpp 9 + + We will now create the state machine. The whole \c PadNavigator state + machinery is controlled by one single state machine that has a + straight-forward state structure. The state engine itself is created + as a child of the \c PadNavigator itself. We then create three top level + states: + + \list + \li \c splashState: The initial state where the splash item is visible. + \li \c frontState: The base state where the splash is gone and we can see + the front side of the pad, and navigate the selection item. + \li \c backState: The flipped state where the \c backItem is visible, and we + can interact with the QGraphicsProxyWidget-embedded form. + \endlist + + \snippet graphicsview/padnavigator/padnavigator.cpp 10 + + Each state assigns specific properties to objects on entry. Most + interesting perhaps is the assignment of the value 0.0 to the pad's \c + flipRotation angle property when in \c frontState, and 180.0 when in \c + backState. + + At the end of this section we register default animations with the state + engine; these animations will apply to their respective objects and + properties for any state transition. Otherwise it's common to assign + animations to specific transitions. + + Specifically, we use default animations to control the selection item's + movement and tilt rotations. The tilt rotations are set to 0 when the pad + is flipped, and restored back to their original values when flipped back. + + The \c splashState state is set as the initial state. This is required + before we start the state engine. We proceed with creating some + transitions. + + \snippet graphicsview/padnavigator/padnavigator.cpp 11 + + QEventTransition defines a very flexible transition type. You can use this + class to trigger a transition based on an object receiving an event of a + specific type. In this case, we would like to transition from \c + splashState into \c frontState if \c PadNavigator receives any key press + event (QEvent::KeyPress). + + We register the \c splashItem's animations to this transition to ensure they + are used to animate the item's movement and opacity. + + \snippet graphicsview/padnavigator/padnavigator.cpp 12 + + We use QKeyEventTransition to capture specific key events. In this case, we + detect that the user presses Qt::Key_Return or Qt::Key_Enter, and use this + to trigger transitions between \c frontState and backState. We register \c + flipAnimation, our complex parallel animation group, with these + transitions. + + We continue by defining the states for each of the icons in the grid. + + \snippet graphicsview/padnavigator/padnavigator.cpp 13 + + We will use state groups to control transitions between icons. Each icon + represents a \e substate of \c frontState. We will then define transitions + between the states by detecting key presses, using QKeyEventTransition. + + We start by creating all the substates, and at the same time we create a + temporary grid structure for the states to make it easier to find which + states represents icons that are up, down, left and to the right each + other. + + Once the first substate is known, we set this up as the initial substate of + \c frontState. We will use the (0, 0), or top-left, icon for the initial + substate. We initialze the selection item's position to be exactly where + the top-left icon is. + + \snippet graphicsview/padnavigator/padnavigator.cpp 14 + + We can now create four transitions for each icon. Each transition ensures + that we move to the state corresponding to which arrow key has been + pressed. It's clear from this techinique that we could design any other + specific transitions to and from each of the sub states depending on these + and other keys. + + \snippet graphicsview/padnavigator/padnavigator.cpp 15 + + Also, for each of the icons, we assign suitable values to the \c xRotation + and \c yRotation objects' "angle"-properties. If you recall, these + properties "tilt" the pad corresponding to which item is currently + selected. We ensure each icon is invisible when the pad is flipped, and + visible when the pad is not flipped. To ensure the visible property is + assigned at the right time, we add property-controlling animations to the + \c setVariableSequence animation defined earlier. + + \snippet graphicsview/padnavigator/padnavigator.cpp 16 + + We are now finished with all states, transitions, and animations. We now + create the scene that will contain all our items. The scene gets a defined + background pixmap, and we disable item indexing (as most items in this + scene are animated). We add our \c pad item to the scene, and use its + bounding rectangle to fixate the scene rectangle. This rectangle is used by + the view to find a suitable size for the application window. + + Then the scene is assigned to the view, or in our case, \c PadNavigator + itself. + + \snippet graphicsview/padnavigator/padnavigator.cpp 17 + + Now that the scene has received its final size, we can position the splash + item at the very top, find its fade-out position, and add it to the scene. + + \snippet graphicsview/padnavigator/padnavigator.cpp 18 + + The view toggles a few necessary properties: + + \list + \li It disables its scroll bars - this application has no use for scroll bars. + \li It assigns a minimum size. This is necessary to avoid numerical errors + in our fit-in-view \c resizeEvent() implementation. + \li It sets \l{QGraphicsView::FullViewportUpdate}{FullViewportUpdate}, to + ensure QGraphicsView doesn't spend time figuring out precisely what needs + to be redrawn. This application is very simple - if anything changes, + everything is updated. + \li It enables background caching - this makes no performance difference + with OpenGL, but without OpenGL it avoids unnecessary re-scaling of the + background pixmap. + \li It sets render hints that increase rendering quality. + \li If OpenGL is supported, a QOpenGLWidget viewport is assigned to the view. + \endlist + + Finally, we start the state engine. + + \snippet graphicsview/padnavigator/padnavigator.cpp 19 + + The \l{QGraphicsView::resizeEvent()}{resizeEvent()} implementation calls + the base implementation, and then calls QGraphicsView::fitInView() to scale + the scene so that it fits perfectly inside the view. + + By resizing the main application window, you can see this effect yourself. + The scene contents grow when you make the window larger, and shrink when + you make it smaller, while keeping the aspect ratio intact. + + \section1 The main() Function + + \snippet graphicsview/padnavigator/main.cpp 0 + + The \c main function creates the QApplication instance, uses + Q_INIT_RESOURCE to ensure our compiled-in resources aren't removed by the + linker, and then creates a 3x3 \c PadNavigator instance and shows it. + + Our flippable pad shows up with a suitable splash item once control returns + to the event loop. + + \section1 Performance Notes + + The example uses OpenGL if this is available, to achieve optimal + performance; otherwise perspective tranformations can be quite costly. + + Although this example does use QGraphicsProxyWidget to demonstrate + integration of Qt widget components integrated into Graphics View, using + QGraphicsProxyWidget comes with a performance penalty, and is therefore not + recommended for embedded development. + + This example uses extensive item caching to avoid rerendering of static + elements, at the expense of graphics memory. +*/ diff --git a/examples/widgets/doc/src/pingpong.qdoc b/examples/widgets/doc/src/pingpong.qdoc new file mode 100644 index 0000000..9545058 --- /dev/null +++ b/examples/widgets/doc/src/pingpong.qdoc @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/pingpong + \title Ping Pong States Example + + \brief The Ping Pong States example shows how to use parallel states together + with custom events and transitions in \l{The State Machine Framework}. + + This example implements a statechart where two states communicate by + posting events to the state machine. The state chart looks as follows: + + \image pingpong-example.png + \omit + \caption This is a caption + \endomit + + The \c pinger and \c ponger states are parallel states, i.e. they are + entered simultaneously and will take transitions independently of + eachother. + + The \c pinger state will post the first \c ping event upon entry; the \c + ponger state will respond by posting a \c pong event; this will cause the + \c pinger state to post a new \c ping event; and so on. + + \snippet statemachine/pingpong/main.cpp 0 + + Two custom events are defined, \c PingEvent and \c PongEvent. + + \snippet statemachine/pingpong/main.cpp 1 + + The \c Pinger class defines a state that posts a \c PingEvent to the state + machine when the state is entered. + + \snippet statemachine/pingpong/main.cpp 2 + + The \c PingTransition class defines a transition that is triggered by + events of type \c PingEvent, and that posts a \c PongEvent (with a delay + of 500 milliseconds) to the state machine when the transition is + triggered. + + \snippet statemachine/pingpong/main.cpp 3 + + The \c PongTransition class defines a transition that is triggered by + events of type \c PongEvent, and that posts a \c PingEvent (with a delay + of 500 milliseconds) to the state machine when the transition is + triggered. + + \snippet statemachine/pingpong/main.cpp 4 + + The main() function begins by creating a state machine and a parallel + state group. + + \snippet statemachine/pingpong/main.cpp 5 + + Next, the \c pinger and \c ponger states are created, with the parallel + state group as their parent state. Note that the transitions are \e + targetless. When such a transition is triggered, the source state won't be + exited and re-entered; only the transition's onTransition() function will + be called, and the state machine's configuration will remain the same, + which is precisely what we want in this case. + + \snippet statemachine/pingpong/main.cpp 6 + + Finally, the group is added to the state machine, the machine is started, + and the application event loop is entered. + + */ diff --git a/examples/widgets/doc/src/rogue.qdoc b/examples/widgets/doc/src/rogue.qdoc new file mode 100644 index 0000000..b8b7cb1 --- /dev/null +++ b/examples/widgets/doc/src/rogue.qdoc @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/rogue + \title Rogue Example + + \brief The Rogue example shows how to use the Qt state machine for event + handling. + + \image rogue-example.png + + This example implements a simple text based game. Do you see the + \c{@} in the screenshot? That's you, the rogue. The \c{#} + characters are walls, and the dots represent floor. In a real + game, other ASCII characters would represent all kinds of objects + and creatures, for instance, ancient dragons (\c{D}s) or food + rations (\c{%}s). But let's not get carried away. In this game, + the rogue is simply running around in an empty room. + + The rogue is moved with the keypad (2, 4, 8, 6). That aside, we + have implemented a \c quit command that triggers if the player + types \c {q}. The player is then asked if he/she really wants to + quit. + + Most games have commands that need more than one key press (we + think of consecutive presses, i.e., not of several keys being + pressed at the same time). In this game, only the \c quit command + falls under this category, but for the sake of argument, let's + imagine a fully-fledged game with a rich set of commands. If we + were to implement these by catching key events in + \l{QWidget::}{keyPressEvent()}, we would have to keep a lot of + class member variables to track the sequence of keys already typed + (or find some other way of deducing the current state of a + command). This can easily lead to spaghetti, which is--as we all + well know, I'm sure--unpleasant. With a state machine, on the + other hand, separate states can wait for a single key press, and + that makes our lives a lot simpler. + + The example consists of two classes: + + \list + \li \c Window draws the text display of the game and sets + up the state machine. The window also has a status bar + above the area in which the rouge moves. + \li \c MovementTransition is a transition that carries out + a single move of the rogue. + \endlist + + Before we embark on a code walkthrough, it is necessary to take a + closer look at the design of the machine. Here is a state chart + that shows what we want to achieve: + + \image rogue-statechart.png + + The input state waits for a key press to start a new command. + When receiving a key it recognizes, it transitions to one of the + two commands of the game; though, as we will see, movement is + handled by the transition itself. The quit state waits for the + player to answer yes or no (by typing \c y or \c n) when asked + whether he/she really wants to quit the game. + + The chart demonstrates how we use one state to wait for a single + key press. The press received may trigger one of the transitions + connected to the state. + + \section1 Window Class Definition + + The \c Window class is a widget that draws the text display of the + game. It also sets up the state machine, i.e., creates and + connects the states in the machine. It is the key events from this + widget that are used by the machine. + + \snippet statemachine/rogue/window.h 0 + + \c Direction specifies the direction in which the rogue is to + move. We use this in \c movePlayer(), which moves the rogue and + repaints the window. The game has a status line above the area in + which the rogue moves. The \c status property contains the text of + this line. We use a property because the QState class allows + setting any Qt \l{Qt's Property System}{property} when entered. + More on this later. + + \snippet statemachine/rogue/window.h 1 + + The \c map is an array with the characters that are currently + displayed. We set up the array in \c setupMap(), and update it + when the rogue is moved. \c pX and \c pY is the current position + of the rogue. \c WIDTH and \c HEIGHT are macros specifying the + dimensions of the map. + + The \c paintEvent() function is left out of this walkthrough. We + also do not discuss other code that does not concern the state + machine (the \c setupMap(), \c status(), \c setStatus(), \c + movePlayer(), and \c sizeHint() functions). If you wish to take a + look at the code, click on the link for the \c window.cpp file at + the top of this page. + + \section1 Window Class Implementation + + Here is the constructor of \c Window: + + \snippet statemachine/rogue/window.cpp 0 + \dots + \snippet statemachine/rogue/window.cpp 1 + + The player starts off at position (5, 5). We then set up the map + and statemachine. Let's proceed with the \c buildMachine() + function: + + \snippet statemachine/rogue/window.cpp 2 + + We enter \c inputState when the machine is started and from the \c + quitState if the user wants to continue playing. We then set the + status to a helpful reminder of how to play the game. + + First, the \c Movement transition is added to the input state. + This will enable the rogue to be moved with the keypad. Notice + that we don't set a target state for the movement transition. This + will cause the transition to be triggered (and the + \l{QAbstractTransition::}{onTransition()} function to be invoked), + but the machine will not leave the \c inputState. If we had set \c + inputState as the target state, we would first have left and then + entered the \c inputState again. + + \snippet statemachine/rogue/window.cpp 3 + + When we enter \c quitState, we update the status bar of the + window. + + \c QKeyEventTransition is a utility class that removes the hassle + of implementing transitions for \l{QKeyEvent}s. We simply need to + specify the key on which the transition should trigger and the + target state of the transition. + + \snippet statemachine/rogue/window.cpp 4 + + The transition from \c inputState allows triggering the quit state + when the player types \c {q}. + + \snippet statemachine/rogue/window.cpp 5 + + The machine is set up, so it's time to start it. + + \section1 The MovementTransition Class + + \c MovementTransition is triggered when the player request the + rogue to be moved (by typing 2, 4, 6, or 8) when the machine is in + the \c inputState. + + \snippet statemachine/rogue/movementtransition.h 0 + + In the constructor, we tell QEventTransition to only send + \l{QEvent::}{KeyPress} events to the + \l{QAbstractTransition::}{eventTest()} function: + + \snippet statemachine/rogue/movementtransition.h 1 + + The KeyPress events come wrapped in \l{QStateMachine::WrappedEvent}s. \c event + must be confirmed to be a wrapped event because Qt uses other + events internally. After that, it is simply a matter of checking + which key has been pressed. + + Let's move on to the \c onTransition() function: + + \snippet statemachine/rogue/movementtransition.h 2 + + When \c onTransition() is invoked, we know that we have a + \l{QEvent::}{KeyPress} event with 2, 4, 6, or 8, and can ask \c + Window to move the player. + + \section1 The Roguelike Tradition + + You might have been wondering why the game features a rogue. Well, + these kinds of text based dungeon exploration games date back to a + game called, yes, "Rogue". Although outflanked by the technology + of modern 3D computer games, roguelikes have a solid community of + hard-core, devoted followers. + + Playing these games can be surprisingly addictive (despite the + lack of graphics). Angband, the perhaps most well-known rougelike, + is found here: \l{http://rephial.org/}. +*/ + diff --git a/examples/widgets/doc/src/states.qdoc b/examples/widgets/doc/src/states.qdoc new file mode 100644 index 0000000..1ae379f --- /dev/null +++ b/examples/widgets/doc/src/states.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example animation/states + \title States Example + + \brief The States example shows how to use the Qt state machine to play + animations. + + \image states-example.png +*/ diff --git a/examples/widgets/doc/src/stickman.qdoc b/examples/widgets/doc/src/stickman.qdoc new file mode 100644 index 0000000..ffc7366 --- /dev/null +++ b/examples/widgets/doc/src/stickman.qdoc @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example animation/stickman + \title Stickman Example + + \brief The Stickman example shows how to animate transitions in a state + machine to implement key frame animations. + + \image stickman-example.png + + In this example, we will write a small application which animates the joints in a skeleton and + projects a stickman figure on top. The stickman can be either "alive" or "dead", and when in the + "alive" state, he can be performing different actions defined by key frame animations. + + Animations are implemented as composite states. Each child state of the animation state + represents a frame in the animation by setting the position of each joint in the stickman's + skeleton to the positions defined for the particular frame. The frames are then bound together + with animated transitions that trigger on the source state's propertiesAssigned() signal. Thus, + the machine will enter the state representing the next frame in the animation immediately after + it has finished animating into the previous frame. + + \image stickman-example1.png + + The states for an animation is constructed by reading a custom animation file format and + creating states that assign values to the "position" properties of each of the nodes in the + skeleton graph. + + \snippet animation/stickman/lifecycle.cpp 1 + + The states are then bound together with signal transitions that listen to the + propertiesAssigned() signal. + + \snippet animation/stickman/lifecycle.cpp 2 + + The last frame state is given a transition to the first one, so that the animation will loop + until it is interrupted when a transition out from the animation state is taken. To get smooth + animations between the different key frames, we set a default animation on the state machine. + This is a parallel animation group which contains animations for all the "position" properties + and will be selected by default when taking any transition that leads into a state that assigns + values to these properties. + + \snippet animation/stickman/lifecycle.cpp 3 + + Several such animation states are constructed, and are placed together as children of a top + level "alive" state which represents the stickman life cycle. Transitions go from the parent + state to the child state to ensure that each of the child states inherit them. + + \image stickman-example2.png + + This saves us the effort of connect every state to every state with identical transitions. The + state machine makes sure that transitions between the key frame animations are also smooth by + applying the default animation when interrupting one and starting another. + + Finally, there is a transition out from the "alive" state and into the "dead" state. This is + a custom transition type called LightningSrikesTransition which samples every second and + triggers at random (one out of fifty times on average.) + + \snippet animation/stickman/lifecycle.cpp 4 + + When it triggers, the machine will first enter a "lightningBlink" state which uses a timer to + pause for a brief period of time while the background color of the scene is white. This gives us + a flash effect when the lightning strikes. + + \snippet animation/stickman/lifecycle.cpp 5 + + We start and stop a QTimer object when entering and exiting the state. Then we transition into + the "dead" state when the timer times out. + + \snippet animation/stickman/lifecycle.cpp 0 + + When the machine is in the "dead" state, it will be unresponsive. This is because the "dead" + state has no transitions leading out. + + \image stickman-example3.png + +*/ diff --git a/examples/widgets/doc/src/sub-attaq.qdoc b/examples/widgets/doc/src/sub-attaq.qdoc new file mode 100644 index 0000000..994e9d6 --- /dev/null +++ b/examples/widgets/doc/src/sub-attaq.qdoc @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example animation/sub-attaq + \title Sub-Attaq + \ingroup examples-layout + + \brief This example shows Qt's ability to combine \l{The Animation Framework}{the animation framework} + and \l{The State Machine Framework}{the state machine framework} to create a game. + + \image sub-attaq-demo.png + + The purpose of the game is to destroy all submarines to win the current level. + The boat can be controlled using left and right keys. To fire a bomb you can press + up and down keys. +*/ diff --git a/examples/widgets/doc/src/trafficlight.qdoc b/examples/widgets/doc/src/trafficlight.qdoc new file mode 100644 index 0000000..50c0944 --- /dev/null +++ b/examples/widgets/doc/src/trafficlight.qdoc @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/trafficlight + \title Traffic Light Example + + \brief The Traffic Light example shows how to use \l{The State Machine Framework} + to implement the control flow of a traffic light. + + \image trafficlight-example.png + + In this example we write a TrafficLightWidget class. The traffic light has + three lights: Red, yellow and green. The traffic light transitions from + one light to another (red to yellow to green to yellow to red again) at + certain intervals. + + \snippet statemachine/trafficlight/main.cpp 0 + + The LightWidget class represents a single light of the traffic light. It + provides an \c on property and two slots, turnOn() and turnOff(), to turn + the light on and off, respectively. The widget paints itself in the color + that's passed to the constructor. + + \snippet statemachine/trafficlight/main.cpp 1 + + The TrafficLightWidget class represents the visual part of the traffic + light; it's a widget that contains three lights arranged vertically, and + provides accessor functions for these. + + \snippet statemachine/trafficlight/main.cpp 2 + + The createLightState() function creates a state that turns a light on when + the state is entered, and off when the state is exited. The state uses a + timer, and as we shall see the timeout is used to transition from one + LightState to another. Here is the statechart for the light state: + + \image trafficlight-example1.png + \omit + \caption This is a caption + \endomit + + \snippet statemachine/trafficlight/main.cpp 3 + + The TrafficLight class combines the TrafficLightWidget with a state + machine. The state graph has four states: red-to-yellow, yellow-to-green, + green-to-yellow and yellow-to-red. The initial state is red-to-yellow; + when the state's timer times out, the state machine transitions to + yellow-to-green. The same process repeats through the other states. + This is what the statechart looks like: + + \image trafficlight-example2.png + \omit + \caption This is a caption + \endomit + + \snippet statemachine/trafficlight/main.cpp 4 + + The main() function constructs a TrafficLight and shows it. + +*/ diff --git a/examples/widgets/doc/src/twowaybutton.qdoc b/examples/widgets/doc/src/twowaybutton.qdoc new file mode 100644 index 0000000..2e1c291 --- /dev/null +++ b/examples/widgets/doc/src/twowaybutton.qdoc @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example statemachine/twowaybutton + \title Two-way Button Example + + \brief The Two-way button example shows how to use \l{The State Machine + Framework} to implement a simple state machine that toggles the current + state when a button is clicked. + + \snippet statemachine/twowaybutton/main.cpp 0 + + The application's main() function begins by constructing the application + object, a button and a state machine. + + \snippet statemachine/twowaybutton/main.cpp 1 + + The state machine has two states; \c on and \c off. When either state is + entered, the text of the button will be set accordingly. + + \snippet statemachine/twowaybutton/main.cpp 2 + + When the state machine is in the \c off state and the button is clicked, + it will transition to the \c on state; when the state machine is in the \c + on state and the button is clicked, it will transition to the \c off + state. + + \snippet statemachine/twowaybutton/main.cpp 3 + + The states are added to the state machine; they become top-level (sibling) + states. + + \snippet statemachine/twowaybutton/main.cpp 4 + + The initial state is \c off; this is the state the state machine will + immediately transition to once the state machine is started. + + \snippet statemachine/twowaybutton/main.cpp 5 + + Finally, the button is resized and made visible, and the application event + loop is entered. + +*/ diff --git a/examples/widgets/graphicsview/CMakeLists.txt b/examples/widgets/graphicsview/CMakeLists.txt new file mode 100644 index 0000000..8408c3f --- /dev/null +++ b/examples/widgets/graphicsview/CMakeLists.txt @@ -0,0 +1,3 @@ +# Generated from graphicsview.pro. + +add_subdirectory(padnavigator) diff --git a/examples/widgets/graphicsview/README b/examples/widgets/graphicsview/README new file mode 100644 index 0000000..e710fc3 --- /dev/null +++ b/examples/widgets/graphicsview/README @@ -0,0 +1,9 @@ +Qt is provided with a comprehensive canvas through the GraphicsView +classes. + +These examples demonstrate the fundamental aspects of canvas programming +with Qt. + + +Documentation for these examples can be found via the Examples +link in the main Qt documentation. diff --git a/examples/widgets/graphicsview/graphicsview.pro b/examples/widgets/graphicsview/graphicsview.pro new file mode 100644 index 0000000..c1dd04c --- /dev/null +++ b/examples/widgets/graphicsview/graphicsview.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = padnavigator diff --git a/examples/widgets/graphicsview/padnavigator/.prev_CMakeLists.txt b/examples/widgets/graphicsview/padnavigator/.prev_CMakeLists.txt new file mode 100644 index 0000000..514b893 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/.prev_CMakeLists.txt @@ -0,0 +1,69 @@ +# Generated from padnavigator.pro. + +cmake_minimum_required(VERSION 3.14) +project(padnavigator LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/padnavigator") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_executable(padnavigator + flippablepad.cpp flippablepad.h + form.ui + main.cpp + padnavigator.cpp padnavigator.h + roundrectitem.cpp roundrectitem.h + splashitem.cpp splashitem.h +) +target_link_libraries(padnavigator PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set(padnavigator_resource_files + "images/artsfftscope.png" + "images/blue_angle_swirl.jpg" + "images/kontact_contacts.png" + "images/kontact_journal.png" + "images/kontact_mail.png" + "images/kontact_notes.png" + "images/kopeteavailable.png" + "images/metacontact_online.png" + "images/minitools.png" +) + +qt6_add_resources(padnavigator "padnavigator" + PREFIX + "/" + FILES + ${padnavigator_resource_files} +) + +if(TARGET Qt::OpenGL) + target_link_libraries(padnavigator PUBLIC + Qt::OpenGL + Qt::OpenGLWidgets + ) +endif() + +install(TARGETS padnavigator + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/graphicsview/padnavigator/CMakeLists.txt b/examples/widgets/graphicsview/padnavigator/CMakeLists.txt new file mode 100644 index 0000000..b024350 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/CMakeLists.txt @@ -0,0 +1,70 @@ +# Generated from padnavigator.pro. + +cmake_minimum_required(VERSION 3.14) +project(padnavigator LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/padnavigator") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) +find_package(Qt6 COMPONENTS OpenGL) # special case + +add_executable(padnavigator + flippablepad.cpp flippablepad.h + form.ui + main.cpp + padnavigator.cpp padnavigator.h + roundrectitem.cpp roundrectitem.h + splashitem.cpp splashitem.h +) +target_link_libraries(padnavigator PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + + +# Resources: +set(padnavigator_resource_files + "images/artsfftscope.png" + "images/blue_angle_swirl.jpg" + "images/kontact_contacts.png" + "images/kontact_journal.png" + "images/kontact_mail.png" + "images/kontact_notes.png" + "images/kopeteavailable.png" + "images/metacontact_online.png" + "images/minitools.png" +) + +qt6_add_resources(padnavigator "padnavigator" + PREFIX + "/" + FILES + ${padnavigator_resource_files} +) + +if(TARGET Qt::OpenGL) + target_link_libraries(padnavigator PUBLIC + Qt::OpenGL + Qt::OpenGLWidgets + ) +endif() + +install(TARGETS padnavigator + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/graphicsview/padnavigator/flippablepad.cpp b/examples/widgets/graphicsview/padnavigator/flippablepad.cpp new file mode 100644 index 0000000..2639092 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/flippablepad.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 <QDirIterator> + +//! [0] +static QRectF boundsFromSize(const QSize &size) +{ + return QRectF((-size.width() / 2.0) * 150, (-size.height() / 2.0) * 150, + size.width() * 150, size.height() * 150); +} +//! [0] + +//! [1] +static QPointF posForLocation(int column, int row, const QSize &size) +{ + return QPointF(column * 150, row * 150) + - QPointF((size.width() - 1) * 75, (size.height() - 1) * 75); +} +//! [1] + +//! [2] +FlippablePad::FlippablePad(const QSize &size, QGraphicsItem *parent) + : RoundRectItem(boundsFromSize(size), QColor(226, 255, 92, 64), parent) +{ +//! [2] +//! [3] + int numIcons = size.width() * size.height(); + QList<QPixmap> pixmaps; + QDirIterator it(":/images", {"*.png"}); + while (it.hasNext() && pixmaps.size() < numIcons) + pixmaps << it.next(); +//! [3] + +//! [4] + const QRectF iconRect(-54, -54, 108, 108); + const QColor iconColor(214, 240, 110, 128); + iconGrid.resize(size.height()); + int n = 0; + + for (int y = 0; y < size.height(); ++y) { + iconGrid[y].resize(size.width()); + for (int x = 0; x < size.width(); ++x) { + RoundRectItem *rect = new RoundRectItem(iconRect, iconColor, this); + rect->setZValue(1); + rect->setPos(posForLocation(x, y, size)); + rect->setPixmap(pixmaps.at(n++ % pixmaps.size())); + iconGrid[y][x] = rect; + } + } +} +//! [4] + +//! [5] +RoundRectItem *FlippablePad::iconAt(int column, int row) const +{ + return iconGrid[row][column]; +} +//! [5] diff --git a/examples/widgets/graphicsview/padnavigator/flippablepad.h b/examples/widgets/graphicsview/padnavigator/flippablepad.h new file mode 100644 index 0000000..a056eae --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/flippablepad.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef FLIPPABLEPAD_H +#define FLIPPABLEPAD_H + +#include "roundrectitem.h" + +#include <QList> + +//! [0] +class FlippablePad : public RoundRectItem +{ +public: + explicit FlippablePad(const QSize &size, QGraphicsItem *parent = nullptr); + + RoundRectItem *iconAt(int column, int row) const; + +private: + QList<QList<RoundRectItem *>> iconGrid; +}; +//! [0] + +#endif // FLIPPABLEPAD_H diff --git a/examples/widgets/graphicsview/padnavigator/form.ui b/examples/widgets/graphicsview/padnavigator/form.ui new file mode 100644 index 0000000..fc7d123 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/form.ui @@ -0,0 +1,208 @@ +<ui version="4.0" > + <class>Form</class> + <widget class="QWidget" name="Form" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>378</width> + <height>385</height> + </rect> + </property> + <property name="windowTitle" > + <string>BackSide</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QGroupBox" name="groupBox" > + <property name="title" > + <string>Settings</string> + </property> + <property name="flat" > + <bool>true</bool> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Title:</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QLineEdit" name="hostName" > + <property name="text" > + <string>Pad Navigator Example</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Modified:</string> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Extent</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QSlider" name="horizontalSlider" > + <property name="value" > + <number>42</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox" > + <property name="value" > + <number>42</number> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="1" > + <widget class="QDateTimeEdit" name="dateTimeEdit" /> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Other input</string> + </property> + <property name="flat" > + <bool>true</bool> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <widget class="QTreeWidget" name="treeWidget" > + <column> + <property name="text" > + <string>Widgets On Graphics View</string> + </property> + </column> + <item> + <property name="text" > + <string>QGraphicsProxyWidget</string> + </property> + <item> + <property name="text" > + <string>QGraphicsWidget</string> + </property> + <item> + <property name="text" > + <string>QObject</string> + </property> + </item> + <item> + <property name="text" > + <string>QGraphicsItem</string> + </property> + </item> + <item> + <property name="text" > + <string>QGraphicsLayoutItem</string> + </property> + </item> + </item> + </item> + <item> + <property name="text" > + <string>QGraphicsGridLayout</string> + </property> + <item> + <property name="text" > + <string>QGraphicsLayout</string> + </property> + <item> + <property name="text" > + <string>QGraphicsLayoutItem</string> + </property> + </item> + </item> + </item> + <item> + <property name="text" > + <string>QGraphicsLinearLayout</string> + </property> + <item> + <property name="text" > + <string>QGraphicsLayout</string> + </property> + <item> + <property name="text" > + <string>QGraphicsLayoutItem</string> + </property> + </item> + </item> + </item> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>groupBox</tabstop> + <tabstop>hostName</tabstop> + <tabstop>dateTimeEdit</tabstop> + <tabstop>horizontalSlider</tabstop> + <tabstop>spinBox</tabstop> + <tabstop>groupBox_2</tabstop> + <tabstop>treeWidget</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>horizontalSlider</sender> + <signal>valueChanged(int)</signal> + <receiver>spinBox</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>184</x> + <y>125</y> + </hint> + <hint type="destinationlabel" > + <x>275</x> + <y>127</y> + </hint> + </hints> + </connection> + <connection> + <sender>spinBox</sender> + <signal>valueChanged(int)</signal> + <receiver>horizontalSlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>272</x> + <y>114</y> + </hint> + <hint type="destinationlabel" > + <x>190</x> + <y>126</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/widgets/graphicsview/padnavigator/images/artsfftscope.png b/examples/widgets/graphicsview/padnavigator/images/artsfftscope.png Binary files differnew file mode 100644 index 0000000..4db003f --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/artsfftscope.png diff --git a/examples/widgets/graphicsview/padnavigator/images/blue_angle_swirl.jpg b/examples/widgets/graphicsview/padnavigator/images/blue_angle_swirl.jpg Binary files differnew file mode 100644 index 0000000..5bf0deb --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/blue_angle_swirl.jpg diff --git a/examples/widgets/graphicsview/padnavigator/images/kontact_contacts.png b/examples/widgets/graphicsview/padnavigator/images/kontact_contacts.png Binary files differnew file mode 100644 index 0000000..6fb4cc8 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/kontact_contacts.png diff --git a/examples/widgets/graphicsview/padnavigator/images/kontact_journal.png b/examples/widgets/graphicsview/padnavigator/images/kontact_journal.png Binary files differnew file mode 100644 index 0000000..b1fedb6 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/kontact_journal.png diff --git a/examples/widgets/graphicsview/padnavigator/images/kontact_mail.png b/examples/widgets/graphicsview/padnavigator/images/kontact_mail.png Binary files differnew file mode 100644 index 0000000..672f8fa --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/kontact_mail.png diff --git a/examples/widgets/graphicsview/padnavigator/images/kontact_notes.png b/examples/widgets/graphicsview/padnavigator/images/kontact_notes.png Binary files differnew file mode 100644 index 0000000..229bf73 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/kontact_notes.png diff --git a/examples/widgets/graphicsview/padnavigator/images/kopeteavailable.png b/examples/widgets/graphicsview/padnavigator/images/kopeteavailable.png Binary files differnew file mode 100644 index 0000000..2eaf41a --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/kopeteavailable.png diff --git a/examples/widgets/graphicsview/padnavigator/images/metacontact_online.png b/examples/widgets/graphicsview/padnavigator/images/metacontact_online.png Binary files differnew file mode 100644 index 0000000..6a398dd --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/metacontact_online.png diff --git a/examples/widgets/graphicsview/padnavigator/images/minitools.png b/examples/widgets/graphicsview/padnavigator/images/minitools.png Binary files differnew file mode 100644 index 0000000..0248c9d --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/images/minitools.png diff --git a/examples/widgets/graphicsview/padnavigator/main.cpp b/examples/widgets/graphicsview/padnavigator/main.cpp new file mode 100644 index 0000000..c433ab3 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/main.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 "padnavigator.h" + +#include <QtWidgets/QtWidgets> + +//! [0] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(padnavigator); + + PadNavigator navigator(QSize(3, 3)); + navigator.show(); + return app.exec(); +} +//! [0] diff --git a/examples/widgets/graphicsview/padnavigator/padnavigator.cpp b/examples/widgets/graphicsview/padnavigator/padnavigator.cpp new file mode 100644 index 0000000..5088386 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/padnavigator.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** 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" + +#include <QEventTransition> +#include <QGraphicsProxyWidget> +#include <QGraphicsRotation> +#include <QHistoryState> +#include <QKeyEventTransition> +#include <QParallelAnimationGroup> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QStateMachine> + +#ifndef QT_NO_OPENGL +#include <QOpenGLWidget> +#endif + +//! [0] +PadNavigator::PadNavigator(const QSize &size, QWidget *parent) + : QGraphicsView(parent) +{ +//! [0] +//! [1] + // Splash item + SplashItem *splash = new SplashItem; + splash->setZValue(1); +//! [1] + +//! [2] + // Pad item + 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); +//! [2] + +//! [3] + // Back (proxy widget) item + 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)); +//! [3] + +//! [4] + // Selection item + RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray, pad); + selectionItem->setZValue(0.5); +//! [4] + +//! [5] + // Splash animations + QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y"); + QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity"); + smoothSplashMove->setEasingCurve(QEasingCurve::InQuad); + smoothSplashMove->setDuration(250); + smoothSplashOpacity->setDuration(250); +//! [5] + +//! [6] + // Selection animation + 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); +//! [6] + +//! [7] + // Flip animation setup + QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle"); + QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale"); + QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this); + smoothFlipScale->setDuration(500); + smoothFlipRotation->setDuration(500); + smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad); + smoothFlipRotation->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); +//! [7] + +//! [8] + // Flip animation delayed property assignment + 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); +//! [8] + +//! [9] + // Build the state machine + 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); +//! [9] +//! [10] + 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); +//! [10] + +//! [11] + // Transitions + QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState); + anyKeyTransition->setTargetState(frontState); + anyKeyTransition->addAnimation(smoothSplashMove); + anyKeyTransition->addAnimation(smoothSplashOpacity); +//! [11] + +//! [12] + 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); +//! [12] + +//! [13] + // Create substates for each icon; store in temporary grid. + int columns = size.width(); + int rows = size.height(); + QList<QList<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()); +//! [13] + +//! [14] + // 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]); +//! [14] +//! [15] + 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); + } + } +//! [15] + +//! [16] + // 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); +//! [16] + +//! [17] + // Adjust splash item to scene contents + 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); +//! [17] + +//! [18] + // 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(); +//! [18] +} + +//! [19] +void PadNavigator::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); +} +//! [19] diff --git a/examples/widgets/graphicsview/padnavigator/padnavigator.h b/examples/widgets/graphicsview/padnavigator/padnavigator.h new file mode 100644 index 0000000..0fe9ad0 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/padnavigator.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef PADNAVIGATOR_H +#define PADNAVIGATOR_H + +#include <QGraphicsView> +#include "ui_form.h" + +//! [0] +class PadNavigator : public QGraphicsView +{ + Q_OBJECT +public: + explicit PadNavigator(const QSize &size, QWidget *parent = nullptr); + +protected: + void resizeEvent(QResizeEvent *event) override; + +private: + Ui::Form form; +}; +//! [0] + +#endif // PADNAVIGATOR_H diff --git a/examples/widgets/graphicsview/padnavigator/padnavigator.pro b/examples/widgets/graphicsview/padnavigator/padnavigator.pro new file mode 100644 index 0000000..dd7fac7 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/padnavigator.pro @@ -0,0 +1,27 @@ +SOURCES += main.cpp \ + roundrectitem.cpp \ + flippablepad.cpp \ + padnavigator.cpp \ + splashitem.cpp + +HEADERS += \ + roundrectitem.h \ + flippablepad.h \ + padnavigator.h \ + splashitem.h + +RESOURCES += \ + padnavigator.qrc + +FORMS += \ + form.ui + +QT += statemachine widgets +requires(qtConfig(treewidget)) +qtHaveModule(opengl): QT += opengl openglwidgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/padnavigator +INSTALLS += target + +CONFIG += console diff --git a/examples/widgets/graphicsview/padnavigator/padnavigator.qrc b/examples/widgets/graphicsview/padnavigator/padnavigator.qrc new file mode 100644 index 0000000..b26ab92 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/padnavigator.qrc @@ -0,0 +1,13 @@ +<RCC> + <qresource> + <file>images/blue_angle_swirl.jpg</file> + <file>images/artsfftscope.png</file> + <file>images/kontact_contacts.png</file> + <file>images/kontact_journal.png</file> + <file>images/kontact_mail.png</file> + <file>images/kontact_notes.png</file> + <file>images/kopeteavailable.png</file> + <file>images/metacontact_online.png</file> + <file>images/minitools.png</file> + </qresource> +</RCC> diff --git a/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp b/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp new file mode 100644 index 0000000..b4ea489 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** 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 "roundrectitem.h" + +#include <QGuiApplication> +#include <QPainter> +#include <QPalette> + +//! [0] +RoundRectItem::RoundRectItem(const QRectF &bounds, const QColor &color, + QGraphicsItem *parent) + : QGraphicsObject(parent), fillRect(false), bounds(bounds) +{ + gradient.setStart(bounds.topLeft()); + gradient.setFinalStop(bounds.bottomRight()); + gradient.setColorAt(0, color); + gradient.setColorAt(1, color.darker(200)); + setCacheMode(ItemCoordinateCache); +} +//! [0] + +//! [1] +QPixmap RoundRectItem::pixmap() const +{ + return pix; +} +void RoundRectItem::setPixmap(const QPixmap &pixmap) +{ + pix = pixmap; + update(); +} +//! [1] + +//! [2] +QRectF RoundRectItem::boundingRect() const +{ + return bounds.adjusted(0, 0, 2, 2); +} +//! [2] + +//! [3] +void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + painter->drawRoundedRect(bounds.translated(2, 2), 25, 25, Qt::RelativeSize); +//! [3] +//! [4] + if (fillRect) + painter->setBrush(QGuiApplication::palette().brush(QPalette::Window)); + else + painter->setBrush(gradient); + painter->setPen(QPen(Qt::black, 1)); + painter->drawRoundedRect(bounds, 25,25, Qt::RelativeSize); +//! [4] +//! [5] + if (!pix.isNull()) { + painter->scale(1.95, 1.95); + painter->drawPixmap(-pix.width() / 2, -pix.height() / 2, pix); + } +} +//! [5] + +//! [6] +bool RoundRectItem::fill() const +{ + return fillRect; +} +void RoundRectItem::setFill(bool fill) +{ + fillRect = fill; + update(); +} +//! [6] diff --git a/examples/widgets/graphicsview/padnavigator/roundrectitem.h b/examples/widgets/graphicsview/padnavigator/roundrectitem.h new file mode 100644 index 0000000..91b3e65 --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/roundrectitem.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef ROUNDRECTITEM_H +#define ROUNDRECTITEM_H + +#include <QGraphicsObject> +#include <QLinearGradient> + +//! [0] +class RoundRectItem : public QGraphicsObject +{ + Q_OBJECT + Q_PROPERTY(bool fill READ fill WRITE setFill) +public: + RoundRectItem(const QRectF &bounds, const QColor &color, + QGraphicsItem *parent = nullptr); + + QPixmap pixmap() const; + void setPixmap(const QPixmap &pixmap); + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + + bool fill() const; + void setFill(bool fill); +//! [0] + +//! [1] +private: + QPixmap pix; + bool fillRect; + QRectF bounds; + QLinearGradient gradient; +}; +//! [1] + +#endif // ROUNDRECTITEM_H diff --git a/examples/widgets/graphicsview/padnavigator/splashitem.cpp b/examples/widgets/graphicsview/padnavigator/splashitem.cpp new file mode 100644 index 0000000..7c3dfba --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/splashitem.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 "splashitem.h" + +#include <QPainter> + +//! [0] +SplashItem::SplashItem(QGraphicsItem *parent) + : QGraphicsObject(parent) +{ + text = tr("Welcome to the Pad Navigator Example. You can use the" + " keyboard arrows to navigate the icons, and press enter" + " to activate an item. Press any key to begin."); + setCacheMode(DeviceCoordinateCache); +} +//! [0] + +//! [1] +QRectF SplashItem::boundingRect() const +{ + return QRectF(0, 0, 400, 175); +} +//! [1] + +//! [2] +void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + painter->setPen(QPen(Qt::black, 2)); + painter->setBrush(QColor(245, 245, 255, 220)); + painter->setClipRect(boundingRect()); + painter->drawRoundedRect(3, -100 + 3, 400 - 6, 250 - 6, 25, 25, Qt::RelativeSize); + + QRectF textRect = boundingRect().adjusted(10, 10, -10, -10); + int flags = Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap; + + QFont font; + font.setPixelSize(18); + painter->setPen(Qt::black); + painter->setFont(font); + painter->drawText(textRect, flags, text); +} +//! [2] diff --git a/examples/widgets/graphicsview/padnavigator/splashitem.h b/examples/widgets/graphicsview/padnavigator/splashitem.h new file mode 100644 index 0000000..b8e723d --- /dev/null +++ b/examples/widgets/graphicsview/padnavigator/splashitem.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef SPLASHITEM_H +#define SPLASHITEM_H + +#include <QGraphicsObject> + +//! [0] +class SplashItem : public QGraphicsObject +{ + Q_OBJECT +public: + explicit SplashItem(QGraphicsItem *parent = nullptr); + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + +private: + QString text; +}; +//! [0] + +#endif // SPLASHITEM_H diff --git a/examples/widgets/statemachine/CMakeLists.txt b/examples/widgets/statemachine/CMakeLists.txt new file mode 100644 index 0000000..90a7b3e --- /dev/null +++ b/examples/widgets/statemachine/CMakeLists.txt @@ -0,0 +1,10 @@ +# Generated from statemachine.pro. + +add_subdirectory(factorial) +add_subdirectory(pingpong) +if(TARGET Qt::Widgets) + add_subdirectory(eventtransitions) + add_subdirectory(rogue) + add_subdirectory(trafficlight) + add_subdirectory(twowaybutton) +endif() diff --git a/examples/widgets/statemachine/README b/examples/widgets/statemachine/README new file mode 100644 index 0000000..a0ac35a --- /dev/null +++ b/examples/widgets/statemachine/README @@ -0,0 +1,6 @@ +Qt is provided with a powerful hierchical finite state machine through +the Qt State Machine classes. + + +Documentation for these examples can be found via the Examples +link in the main Qt documentation. diff --git a/examples/widgets/statemachine/eventtransitions/CMakeLists.txt b/examples/widgets/statemachine/eventtransitions/CMakeLists.txt new file mode 100644 index 0000000..eeb2223 --- /dev/null +++ b/examples/widgets/statemachine/eventtransitions/CMakeLists.txt @@ -0,0 +1,36 @@ +# Generated from eventtransitions.pro. + +cmake_minimum_required(VERSION 3.14) +project(eventtransitions LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/eventtransitions") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(eventtransitions + main.cpp +) +target_link_libraries(eventtransitions PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + +install(TARGETS eventtransitions + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/eventtransitions/eventtransitions.pro b/examples/widgets/statemachine/eventtransitions/eventtransitions.pro new file mode 100644 index 0000000..ab458df --- /dev/null +++ b/examples/widgets/statemachine/eventtransitions/eventtransitions.pro @@ -0,0 +1,7 @@ +QT += statemachine widgets + +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/eventtransitions +INSTALLS += target diff --git a/examples/widgets/statemachine/eventtransitions/main.cpp b/examples/widgets/statemachine/eventtransitions/main.cpp new file mode 100644 index 0000000..fe95180 --- /dev/null +++ b/examples/widgets/statemachine/eventtransitions/main.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QApplication> +#include <QEventTransition> +#include <QPushButton> +#include <QStateMachine> +#include <QVBoxLayout> +#include <QWidget> + +//! [0] +class Window : public QWidget +{ +public: + Window(QWidget *parent = nullptr) + : QWidget(parent) + { + QPushButton *button = new QPushButton(this); + button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(button); + layout->setContentsMargins(80, 80, 80, 80); + setLayout(layout); +//! [0] + +//! [1] + QStateMachine *machine = new QStateMachine(this); + + QState *s1 = new QState(); + s1->assignProperty(button, "text", "Outside"); + + QState *s2 = new QState(); + s2->assignProperty(button, "text", "Inside"); +//! [1] + +//! [2] + QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter); + enterTransition->setTargetState(s2); + s1->addTransition(enterTransition); +//! [2] + +//! [3] + QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave); + leaveTransition->setTargetState(s1); + s2->addTransition(leaveTransition); +//! [3] + +//! [4] + QState *s3 = new QState(); + s3->assignProperty(button, "text", "Pressing..."); + + QEventTransition *pressTransition = new QEventTransition(button, QEvent::MouseButtonPress); + pressTransition->setTargetState(s3); + s2->addTransition(pressTransition); + + QEventTransition *releaseTransition = new QEventTransition(button, QEvent::MouseButtonRelease); + releaseTransition->setTargetState(s2); + s3->addTransition(releaseTransition); +//! [4] + +//! [5] + machine->addState(s1); + machine->addState(s2); + machine->addState(s3); + + machine->setInitialState(s1); + machine->start(); + } +}; +//! [5] + +//! [6] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Window window; + window.resize(300, 300); + window.show(); + + return app.exec(); +} +//! [6] diff --git a/examples/widgets/statemachine/factorial/CMakeLists.txt b/examples/widgets/statemachine/factorial/CMakeLists.txt new file mode 100644 index 0000000..9f0e9ce --- /dev/null +++ b/examples/widgets/statemachine/factorial/CMakeLists.txt @@ -0,0 +1,32 @@ +# Generated from factorial.pro. + +cmake_minimum_required(VERSION 3.14) +project(factorial LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/factorial") + +find_package(Qt6 COMPONENTS Core) + +add_executable(factorial + main.cpp +) +target_link_libraries(factorial PUBLIC + Qt::Core + statemachine +) + +install(TARGETS factorial + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/factorial/factorial.pro b/examples/widgets/statemachine/factorial/factorial.pro new file mode 100644 index 0000000..af0c129 --- /dev/null +++ b/examples/widgets/statemachine/factorial/factorial.pro @@ -0,0 +1,10 @@ +QT = core statemachine +CONFIG += cmdline + +SOURCES += main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/factorial +INSTALLS += target + + diff --git a/examples/widgets/statemachine/factorial/main.cpp b/examples/widgets/statemachine/factorial/main.cpp new file mode 100644 index 0000000..03b7f92 --- /dev/null +++ b/examples/widgets/statemachine/factorial/main.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtCore> +#include <QtStateMachine> + +//! [0] +class Factorial : public QObject +{ + Q_OBJECT + Q_PROPERTY(int x READ x WRITE setX) + Q_PROPERTY(int fac READ fac WRITE setFac) +public: + using QObject::QObject; + + int x() const + { + return m_x; + } + + void setX(int x) + { + if (x == m_x) + return; + m_x = x; + emit xChanged(x); + } + + int fac() const + { + return m_fac; + } + + void setFac(int fac) + { + m_fac = fac; + } + +Q_SIGNALS: + void xChanged(int value); + +private: + int m_x = -1; + int m_fac = 1; +}; +//! [0] + +//! [1] +class FactorialLoopTransition : public QSignalTransition +{ +public: + FactorialLoopTransition(Factorial *fact) + : QSignalTransition(fact, &Factorial::xChanged), m_fact(fact) + {} + + bool eventTest(QEvent *e) override + { + if (!QSignalTransition::eventTest(e)) + return false; + QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e); + return se->arguments().at(0).toInt() > 1; + } + + void onTransition(QEvent *e) override + { + QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e); + int x = se->arguments().at(0).toInt(); + int fac = m_fact->property("fac").toInt(); + m_fact->setProperty("fac", x * fac); + m_fact->setProperty("x", x - 1); + } + +private: + Factorial *m_fact; +}; +//! [1] + +//! [2] +class FactorialDoneTransition : public QSignalTransition +{ +public: + FactorialDoneTransition(Factorial *fact) + : QSignalTransition(fact, &Factorial::xChanged), m_fact(fact) + {} + + bool eventTest(QEvent *e) override + { + if (!QSignalTransition::eventTest(e)) + return false; + QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e); + return se->arguments().at(0).toInt() <= 1; + } + + void onTransition(QEvent *) override + { + qInfo() << m_fact->property("fac").toInt(); + } + +private: + Factorial *m_fact; +}; +//! [2] + +//! [3] +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + Factorial factorial; + QStateMachine machine; +//! [3] + +//! [4] + QState *compute = new QState(&machine); + compute->assignProperty(&factorial, "fac", 1); + compute->assignProperty(&factorial, "x", 6); + compute->addTransition(new FactorialLoopTransition(&factorial)); +//! [4] + +//! [5] + QFinalState *done = new QFinalState(&machine); + FactorialDoneTransition *doneTransition = new FactorialDoneTransition(&factorial); + doneTransition->setTargetState(done); + compute->addTransition(doneTransition); +//! [5] + +//! [6] + machine.setInitialState(compute); + QObject::connect(&machine, &QStateMachine::finished, &app, QCoreApplication::quit); + machine.start(); + + return app.exec(); +} +//! [6] + +#include "main.moc" diff --git a/examples/widgets/statemachine/pingpong/CMakeLists.txt b/examples/widgets/statemachine/pingpong/CMakeLists.txt new file mode 100644 index 0000000..3ad02b9 --- /dev/null +++ b/examples/widgets/statemachine/pingpong/CMakeLists.txt @@ -0,0 +1,32 @@ +# Generated from pingpong.pro. + +cmake_minimum_required(VERSION 3.14) +project(pingpong LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/pingpong") + +find_package(Qt6 COMPONENTS Core) + +add_executable(pingpong + main.cpp +) +target_link_libraries(pingpong PUBLIC + Qt::Core + statemachine +) + +install(TARGETS pingpong + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/pingpong/main.cpp b/examples/widgets/statemachine/pingpong/main.cpp new file mode 100644 index 0000000..5f3de39 --- /dev/null +++ b/examples/widgets/statemachine/pingpong/main.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtCore> +#include <QtStateMachine> + +#include <stdio.h> + +//! [0] +class PingEvent : public QEvent +{ +public: + PingEvent() : QEvent(QEvent::Type(QEvent::User+2)) + {} +}; + +class PongEvent : public QEvent +{ +public: + PongEvent() : QEvent(QEvent::Type(QEvent::User+3)) + {} +}; +//! [0] + +//! [1] +class Pinger : public QState +{ +public: + Pinger(QState *parent) + : QState(parent) {} + +protected: + void onEntry(QEvent *) override + { + machine()->postEvent(new PingEvent()); + fprintf(stdout, "ping?\n"); + } +}; +//! [1] + +//! [3] +class PongTransition : public QAbstractTransition +{ +public: + PongTransition() {} + +protected: + bool eventTest(QEvent *e) override { + return (e->type() == QEvent::User+3); + } + void onTransition(QEvent *) override + { + machine()->postDelayedEvent(new PingEvent(), 500); + fprintf(stdout, "ping?\n"); + } +}; +//! [3] + +//! [2] +class PingTransition : public QAbstractTransition +{ +public: + PingTransition() {} + +protected: + bool eventTest(QEvent *e) override { + return (e->type() == QEvent::User+2); + } + void onTransition(QEvent *) override + { + machine()->postDelayedEvent(new PongEvent(), 500); + fprintf(stdout, "pong!\n"); + } +}; +//! [2] + +//! [4] +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QStateMachine machine; + QState *group = new QState(QState::ParallelStates); + group->setObjectName("group"); +//! [4] + +//! [5] + Pinger *pinger = new Pinger(group); + pinger->setObjectName("pinger"); + pinger->addTransition(new PongTransition()); + + QState *ponger = new QState(group); + ponger->setObjectName("ponger"); + ponger->addTransition(new PingTransition()); +//! [5] + +//! [6] + machine.addState(group); + machine.setInitialState(group); + machine.start(); + + return app.exec(); +} +//! [6] diff --git a/examples/widgets/statemachine/pingpong/pingpong.pro b/examples/widgets/statemachine/pingpong/pingpong.pro new file mode 100644 index 0000000..b8b75af --- /dev/null +++ b/examples/widgets/statemachine/pingpong/pingpong.pro @@ -0,0 +1,10 @@ +QT = statemachine core +CONFIG += cmdline + +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/pingpong +INSTALLS += target + + diff --git a/examples/widgets/statemachine/rogue/CMakeLists.txt b/examples/widgets/statemachine/rogue/CMakeLists.txt new file mode 100644 index 0000000..5f183a3 --- /dev/null +++ b/examples/widgets/statemachine/rogue/CMakeLists.txt @@ -0,0 +1,38 @@ +# Generated from rogue.pro. + +cmake_minimum_required(VERSION 3.14) +project(rogue LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/rogue") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(rogue + main.cpp + movementtransition.h + window.cpp window.h +) +target_link_libraries(rogue PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + +install(TARGETS rogue + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/rogue/main.cpp b/examples/widgets/statemachine/rogue/main.cpp new file mode 100644 index 0000000..44ade77 --- /dev/null +++ b/examples/widgets/statemachine/rogue/main.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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 <QtWidgets> + +#include "window.h" + +int main(int argv, char **args) +{ + QApplication app(argv, args); + + Window window; + window.show(); + + return app.exec(); +} + diff --git a/examples/widgets/statemachine/rogue/movementtransition.h b/examples/widgets/statemachine/rogue/movementtransition.h new file mode 100644 index 0000000..d8a9b97 --- /dev/null +++ b/examples/widgets/statemachine/rogue/movementtransition.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +#ifndef MOVEMENTTRANSITION_H +#define MOVEMENTTRANSITION_H + +#include <QtStateMachine> +#include <QtWidgets> + +#include "window.h" + +//![0] +class MovementTransition : public QEventTransition +{ + Q_OBJECT + +public: + MovementTransition(Window *window) : + QEventTransition(window, QEvent::KeyPress) { + this->window = window; + } +//![0] + +//![1] +protected: + bool eventTest(QEvent *event) override { + if (event->type() == QEvent::StateMachineWrapped && + static_cast<QStateMachine::WrappedEvent *>(event)->event()->type() == QEvent::KeyPress) { + QEvent *wrappedEvent = static_cast<QStateMachine::WrappedEvent *>(event)->event(); + + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(wrappedEvent); + int key = keyEvent->key(); + + return key == Qt::Key_2 || key == Qt::Key_8 || key == Qt::Key_6 || + key == Qt::Key_4 || key == Qt::Key_Down || key == Qt::Key_Up || + key == Qt::Key_Right || key == Qt::Key_Left; + } + return false; + } +//![1] + +//![2] + void onTransition(QEvent *event) override { + QKeyEvent *keyEvent = static_cast<QKeyEvent *>( + static_cast<QStateMachine::WrappedEvent *>(event)->event()); + + int key = keyEvent->key(); + switch (key) { + case Qt::Key_Left: + case Qt::Key_4: + window->movePlayer(Window::Left); + break; + case Qt::Key_Up: + case Qt::Key_8: + window->movePlayer(Window::Up); + break; + case Qt::Key_Right: + case Qt::Key_6: + window->movePlayer(Window::Right); + break; + case Qt::Key_Down: + case Qt::Key_2: + window->movePlayer(Window::Down); + break; + default: + ; + } + } +//![2] + +private: + Window *window; +}; + +#endif + diff --git a/examples/widgets/statemachine/rogue/rogue.pro b/examples/widgets/statemachine/rogue/rogue.pro new file mode 100644 index 0000000..484c8eb --- /dev/null +++ b/examples/widgets/statemachine/rogue/rogue.pro @@ -0,0 +1,10 @@ +QT += statemachine widgets + +HEADERS = window.h \ + movementtransition.h +SOURCES = main.cpp \ + window.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/rogue +INSTALLS += target diff --git a/examples/widgets/statemachine/rogue/window.cpp b/examples/widgets/statemachine/rogue/window.cpp new file mode 100644 index 0000000..a5363e2 --- /dev/null +++ b/examples/widgets/statemachine/rogue/window.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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 <QtWidgets> + +#include "window.h" +#include "movementtransition.h" + +//![0] +Window::Window() +{ + pX = 5; + pY = 5; +//![0] + + QFontDatabase database; + QFont font; + if (database.families().contains("Monospace")) { + font = QFont("Monospace"); + } + else { + const QStringList fontFamilies = database.families(); + for (const QString &family : fontFamilies ) { + if (database.isFixedPitch(family)) { + font = QFont(family); + break; + } + } + } + font.setPointSize(12); + setFont(font); + +//![1] + setupMap(); + buildMachine(); +} +//![1] + +void Window::setStatus(const QString &status) +{ + myStatus = status; + repaint(); +} + +QString Window::status() const +{ + return myStatus; +} + +void Window::paintEvent(QPaintEvent * /* event */) +{ + QFontMetrics metrics(font()); + QPainter painter(this); + int fontHeight = metrics.height(); + int fontWidth = metrics.horizontalAdvance('X'); + int yPos = fontHeight; + int xPos; + + painter.fillRect(rect(), Qt::black); + painter.setPen(Qt::white); + + painter.drawText(QPoint(0, yPos), status()); + + for (int y = 0; y < HEIGHT; ++y) { + yPos += fontHeight; + xPos = 0; + + for (int x = 0; x < WIDTH; ++x) { + if (y == pY && x == pX) { + xPos += fontWidth; + continue; + } + + painter.setPen(Qt::white); + + double x1 = static_cast<double>(pX); + double y1 = static_cast<double>(pY); + double x2 = static_cast<double>(x); + double y2 = static_cast<double>(y); + + if (x2<x1) { + x2+=0.5; + } else if (x2>x1) { + x2-=0.5; + } + + if (y2<y1) { + y2+=0.5; + } else if (y2>y1) { + y2-=0.5; + } + + double dx = x2 - x1; + double dy = y2 - y1; + + double length = qSqrt(dx*dx+dy*dy); + + dx /= length; + dy /= length; + + double xi = x1; + double yi = y1; + + while (length > 0) { + int cx = static_cast<int>(xi+0.5); + int cy = static_cast<int>(yi+0.5); + + if (x2 == cx && y2 == cy) + break; + + if (!(x1==cx && y1==cy) + && (map[cx][cy] == '#' || (length-10) > 0)) { + painter.setPen(QColor(60,60,60)); + break; + } + + xi += dx; + yi += dy; + --length; + } + + painter.drawText(QPoint(xPos, yPos), map[x][y]); + xPos += fontWidth; + } + } + painter.setPen(Qt::white); + painter.drawText(QPoint(pX * fontWidth, (pY + 2) * fontHeight), QChar('@')); +} + +QSize Window::sizeHint() const +{ + QFontMetrics metrics(font()); + + return QSize(metrics.horizontalAdvance('X') * WIDTH, metrics.height() * (HEIGHT + 1)); +} + +//![2] +void Window::buildMachine() +{ + machine = new QStateMachine; + + QState *inputState = new QState(machine); + inputState->assignProperty(this, "status", "Move the rogue with 2, 4, 6, and 8"); + + MovementTransition *transition = new MovementTransition(this); + inputState->addTransition(transition); +//![2] + +//![3] + QState *quitState = new QState(machine); + quitState->assignProperty(this, "status", "Really quit(y/n)?"); + + QKeyEventTransition *yesTransition = new + QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Y); + yesTransition->setTargetState(new QFinalState(machine)); + quitState->addTransition(yesTransition); + + QKeyEventTransition *noTransition = + new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_N); + noTransition->setTargetState(inputState); + quitState->addTransition(noTransition); +//![3] + +//![4] + QKeyEventTransition *quitTransition = + new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Q); + quitTransition->setTargetState(quitState); + inputState->addTransition(quitTransition); +//![4] + +//![5] + machine->setInitialState(inputState); + + connect(machine, &QStateMachine::finished, + qApp, &QApplication::quit); + + machine->start(); +} +//![5] + +void Window::movePlayer(Direction direction) +{ + switch (direction) { + case Left: + if (map[pX - 1][pY] != '#') + --pX; + break; + case Right: + if (map[pX + 1][pY] != '#') + ++pX; + break; + case Up: + if (map[pX][pY - 1] != '#') + --pY; + break; + case Down: + if (map[pX][pY + 1] != '#') + ++pY; + break; + } + repaint(); +} + +void Window::setupMap() +{ + for (int x = 0; x < WIDTH; ++x) + for (int y = 0; y < HEIGHT; ++y) { + if (x == 0 || x == WIDTH - 1 || y == 0 || y == HEIGHT - 1 || QRandomGenerator::global()->bounded(40) == 0) + map[x][y] = '#'; + else + map[x][y] = '.'; + } +} + diff --git a/examples/widgets/statemachine/rogue/window.h b/examples/widgets/statemachine/rogue/window.h new file mode 100644 index 0000000..af34815 --- /dev/null +++ b/examples/widgets/statemachine/rogue/window.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QState; +class QStateMachine; +class QTransition; +QT_END_NAMESPACE + +#define WIDTH 35 +#define HEIGHT 20 + +//![0] +class Window : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString status READ status WRITE setStatus) + +public: + enum Direction { Up, Down, Left, Right }; + + Window(); + + void movePlayer(Direction direction); + void setStatus(const QString &status); + QString status() const; + + QSize sizeHint() const override; + +protected: + void paintEvent(QPaintEvent *event) override; +//![0] + +//![1] +private: + void buildMachine(); + void setupMap(); + + QChar map[WIDTH][HEIGHT]; + int pX, pY; + + QStateMachine *machine; + QString myStatus; +}; +//![1] + +#endif + diff --git a/examples/widgets/statemachine/statemachine.pro b/examples/widgets/statemachine/statemachine.pro new file mode 100644 index 0000000..926e01c --- /dev/null +++ b/examples/widgets/statemachine/statemachine.pro @@ -0,0 +1,12 @@ +TEMPLATE = subdirs +SUBDIRS = \ + factorial \ + pingpong + +qtHaveModule(widgets) { + SUBDIRS += \ + eventtransitions \ + rogue \ + trafficlight \ + twowaybutton +} diff --git a/examples/widgets/statemachine/trafficlight/CMakeLists.txt b/examples/widgets/statemachine/trafficlight/CMakeLists.txt new file mode 100644 index 0000000..f1c618c --- /dev/null +++ b/examples/widgets/statemachine/trafficlight/CMakeLists.txt @@ -0,0 +1,36 @@ +# Generated from trafficlight.pro. + +cmake_minimum_required(VERSION 3.14) +project(trafficlight LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/trafficlight") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(trafficlight + main.cpp +) +target_link_libraries(trafficlight PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + +install(TARGETS trafficlight + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/trafficlight/main.cpp b/examples/widgets/statemachine/trafficlight/main.cpp new file mode 100644 index 0000000..dd8bddc --- /dev/null +++ b/examples/widgets/statemachine/trafficlight/main.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QApplication> +#include <QFinalState> +#include <QPainter> +#include <QStateMachine> +#include <QTimer> +#include <QVBoxLayout> +#include <QWidget> + +//! [0] +class LightWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(bool on READ isOn WRITE setOn) +public: + LightWidget(const QColor &color, QWidget *parent = nullptr) + : QWidget(parent), m_color(color), m_on(false) {} + + bool isOn() const + { return m_on; } + void setOn(bool on) + { + if (on == m_on) + return; + m_on = on; + update(); + } + +public slots: + void turnOff() { setOn(false); } + void turnOn() { setOn(true); } + +protected: + void paintEvent(QPaintEvent *) override + { + if (!m_on) + return; + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setBrush(m_color); + painter.drawEllipse(0, 0, width(), height()); + } + +private: + QColor m_color; + bool m_on; +}; +//! [0] + +//! [1] +class TrafficLightWidget : public QWidget +{ +public: + TrafficLightWidget(QWidget *parent = nullptr) + : QWidget(parent) + { + QVBoxLayout *vbox = new QVBoxLayout(this); + m_red = new LightWidget(Qt::red); + vbox->addWidget(m_red); + m_yellow = new LightWidget(Qt::yellow); + vbox->addWidget(m_yellow); + m_green = new LightWidget(Qt::green); + vbox->addWidget(m_green); + QPalette pal = palette(); + pal.setColor(QPalette::Window, Qt::black); + setPalette(pal); + setAutoFillBackground(true); + } + + LightWidget *redLight() const + { return m_red; } + LightWidget *yellowLight() const + { return m_yellow; } + LightWidget *greenLight() const + { return m_green; } + +private: + LightWidget *m_red; + LightWidget *m_yellow; + LightWidget *m_green; +}; +//! [1] + +//! [2] +QState *createLightState(LightWidget *light, int duration, QState *parent = nullptr) +{ + QState *lightState = new QState(parent); + QTimer *timer = new QTimer(lightState); + timer->setInterval(duration); + timer->setSingleShot(true); + QState *timing = new QState(lightState); + QObject::connect(timing, &QAbstractState::entered, light, &LightWidget::turnOn); + QObject::connect(timing, &QAbstractState::entered, timer, QOverload<>::of(&QTimer::start)); + QObject::connect(timing, &QAbstractState::exited, light, &LightWidget::turnOff); + QFinalState *done = new QFinalState(lightState); + timing->addTransition(timer, &QTimer::timeout, done); + lightState->setInitialState(timing); + return lightState; +} +//! [2] + +//! [3] +class TrafficLight : public QWidget +{ +public: + TrafficLight(QWidget *parent = nullptr) + : QWidget(parent) + { + QVBoxLayout *vbox = new QVBoxLayout(this); + TrafficLightWidget *widget = new TrafficLightWidget; + vbox->addWidget(widget); + vbox->setContentsMargins(QMargins()); + + QStateMachine *machine = new QStateMachine(this); + QState *redGoingYellow = createLightState(widget->redLight(), 3000); + redGoingYellow->setObjectName("redGoingYellow"); + QState *yellowGoingGreen = createLightState(widget->yellowLight(), 1000); + yellowGoingGreen->setObjectName("yellowGoingGreen"); + redGoingYellow->addTransition(redGoingYellow, &QState::finished, yellowGoingGreen); + QState *greenGoingYellow = createLightState(widget->greenLight(), 3000); + greenGoingYellow->setObjectName("greenGoingYellow"); + yellowGoingGreen->addTransition(yellowGoingGreen, &QState::finished, greenGoingYellow); + QState *yellowGoingRed = createLightState(widget->yellowLight(), 1000); + yellowGoingRed->setObjectName("yellowGoingRed"); + greenGoingYellow->addTransition(greenGoingYellow, &QState::finished, yellowGoingRed); + yellowGoingRed->addTransition(yellowGoingRed, &QState::finished, redGoingYellow); + + machine->addState(redGoingYellow); + machine->addState(yellowGoingGreen); + machine->addState(greenGoingYellow); + machine->addState(yellowGoingRed); + machine->setInitialState(redGoingYellow); + machine->start(); + } +}; +//! [3] + +//! [4] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + TrafficLight widget; + widget.resize(110, 300); + widget.show(); + + return app.exec(); +} +//! [4] + +#include "main.moc" diff --git a/examples/widgets/statemachine/trafficlight/trafficlight.pro b/examples/widgets/statemachine/trafficlight/trafficlight.pro new file mode 100644 index 0000000..e70ebdd --- /dev/null +++ b/examples/widgets/statemachine/trafficlight/trafficlight.pro @@ -0,0 +1,9 @@ +QT += statemachine widgets + +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/trafficlight +INSTALLS += target + + diff --git a/examples/widgets/statemachine/twowaybutton/CMakeLists.txt b/examples/widgets/statemachine/twowaybutton/CMakeLists.txt new file mode 100644 index 0000000..f989f5e --- /dev/null +++ b/examples/widgets/statemachine/twowaybutton/CMakeLists.txt @@ -0,0 +1,36 @@ +# Generated from twowaybutton.pro. + +cmake_minimum_required(VERSION 3.14) +project(twowaybutton LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/statemachine/twowaybutton") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +add_qt_gui_executable(twowaybutton + main.cpp +) +target_link_libraries(twowaybutton PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + statemachine +) + +install(TARGETS twowaybutton + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/widgets/statemachine/twowaybutton/main.cpp b/examples/widgets/statemachine/twowaybutton/main.cpp new file mode 100644 index 0000000..4238193 --- /dev/null +++ b/examples/widgets/statemachine/twowaybutton/main.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 <QtStateMachine> +#include <QtWidgets> + +//! [0] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + QPushButton button; + QStateMachine machine; +//! [0] + +//! [1] + QState *off = new QState(); + off->assignProperty(&button, "text", "Off"); + off->setObjectName("off"); + + QState *on = new QState(); + on->setObjectName("on"); + on->assignProperty(&button, "text", "On"); +//! [1] + +//! [2] + off->addTransition(&button, &QAbstractButton::clicked, on); + on->addTransition(&button, &QAbstractButton::clicked, off); +//! [2] + +//! [3] + machine.addState(off); + machine.addState(on); +//! [3] + +//! [4] + machine.setInitialState(off); + machine.start(); +//! [4] + +//! [5] + button.resize(100, 50); + button.show(); + return app.exec(); +} +//! [5] diff --git a/examples/widgets/statemachine/twowaybutton/twowaybutton.pro b/examples/widgets/statemachine/twowaybutton/twowaybutton.pro new file mode 100644 index 0000000..e4911d7 --- /dev/null +++ b/examples/widgets/statemachine/twowaybutton/twowaybutton.pro @@ -0,0 +1,9 @@ +QT += statemachine widgets + +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/statemachine/twowaybutton +INSTALLS += target + + diff --git a/examples/widgets/widgets.pro b/examples/widgets/widgets.pro new file mode 100644 index 0000000..cb7341e --- /dev/null +++ b/examples/widgets/widgets.pro @@ -0,0 +1,8 @@ +requires(qtHaveModule(widgets)) + +TEMPLATE = subdirs +CONFIG += no_docs_target + +SUBDIRS = graphicsview \ + statemachine +qtConfig(animation): SUBDIRS += animation |