diff options
Diffstat (limited to 'examples')
347 files changed, 19326 insertions, 303 deletions
diff --git a/examples/animation/animatedtiles/animatedtiles.pro b/examples/animation/animatedtiles/animatedtiles.pro new file mode 100644 index 0000000..9e9062c --- /dev/null +++ b/examples/animation/animatedtiles/animatedtiles.pro @@ -0,0 +1,2 @@ +SOURCES += main.cpp +RESOURCES += animatedtiles.qrc diff --git a/examples/animation/animatedtiles/animatedtiles.qrc b/examples/animation/animatedtiles/animatedtiles.qrc new file mode 100644 index 0000000..c43a979 --- /dev/null +++ b/examples/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/animation/animatedtiles/images/Time-For-Lunch-2.jpg b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg Binary files differnew file mode 100644 index 0000000..c57a555 --- /dev/null +++ b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg diff --git a/examples/animation/animatedtiles/images/centered.png b/examples/animation/animatedtiles/images/centered.png Binary files differnew file mode 100644 index 0000000..e416156 --- /dev/null +++ b/examples/animation/animatedtiles/images/centered.png diff --git a/examples/animation/animatedtiles/images/ellipse.png b/examples/animation/animatedtiles/images/ellipse.png Binary files differnew file mode 100644 index 0000000..2c3ba88 --- /dev/null +++ b/examples/animation/animatedtiles/images/ellipse.png diff --git a/examples/animation/animatedtiles/images/figure8.png b/examples/animation/animatedtiles/images/figure8.png Binary files differnew file mode 100644 index 0000000..6b05804 --- /dev/null +++ b/examples/animation/animatedtiles/images/figure8.png diff --git a/examples/animation/animatedtiles/images/kinetic.png b/examples/animation/animatedtiles/images/kinetic.png Binary files differnew file mode 100644 index 0000000..55cfa55 --- /dev/null +++ b/examples/animation/animatedtiles/images/kinetic.png diff --git a/examples/animation/animatedtiles/images/random.png b/examples/animation/animatedtiles/images/random.png Binary files differnew file mode 100644 index 0000000..415d96f --- /dev/null +++ b/examples/animation/animatedtiles/images/random.png diff --git a/examples/animation/animatedtiles/images/tile.png b/examples/animation/animatedtiles/images/tile.png Binary files differnew file mode 100644 index 0000000..c8f39d8 --- /dev/null +++ b/examples/animation/animatedtiles/images/tile.png diff --git a/examples/animation/animatedtiles/main.cpp b/examples/animation/animatedtiles/main.cpp new file mode 100644 index 0000000..e4a774c --- /dev/null +++ b/examples/animation/animatedtiles/main.cpp @@ -0,0 +1,242 @@ +#include <QtGui> +#ifdef QT_EXPERIMENTAL_SOLUTION +# include "qgraphicswidget.h" +# include "qstate.h" +# include "qstatemachine.h" +# include "qgraphicswidget.h" +# include "qparallelanimationgroup.h" +# include "qpropertyanimation.h" +#else +#include <QtCore/qstate.h> +#endif + +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 = 0) + : QGraphicsWidget(parent), _pix(pixmap) + { + setAcceptHoverEvents(true); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const + { + return QRectF(-65, -65, 130, 130); + } + + QPainterPath shape() const + { + QPainterPath path; + path.addEllipse(boundingRect()); + return path; + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) + { + 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 *) + { + emit pressed(); + update(); + } + + void mouseReleaseEvent(QGraphicsSceneMouseEvent *) + { + update(); + } + +private: + QPixmap _pix; +}; + +class View : public QGraphicsView +{ +public: + View(QGraphicsScene *scene) : QGraphicsView(scene) { } + +protected: + void resizeEvent(QResizeEvent *event) + { + QGraphicsView::resizeEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); + } +}; + +int main(int argc, char **argv) +{ + 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->scale(0.75, 0.75); + 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 < 64; ++i) { + Pixmap *item = items.at(i); + // Ellipse + ellipseState->setPropertyOnEntry(item, "pos", + QPointF(cos((i / 63.0) * 6.28) * 250, + sin((i / 63.0) * 6.28) * 250)); + + // Figure 8 + figure8State->setPropertyOnEntry(item, "pos", + QPointF(sin((i / 63.0) * 6.28) * 250, + sin(((i * 2)/63.0) * 6.28) * 250)); + + // Random + randomState->setPropertyOnEntry(item, "pos", + QPointF(-250 + qrand() % 500, + -250 + qrand() % 500)); + + // Tiled + tiledState->setPropertyOnEntry(item, "pos", + QPointF(((i % 8) - 4) * kineticPix.width() + kineticPix.width() / 2, + ((i / 8) - 4) * kineticPix.height() + kineticPix.height() / 2)); + + // Centered + centeredState->setPropertyOnEntry(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); + + // rootState->addTransition(ellipseButton, SIGNAL(pressed()), ellipseState); + QParallelAnimationGroup *group = new QParallelAnimationGroup; + for (int i = 0; i < 64; ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + rootState->addAnimatedTransition(ellipseButton, SIGNAL(pressed()), ellipseState, group); + + group = new QParallelAnimationGroup; + for (int i = 0; i < 64; ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + rootState->addAnimatedTransition(figure8Button, SIGNAL(pressed()), figure8State, group); + + group = new QParallelAnimationGroup; + for (int i = 0; i < 64; ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + rootState->addAnimatedTransition(randomButton, SIGNAL(pressed()), randomState, group); + + group = new QParallelAnimationGroup; + for (int i = 0; i < 64; ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + rootState->addAnimatedTransition(tiledButton, SIGNAL(pressed()), tiledState, group); + + group = new QParallelAnimationGroup; + for (int i = 0; i < 64; ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + rootState->addAnimatedTransition(centeredButton, SIGNAL(pressed()), centeredState, group); + + states.start(); + QTimer timer; + timer.start(125); + timer.setSingleShot(true); + rootState->addAnimatedTransition(&timer, SIGNAL(timeout()), ellipseState, group); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/animation.pro b/examples/animation/animation.pro new file mode 100644 index 0000000..d5121a1 --- /dev/null +++ b/examples/animation/animation.pro @@ -0,0 +1,21 @@ +TEMPLATE = \ + subdirs +SUBDIRS += \ + animatedtiles \ + appchooser \ + easing \ + example \ + moveblocks \ + padnavigator-ng \ + photobrowser \ + piemenu \ + selectbutton \ + states \ + stickman \ + sub-attaq + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/animation +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS animation.pro README +sources.path = $$[QT_INSTALL_EXAMPLES]/animation +INSTALLS += target sources diff --git a/examples/animation/appchooser/accessories-dictionary.png b/examples/animation/appchooser/accessories-dictionary.png Binary files differnew file mode 100644 index 0000000..e9bd55d --- /dev/null +++ b/examples/animation/appchooser/accessories-dictionary.png diff --git a/examples/animation/appchooser/akregator.png b/examples/animation/appchooser/akregator.png Binary files differnew file mode 100644 index 0000000..a086f45 --- /dev/null +++ b/examples/animation/appchooser/akregator.png diff --git a/examples/animation/appchooser/appchooser.pro b/examples/animation/appchooser/appchooser.pro new file mode 100644 index 0000000..8cda19a --- /dev/null +++ b/examples/animation/appchooser/appchooser.pro @@ -0,0 +1,9 @@ +# Input +SOURCES += main.cpp +RESOURCES += appchooser.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/animation/appchooser +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS appchooser.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/animation/appchooser +INSTALLS += target sources diff --git a/examples/animation/appchooser/appchooser.qrc b/examples/animation/appchooser/appchooser.qrc new file mode 100644 index 0000000..28a3e1c --- /dev/null +++ b/examples/animation/appchooser/appchooser.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>accessories-dictionary.png</file> + <file>akregator.png</file> + <file>digikam.png</file> + <file>k3b.png</file> +</qresource> +</RCC> diff --git a/examples/animation/appchooser/digikam.png b/examples/animation/appchooser/digikam.png Binary files differnew file mode 100644 index 0000000..9de9fb2 --- /dev/null +++ b/examples/animation/appchooser/digikam.png diff --git a/examples/animation/appchooser/k3b.png b/examples/animation/appchooser/k3b.png Binary files differnew file mode 100644 index 0000000..bbcafcf --- /dev/null +++ b/examples/animation/appchooser/k3b.png diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp new file mode 100644 index 0000000..536bbb6 --- /dev/null +++ b/examples/animation/appchooser/main.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtGui> +#ifdef QT_EXPERIMENTAL_SOLUTION +#include "qtgraphicswidget.h" +#endif + + +class Pixmap : public QGraphicsWidget +{ + Q_OBJECT + +public: + Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), orig(pix), p(pix) + { + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + painter->drawPixmap(QPointF(), p); + } + + virtual void mousePressEvent(QGraphicsSceneMouseEvent * ) + { + emit clicked(); + } + + virtual void setGeometry(const QRectF &rect) + { + QGraphicsWidget::setGeometry(rect); + + if (rect.size().width() > orig.size().width()) + p = orig.scaled(rect.size().toSize()); + else + p = orig; + } + +Q_SIGNALS: + void clicked(); + +private: + QPixmap orig; + QPixmap p; +}; + +void createStateAndTransition(QObject *o1, const QRect &selectedRect, QState *parent) +{ + QState *state = new QState(parent); + state->setPropertyOnEntry(o1, "geometry", selectedRect); + + QPropertyAnimation *animation = new QPropertyAnimation(o1, "geometry"); + parent->addAnimatedTransition(o1, SIGNAL(clicked()), state, animation); +} + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(appchooser); + + QApplication app(argc, argv); + + 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")); + + p1->setObjectName("p1"); + p2->setObjectName("p2"); + p3->setObjectName("p3"); + p4->setObjectName("p4"); + + p1->setGeometry(QRectF(0.0, 0.0, 64.0, 64.0)); + p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0)); + p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0)); + p4->setGeometry(QRectF(0.0, 236.0, 64.0, 64.0)); + + QGraphicsScene scene(0, 0, 300, 300); + scene.setBackgroundBrush(Qt::white); + scene.addItem(p1); + scene.addItem(p2); + scene.addItem(p3); + scene.addItem(p4); + + QGraphicsView window(&scene); + window.setFrameStyle(0); + window.setAlignment(Qt::AlignLeft | Qt::AlignTop); + window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + QStateMachine machine; + machine.setGlobalRestorePolicy(QState::RestoreProperties); + + QState *group = new QState(machine.rootState()); + group->setObjectName("group"); + QRect selectedRect(86, 86, 128, 128); + + QState *idleState = new QState(group); + group->setInitialState(idleState); + + createStateAndTransition(p1, selectedRect, group); + createStateAndTransition(p2, selectedRect, group); + createStateAndTransition(p3, selectedRect, group); + createStateAndTransition(p4, selectedRect, group); + + machine.setInitialState(group); + machine.start(); + + window.resize(300, 300); + window.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/easing/animation.h b/examples/animation/easing/animation.h new file mode 100644 index 0000000..db67810 --- /dev/null +++ b/examples/animation/easing/animation.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef ANIMATION_H +#define ANIMATION_H + +#include <QtGui> + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qpropertyanimation.h" +#else +# include <QtCore/qpropertyanimation.h> +#endif + +class Animation : public QPropertyAnimation { +public: + enum PathType { + LinearPath, + CirclePath, + NPathTypes + }; + Animation(QObject *target, const QByteArray &prop) + : QPropertyAnimation(target, prop) + { + setPathType(LinearPath); + } + + void setPathType(PathType pathType) + { + if (pathType >= NPathTypes) + qWarning("Unknown pathType %d", pathType); + + m_pathType = pathType; + m_path = QPainterPath(); + } + + void updateCurrentTime(int msecs) + { + if (m_pathType == CirclePath) { + if (m_path.isEmpty()) { + QPointF to = endValue().toPointF(); + QPointF from = startValue().toPointF(); + m_path.moveTo(from); + m_path.addEllipse(QRectF(from, to)); + } + int dura = duration(); + const qreal progress = ((dura == 0) ? 1 : ((((currentTime() - 1) % dura) + 1) / qreal(dura))); + + qreal easedProgress = easingCurve().valueForProgress(progress); + if (easedProgress > 1.0) { + easedProgress -= 1.0; + } else if (easedProgress < 0) { + easedProgress += 1.0; + } + QPointF pt = m_path.pointAtPercent(easedProgress); + updateCurrentValue(pt); + emit valueChanged(pt); + } else { + QPropertyAnimation::updateCurrentTime(msecs); + } + } + + QPainterPath m_path; + PathType m_pathType; +}; + +#endif // ANIMATION_H diff --git a/examples/animation/easing/easing.pro b/examples/animation/easing/easing.pro new file mode 100644 index 0000000..fa5b22d --- /dev/null +++ b/examples/animation/easing/easing.pro @@ -0,0 +1,16 @@ +###################################################################### +# Automatically generated by qmake (2.01a) to 2. okt 23:22:11 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += window.h animation.h +SOURCES += main.cpp window.cpp + +FORMS += form.ui + +RESOURCES = resources.qrc diff --git a/examples/animation/easing/form.ui b/examples/animation/easing/form.ui new file mode 100644 index 0000000..b60ade8 --- /dev/null +++ b/examples/animation/easing/form.ui @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>471</height> + </rect> + </property> + <property name="windowTitle"> + <string>Easing curves</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QListWidget" name="easingCurvePicker"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>120</height> + </size> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="movement"> + <enum>QListView::Static</enum> + </property> + <property name="isWrapping" stdset="0"> + <bool>false</bool> + </property> + <property name="viewMode"> + <enum>QListView::IconMode</enum> + </property> + <property name="selectionRectVisible"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Path type</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QRadioButton" name="lineRadio"> + <property name="text"> + <string>Line</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string>buttonGroup</string> + </attribute> + </widget> + </item> + <item> + <widget class="QRadioButton" name="circleRadio"> + <property name="text"> + <string>Circle</string> + </property> + <attribute name="buttonGroup"> + <string>buttonGroup</string> + </attribute> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Properties</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Period</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="periodSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Amplitude</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="amplitudeSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Overshoot</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDoubleSpinBox" name="overshootSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="1"> + <widget class="QGraphicsView" name="graphicsView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> + <buttongroups> + <buttongroup name="buttonGroup"/> + </buttongroups> +</ui> diff --git a/examples/animation/easing/images/qt-logo.png b/examples/animation/easing/images/qt-logo.png Binary files differnew file mode 100644 index 0000000..14ddf2a --- /dev/null +++ b/examples/animation/easing/images/qt-logo.png diff --git a/examples/animation/easing/main.cpp b/examples/animation/easing/main.cpp new file mode 100644 index 0000000..139f2da --- /dev/null +++ b/examples/animation/easing/main.cpp @@ -0,0 +1,22 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include "window.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Window w; + w.resize(400, 400); + w.show(); + return app.exec(); +} diff --git a/examples/animation/easing/resources.qrc b/examples/animation/easing/resources.qrc new file mode 100644 index 0000000..7e112d3 --- /dev/null +++ b/examples/animation/easing/resources.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> + <qresource> + <file>images/qt-logo.png</file> + </qresource> + </RCC>
\ No newline at end of file diff --git a/examples/animation/easing/window.cpp b/examples/animation/easing/window.cpp new file mode 100644 index 0000000..c6ea360 --- /dev/null +++ b/examples/animation/easing/window.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "window.h" + +Window::Window(QWidget *parent) + : QWidget(parent), m_iconSize(64, 64) +{ + m_ui.setupUi(this); + QButtonGroup *buttonGroup = qFindChild<QButtonGroup *>(this); // ### workaround for uic in 4.4 + m_ui.easingCurvePicker->setIconSize(m_iconSize); + m_ui.easingCurvePicker->setMinimumHeight(m_iconSize.height() + 50); + buttonGroup->setId(m_ui.lineRadio, 0); + buttonGroup->setId(m_ui.circleRadio, 1); + + QEasingCurve dummy; + m_ui.periodSpinBox->setValue(dummy.period()); + m_ui.amplitudeSpinBox->setValue(dummy.amplitude()); + m_ui.overshootSpinBox->setValue(dummy.overshoot()); + + connect(m_ui.easingCurvePicker, SIGNAL(currentRowChanged(int)), this, SLOT(curveChanged(int))); + connect(buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(pathChanged(int))); + connect(m_ui.periodSpinBox, SIGNAL(valueChanged(double)), this, SLOT(periodChanged(double))); + connect(m_ui.amplitudeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(amplitudeChanged(double))); + connect(m_ui.overshootSpinBox, SIGNAL(valueChanged(double)), this, SLOT(overshootChanged(double))); + createCurveIcons(); + + QPixmap pix(QLatin1String(":/images/qt-logo.png")); + m_item = new PixmapItem(pix); + m_scene.addItem(m_item); + m_ui.graphicsView->setScene(&m_scene); + + m_anim = new Animation(m_item, "pos"); + m_anim->setEasingCurve(QEasingCurve::OutBounce); + m_ui.easingCurvePicker->setCurrentRow(int(QEasingCurve::OutBounce)); + + startAnimation(); +} + +void Window::createCurveIcons() +{ + QPixmap pix(m_iconSize); + QPainter painter(&pix); + QLinearGradient gradient(0,0, 0, m_iconSize.height()); + gradient.setColorAt(0.0, QColor(240, 240, 240)); + gradient.setColorAt(1.0, QColor(224, 224, 224)); + QBrush brush(gradient); + const QMetaObject &mo = QEasingCurve::staticMetaObject; + QMetaEnum metaEnum = mo.enumerator(mo.indexOfEnumerator("Type")); + // Skip QEasingCurve::Custom + for (int i = 0; i < QEasingCurve::NCurveTypes - 1; ++i) { + painter.fillRect(QRect(QPoint(0, 0), m_iconSize), brush); + QEasingCurve curve((QEasingCurve::Type)i); + painter.setPen(QColor(0, 0, 255, 64)); + qreal xAxis = m_iconSize.height()/1.5; + qreal yAxis = m_iconSize.width()/3; + painter.drawLine(0, xAxis, m_iconSize.width(), xAxis); + painter.drawLine(yAxis, 0, yAxis, m_iconSize.height()); + painter.setPen(Qt::black); + + qreal curveScale = m_iconSize.height()/2; + QPoint currentPos(yAxis, xAxis); + + for (qreal t = 0; t < 1.0; t+=1.0/curveScale) { + QPoint to; + to.setX(yAxis + curveScale * t); + to.setY(xAxis - curveScale * curve.valueForProgress(t)); + painter.drawLine(currentPos, to); + currentPos = to; + } + QListWidgetItem *item = new QListWidgetItem; + item->setIcon(QIcon(pix)); + item->setText(metaEnum.key(i)); + m_ui.easingCurvePicker->addItem(item); + } +} + +void Window::startAnimation() +{ + m_anim->setStartValue(QPointF(0, 0)); + m_anim->setEndValue(QPointF(100, 100)); + m_anim->setDuration(2000); + m_anim->setIterationCount(-1); // forever + m_anim->start(); +} + +void Window::curveChanged(int row) +{ + QEasingCurve::Type curveType = (QEasingCurve::Type)row; + m_anim->setEasingCurve(curveType); + m_anim->setCurrentTime(0); + + bool isElastic = curveType >= QEasingCurve::InElastic && curveType <= QEasingCurve::OutInElastic; + bool isBounce = curveType >= QEasingCurve::InBounce && curveType <= QEasingCurve::OutInBounce; + m_ui.periodSpinBox->setEnabled(isElastic); + m_ui.amplitudeSpinBox->setEnabled(isElastic || isBounce); + m_ui.overshootSpinBox->setEnabled(curveType >= QEasingCurve::InBack && curveType <= QEasingCurve::OutInBack); +} + +void Window::pathChanged(int index) +{ + m_anim->setPathType((Animation::PathType)index); +} + +void Window::periodChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setPeriod(value); + m_anim->setEasingCurve(curve); +} + +void Window::amplitudeChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setAmplitude(value); + m_anim->setEasingCurve(curve); +} + +void Window::overshootChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setOvershoot(value); + m_anim->setEasingCurve(curve); +} + diff --git a/examples/animation/easing/window.h b/examples/animation/easing/window.h new file mode 100644 index 0000000..4ba6eb6 --- /dev/null +++ b/examples/animation/easing/window.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "ui_form.h" +#include "animation.h" + +class PixmapItem : public QObject, public QGraphicsPixmapItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix) + { + } +}; + +class Window : public QWidget { + Q_OBJECT +public: + Window(QWidget *parent = 0); +private slots: + void curveChanged(int row); + void pathChanged(int index); + void periodChanged(double); + void amplitudeChanged(double); + void overshootChanged(double); + +private: + void createCurveIcons(); + void startAnimation(); + + Ui::Form m_ui; + QGraphicsScene m_scene; + PixmapItem *m_item; + Animation *m_anim; + QSize m_iconSize; + + +}; diff --git a/examples/animation/example/example.pro b/examples/animation/example/example.pro new file mode 100644 index 0000000..bc79b82 --- /dev/null +++ b/examples/animation/example/example.pro @@ -0,0 +1,12 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Thu Sep 25 14:03:47 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += mainwindow.h +SOURCES += main.cpp mainwindow.cpp diff --git a/examples/animation/example/main.cpp b/examples/animation/example/main.cpp new file mode 100644 index 0000000..d5f5607 --- /dev/null +++ b/examples/animation/example/main.cpp @@ -0,0 +1,23 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + //Q_INIT_RESOURCE(example); + QApplication app(argc, argv); + MainWindow w; + w.show(); + return app.exec(); +} + diff --git a/examples/animation/example/mainwindow.cpp b/examples/animation/example/mainwindow.cpp new file mode 100644 index 0000000..dfb5c70 --- /dev/null +++ b/examples/animation/example/mainwindow.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" + +MainWindow::MainWindow() : QMainWindow(0) +{ + // Text edit and button + listWidget = new QListWidget; + new QListWidgetItem("Rachel", listWidget); + new QListWidgetItem("Andreas", listWidget); + new QListWidgetItem("David", listWidget); + new QListWidgetItem("Olivier", listWidget); + new QListWidgetItem("Andy", listWidget); + new QListWidgetItem("Martial", listWidget); + new QListWidgetItem("Kazou", listWidget); + new QListWidgetItem("Fred", listWidget); + new QListWidgetItem("Ingrid", listWidget); + QGraphicsProxyWidget *listProxy = new QGraphicsProxyWidget; + listProxy->setWidget(listWidget); + + labelWidget = new QLabel; + QGraphicsProxyWidget *labelProxy = new QGraphicsProxyWidget; + labelProxy->setWidget(labelWidget); + labelWidget->setAttribute(Qt::WA_NoSystemBackground); + + label2Widget = new QLabel; + label2Widget->setAlignment(Qt::AlignCenter); + QGraphicsProxyWidget *label2Proxy = new QGraphicsProxyWidget; + label2Proxy->setWidget(label2Widget); + label2Widget->setAttribute(Qt::WA_NoSystemBackground); + + editWidget = new QLineEdit; + QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget; + editProxy->setWidget(editWidget); + editWidget->setAttribute(Qt::WA_NoSystemBackground); + + // Parent widget + QGraphicsWidget *widget = new QGraphicsWidget; + // Parent widget + QGraphicsWidget *widget2 = new QGraphicsWidget; + + QGraphicsLinearLayout *vLayout = new QGraphicsLinearLayout(Qt::Vertical, widget); + vLayout->addItem(listProxy); + vLayout->addItem(widget2); + widget->setLayout(vLayout); + + QPushButton *button = new QPushButton; + QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget; + buttonProxy->setWidget(button); + + QPushButton *button2 = new QPushButton; + QGraphicsProxyWidget *buttonProxy2 = new QGraphicsProxyWidget; + buttonProxy2->setWidget(button2); + + QPushButton *button3 = new QPushButton; + QGraphicsProxyWidget *buttonProxy3 = new QGraphicsProxyWidget; + buttonProxy3->setWidget(button3); + + QPushButton *button4 = new QPushButton; + QGraphicsProxyWidget *buttonProxy4 = new QGraphicsProxyWidget; + buttonProxy4->setWidget(button4); + + QGraphicsLinearLayout *hLayout = new QGraphicsLinearLayout(Qt::Horizontal, widget2); + hLayout->addItem(buttonProxy); + hLayout->addItem(buttonProxy2); + hLayout->addItem(buttonProxy3); + widget2->setLayout(hLayout); + + scene = new QGraphicsScene(0, 0, 700, 600); + scene->setBackgroundBrush(scene->palette().window()); + scene->addItem(widget); + scene->addItem(editProxy); + scene->addItem(label2Proxy); + scene->addItem(labelProxy); + scene->addItem(buttonProxy4); + + machine = new QStateMachine(); + + group = new QState(machine->rootState()); + state1 = new QState(group); + state2 = new QState(group); + state3 = new QState(group); + group->setInitialState(state1); + + machine->setInitialState(group); + + // State 1 + state1->setPropertyOnEntry(button, "text", "Edit"); + state1->setPropertyOnEntry(button2, "text", "Add"); + state1->setPropertyOnEntry(button3, "text", "Remove"); + state1->setPropertyOnEntry(button4, "text", "Accept"); + state1->addTransition(button2, SIGNAL(clicked()), state3); + state1->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 700, 560)); + state1->setPropertyOnEntry(widget, "geometry", QRectF(0, 0, 700, 600)); + state1->setPropertyOnEntry(editProxy, "opacity", double(0)); + state1->setPropertyOnEntry(labelProxy, "opacity", double(0)); + state1->setPropertyOnEntry(label2Proxy, "opacity", double(0)); + state1->setPropertyOnEntry(buttonProxy4, "opacity", double(0)); + state1->setPropertyOnEntry(labelWidget, "text", "Name : "); + state1->setPropertyOnEntry(label2Widget, "text", "Edit a contact"); + state1->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, -50, 300, 30)); + state1->setPropertyOnEntry(labelProxy, "geometry", QRectF(350, 300, 100, 30)); + state1->setPropertyOnEntry(editProxy, "geometry", QRectF(750, 300, 250, 30)); + state1->setPropertyOnEntry(buttonProxy4, "geometry", QRectF(500, 350, 80, 25)); + + // State 2 + state2->setPropertyOnEntry(button, "text", "Close Editing"); + state2->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 350, 560)); + state2->addTransition(button2, SIGNAL(clicked()), state3); + state2->addTransition(button4, SIGNAL(clicked()), state1); + + state2->setPropertyOnEntry(editProxy, "opacity", double(1)); + state2->setPropertyOnEntry(labelProxy, "opacity", double(1)); + state2->setPropertyOnEntry(label2Proxy, "opacity", double(1)); + state2->setPropertyOnEntry(buttonProxy4, "opacity", double(1)); + + state2->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, 250, 300, 30)); + state2->setPropertyOnEntry(editProxy, "geometry", QRectF(440, 300, 260, 30)); + + // State 3 + state3->setPropertyOnEntry(button4, "text", "Create New"); + state3->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 350, 560)); + state3->addTransition(button4, SIGNAL(clicked()), state1); + state3->addTransition(button, SIGNAL(clicked()), state1); + state3->setPropertyOnEntry(editProxy, "opacity", double(1)); + state3->setPropertyOnEntry(labelProxy, "opacity", double(1)); + state3->setPropertyOnEntry(label2Proxy, "opacity", double(1)); + state3->setPropertyOnEntry(buttonProxy4, "opacity", double(1)); + + state3->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, 250, 300, 30)); + state3->setPropertyOnEntry(editProxy, "geometry", QRectF(440, 300, 260, 30)); + + { + QAnimationGroup *animationGroup = new QParallelAnimationGroup; + QVariantAnimation *anim = new QPropertyAnimation(labelProxy, "opacity"); + animationGroup->addAnimation(anim); + anim = new QPropertyAnimation(label2Proxy, "geometry"); + animationGroup->addAnimation(anim); + anim = new QPropertyAnimation(editProxy, "geometry"); + animationGroup->addAnimation(anim); + anim = new QPropertyAnimation(listProxy, "geometry"); + animationGroup->addAnimation(anim); + + state1->addAnimatedTransition(button, SIGNAL(clicked()), state2, animationGroup); + } + + { + QVariantAnimation *anim; + QAnimationGroup *animationGroup = new QParallelAnimationGroup; + anim = new QPropertyAnimation(label2Proxy, "geometry"); + animationGroup->addAnimation(anim); + anim = new QPropertyAnimation(editProxy, "geometry"); + animationGroup->addAnimation(anim); + anim = new QPropertyAnimation(listProxy, "geometry"); + animationGroup->addAnimation(anim); + state2->addAnimatedTransition(button, SIGNAL(clicked()), state1, animationGroup); + } + + currentState = state1; + + view = new QGraphicsView(scene); + + setCentralWidget(view); + + state3->invokeMethodOnEntry(this, "onEnterState3"); + state2->invokeMethodOnEntry(this, "onEnterState2"); + state1->invokeMethodOnEntry(this, "onEnterState1"); + + connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*))); + connect(button3, SIGNAL(clicked()), this, SLOT(onRemoveClicked())); + + machine->start(); +} + +void MainWindow::onEnterState2() +{ + currentState = state2; + if (listWidget->currentItem()) + editWidget->setText(listWidget->currentItem()->text()); +} + +void MainWindow::onEnterState1() +{ + if (currentState == state2 && listWidget->currentItem()) + listWidget->currentItem()->setText(editWidget->text()); + if (currentState == state3 && !editWidget->text().isNull()) { + new QListWidgetItem(editWidget->text(), listWidget); + editWidget->clear(); + } + currentState = state1; +} + +void MainWindow::onEnterState3() +{ + currentState = state3; +} + +void MainWindow::onItemClicked(QListWidgetItem*) +{ + if (currentState == state2) + { + editWidget->setText(listWidget->currentItem()->text()); + editWidget->clear(); + } +} + +void MainWindow::onRemoveClicked() +{ + QListWidgetItem *listItem = listWidget->takeItem(listWidget->currentRow()); + delete listItem; +} diff --git a/examples/animation/example/mainwindow.h b/examples/animation/example/mainwindow.h new file mode 100644 index 0000000..6be7463 --- /dev/null +++ b/examples/animation/example/mainwindow.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __MAINWINDOW__H__ +#define __MAINWINDOW__H__ + +#include <QtGui> + +class MainWindow : public QMainWindow +{ +Q_OBJECT +public: + MainWindow(); + +private slots : + void onEnterState3(); + void onEnterState2(); + void onEnterState1(); + void onItemClicked(QListWidgetItem*); + void onRemoveClicked(); +private: + QListWidget *listWidget; + QLabel *labelWidget; + QLabel *label2Widget; + QLineEdit *editWidget; + QGraphicsScene *scene; + QGraphicsView *view; + QState *state1; + QState *state2; + QState *state3; + QState *currentState; + QState *group; + QStateMachine *machine; +}; + +#endif //__MAINWINDOW__H__ + diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp new file mode 100644 index 0000000..f4c754d --- /dev/null +++ b/examples/animation/moveblocks/main.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtGui> +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qstatemachine.h" +#include "qabstracttransition.h" +#include "qanimationstate.h" +#include "qpropertyanimation.h" +#include "qsequentialanimationgroup.h" +#include "qparallelanimationgroup.h" +#include "qgraphicswidget.h" +#endif +#include <time.h> + +class StateSwitchEvent: public QEvent +{ +public: + StateSwitchEvent() + : QEvent(Type(StateSwitchType)) + { + } + + StateSwitchEvent(int rand) + : QEvent(Type(StateSwitchType)), + m_rand(rand) + { + } + + enum { StateSwitchType = QEvent::User + 256 }; + + int rand() const { return m_rand; } + +private: + int m_rand; +}; + + +class QGraphicsRectWidget : public QGraphicsWidget +{ +public: + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, + QWidget *) + { + painter->fillRect(rect(), Qt::blue); + } +}; + +class StateSwitchTransition: public QAbstractTransition +{ +public: + StateSwitchTransition(int rand) + : QAbstractTransition(), + m_rand(rand) + { + } + +protected: + virtual bool eventTest(QEvent *event) const + { + return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType)) + && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand); + } + + virtual void onTransition() {} + +private: + int m_rand; +}; + +class StateSwitcher : public QState +{ + Q_OBJECT +public: + StateSwitcher(QStateMachine *machine) + : QState(machine->rootState()), m_machine(machine), + m_stateCount(0), m_lastIndex(0) + { } + + virtual void onEntry() + { + int n; + while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) + { } + m_lastIndex = n; + m_machine->postEvent(new StateSwitchEvent(n)); + } + virtual void onExit() {} + + void addState(QState *state, QAbstractAnimation *animation) { + StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); + trans->setTargetState(state); + addAnimatedTransition(trans, animation); + } + + +private: + QStateMachine *m_machine; + int m_stateCount; + int m_lastIndex; +}; + +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->setPropertyOnEntry(w1, "geometry", rect1); + result->setPropertyOnEntry(w1, "geometry", rect1); + result->setPropertyOnEntry(w2, "geometry", rect2); + result->setPropertyOnEntry(w3, "geometry", rect3); + result->setPropertyOnEntry(w4, "geometry", rect4); + + return result; +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + +#if 0 + QWidget window; + QPalette palette; + palette.setBrush(QPalette::Window, Qt::black); + window.setPalette(palette); + QPushButton *button1 = new QPushButton("A", &window); + QPushButton *button2 = new QPushButton("B", &window); + QPushButton *button3 = new QPushButton("C", &window); + QPushButton *button4 = new QPushButton("D", &window); + + button1->setObjectName("button1"); + button2->setObjectName("button2"); + button3->setObjectName("button3"); + button4->setObjectName("button4"); +#else + 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); + + QGraphicsView window(&scene); + window.setFrameStyle(0); + window.setAlignment(Qt::AlignLeft | Qt::AlignTop); + window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +#endif + QStateMachine machine; + + QState *group = new QState(); + group->setObjectName("group"); + QTimer timer; + timer.setInterval(1250); + timer.setSingleShot(true); + group->invokeMethodOnEntry(&timer, "start"); + + 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); + 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); + 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); + + QParallelAnimationGroup animationGroup; + QSequentialAnimationGroup *subGroup; + + QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + animationGroup.addAnimation(anim); + + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(100); + anim = new QPropertyAnimation(button3, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); + + 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); + + StateSwitcher *stateSwitcher = new StateSwitcher(&machine); + stateSwitcher->setObjectName("stateSwitcher"); + group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher); + stateSwitcher->addState(state1, &animationGroup); + stateSwitcher->addState(state2, &animationGroup); + stateSwitcher->addState(state3, &animationGroup); + stateSwitcher->addState(state4, &animationGroup); + stateSwitcher->addState(state5, &animationGroup); + stateSwitcher->addState(state6, &animationGroup); + stateSwitcher->addState(state7, &animationGroup); + + machine.addState(group); + machine.setInitialState(group); + machine.start(); + + + window.resize(300, 300); + window.show(); + + qsrand(time(0)); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/moveblocks/moveblocks.pro b/examples/animation/moveblocks/moveblocks.pro new file mode 100644 index 0000000..7a82ca5 --- /dev/null +++ b/examples/animation/moveblocks/moveblocks.pro @@ -0,0 +1,8 @@ +# Input +SOURCES += main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/animation/moveblocks +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS states.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/animation/moveblocks +INSTALLS += target sources diff --git a/examples/animation/padnavigator-ng/backside.ui b/examples/animation/padnavigator-ng/backside.ui new file mode 100644 index 0000000..afa488c --- /dev/null +++ b/examples/animation/padnavigator-ng/backside.ui @@ -0,0 +1,208 @@ +<ui version="4.0" > + <class>BackSide</class> + <widget class="QWidget" name="BackSide" > + <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/animation/padnavigator-ng/images/artsfftscope.png b/examples/animation/padnavigator-ng/images/artsfftscope.png Binary files differnew file mode 100644 index 0000000..b4b8775 --- /dev/null +++ b/examples/animation/padnavigator-ng/images/artsfftscope.png diff --git a/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg b/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg Binary files differnew file mode 100644 index 0000000..5bf0deb --- /dev/null +++ b/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg diff --git a/examples/animation/padnavigator-ng/images/kontact_contacts.png b/examples/animation/padnavigator-ng/images/kontact_contacts.png Binary files differnew file mode 100644 index 0000000..6fb4cc8 --- /dev/null +++ b/examples/animation/padnavigator-ng/images/kontact_contacts.png diff --git a/examples/animation/padnavigator-ng/images/kontact_journal.png b/examples/animation/padnavigator-ng/images/kontact_journal.png Binary files differnew file mode 100644 index 0000000..b1fedb6 --- /dev/null +++ b/examples/animation/padnavigator-ng/images/kontact_journal.png diff --git a/examples/animation/padnavigator-ng/images/kontact_mail.png b/examples/animation/padnavigator-ng/images/kontact_mail.png Binary files differnew file mode 100644 index 0000000..672f8fa --- /dev/null +++ b/examples/animation/padnavigator-ng/images/kontact_mail.png diff --git a/examples/animation/padnavigator-ng/images/kontact_notes.png b/examples/animation/padnavigator-ng/images/kontact_notes.png Binary files differnew file mode 100644 index 0000000..229bf73 --- /dev/null +++ b/examples/animation/padnavigator-ng/images/kontact_notes.png diff --git a/examples/animation/padnavigator-ng/images/kopeteavailable.png b/examples/animation/padnavigator-ng/images/kopeteavailable.png Binary files differnew file mode 100644 index 0000000..2eaf41a --- /dev/null +++ b/examples/animation/padnavigator-ng/images/kopeteavailable.png diff --git a/examples/animation/padnavigator-ng/images/metacontact_online.png b/examples/animation/padnavigator-ng/images/metacontact_online.png Binary files differnew file mode 100644 index 0000000..6a398dd --- /dev/null +++ b/examples/animation/padnavigator-ng/images/metacontact_online.png diff --git a/examples/animation/padnavigator-ng/images/minitools.png b/examples/animation/padnavigator-ng/images/minitools.png Binary files differnew file mode 100644 index 0000000..0248c9d --- /dev/null +++ b/examples/animation/padnavigator-ng/images/minitools.png diff --git a/examples/animation/padnavigator-ng/main.cpp b/examples/animation/padnavigator-ng/main.cpp new file mode 100644 index 0000000..5b35b62 --- /dev/null +++ b/examples/animation/padnavigator-ng/main.cpp @@ -0,0 +1,24 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include "panel.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(padnavigator); + + Panel panel(3, 3); + panel.show(); + + return app.exec(); +} diff --git a/examples/animation/padnavigator-ng/padnavigator.pro b/examples/animation/padnavigator-ng/padnavigator.pro new file mode 100644 index 0000000..0d094c6 --- /dev/null +++ b/examples/animation/padnavigator-ng/padnavigator.pro @@ -0,0 +1,24 @@ +HEADERS += \ + panel.h \ + roundrectitem.h \ + splashitem.h + +SOURCES += \ + panel.cpp \ + roundrectitem.cpp \ + splashitem.cpp \ + main.cpp + +RESOURCES += \ + padnavigator.qrc + +FORMS += \ + backside.ui + +contains(QT_CONFIG, opengl):QT += opengl + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/padnavigator +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS padnavigator.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/padnavigator +INSTALLS += target sources diff --git a/examples/animation/padnavigator-ng/padnavigator.qrc b/examples/animation/padnavigator-ng/padnavigator.qrc new file mode 100644 index 0000000..30ee8e1 --- /dev/null +++ b/examples/animation/padnavigator-ng/padnavigator.qrc @@ -0,0 +1,14 @@ +<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> + <file>images/blue_angle_swirl.jpg</file> + </qresource> +</RCC> diff --git a/examples/animation/padnavigator-ng/panel.cpp b/examples/animation/padnavigator-ng/panel.cpp new file mode 100644 index 0000000..94dbdec --- /dev/null +++ b/examples/animation/padnavigator-ng/panel.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "panel.h" +#include "roundrectitem.h" +#include "splashitem.h" +#include "ui_backside.h" + +#ifndef QT_NO_OPENGL +#include <QtOpenGL/QtOpenGL> +#else +#endif +#include <QtGui/QtGui> + +Panel::Panel(int width, int height) + : selectedIndex(0), + grid(width*height), + width(width), + height(height), + flipped(false), + flippingGroup(0), + rotationXanim(0), + rotationYanim(0) +{ + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setCacheMode(CacheBackground); + setViewportUpdateMode(FullViewportUpdate); + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg")); +#ifndef QT_NO_OPENGL + setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); +#endif + + QRectF bounds((-width / 2.0) * 150, (-height / 2.0) * 150, width * 150, height * 150); + + setScene(new QGraphicsScene(bounds, this)); + + baseItem = new RoundRectItem(bounds, QColor(226, 255, 92, 64)); + scene()->addItem(baseItem); + + QWidget *embed = new QWidget; + ui = new Ui_BackSide; + ui->setupUi(embed); + ui->hostName->setFocus(); + + backItem = new RoundRectItem(bounds, embed->palette().window(), embed); + backItem->setYRotation(180); + backItem->setParentItem(baseItem); + + selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray); + selectionItem->setParentItem(baseItem); + selectionItem->setZValue(-1); + selectionItem->setPos(posForLocation(0)); + + int currentIndex = 0; + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + RoundRectItem *item = new RoundRectItem(QRectF(-54, -54, 108, 108), + QColor(214, 240, 110, 128)); + item->setPos(posForLocation(currentIndex)); + + item->setParentItem(baseItem); + item->setFlag(QGraphicsItem::ItemIsFocusable); + grid[currentIndex++] = item; + + switch (qrand() % 9) { + case 0: item->setPixmap(QPixmap(":/images/kontact_contacts.png")); break; + case 1: item->setPixmap(QPixmap(":/images/kontact_journal.png")); break; + case 2: item->setPixmap(QPixmap(":/images/kontact_notes.png")); break; + case 3: item->setPixmap(QPixmap(":/images/kopeteavailable.png")); break; + case 4: item->setPixmap(QPixmap(":/images/metacontact_online.png")); break; + case 5: item->setPixmap(QPixmap(":/images/minitools.png")); break; + case 6: item->setPixmap(QPixmap(":/images/kontact_journal.png")); break; + case 7: item->setPixmap(QPixmap(":/images/kontact_contacts.png")); break; + case 8: item->setPixmap(QPixmap(":/images/kopeteavailable.png")); break; + default: + break; + } + + connect(item, SIGNAL(activated()), this, SLOT(flip())); + } + } + + grid.first()->setFocus(); + + connect(backItem, SIGNAL(activated()), + this, SLOT(flip())); + + splash = new SplashItem; + splash->setZValue(5); + splash->setPos(-splash->rect().width() / 2, scene()->sceneRect().top()); + scene()->addItem(splash); + + splash->grabKeyboard(); + + //initialize the position + baseItem->setYRotation(selectionItem->x()/6.); + baseItem->setXRotation(selectionItem->y()/6.); + + setWindowTitle(tr("Pad Navigator Example")); +} + +Panel::~Panel() +{ +} + +void Panel::keyPressEvent(QKeyEvent *event) +{ + if (splash->isVisible() || event->key() == Qt::Key_Return || flipped) { + QGraphicsView::keyPressEvent(event); + return; + } + + selectedIndex = (selectedIndex + grid.count() + (event->key() == Qt::Key_Right) - (event->key() == Qt::Key_Left) + + width * ((event->key() == Qt::Key_Down) - (event->key() == Qt::Key_Up))) % grid.count(); + grid[selectedIndex]->setFocus(); + + const QPointF pos = posForLocation(selectedIndex); + + const double angleY = pos.x() / 6., + angleX = pos.y() / 6.; + + QAnimationGroup *group = new QParallelAnimationGroup(); + + QVariantAnimation *anim = new QPropertyAnimation(baseItem, "xRotation"); + anim->setEndValue(angleX); + anim->setDuration(150); + anim->setEasingCurve(QEasingCurve::OutInSine); + group->addAnimation(anim); + + anim = new QPropertyAnimation(baseItem, "yRotation"); + anim->setEndValue(angleY); + anim->setDuration(150); + anim->setEasingCurve(QEasingCurve::OutInSine); + group->addAnimation(anim); + + anim = new QPropertyAnimation(selectionItem, "pos"); + anim->setEndValue(pos); + anim->setDuration(150); + anim->setEasingCurve(QEasingCurve::Linear); + group->addAnimation(anim); + + group->start(QAbstractAnimation::DeleteWhenStopped); +} + +void Panel::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); +} + +void Panel::flip() +{ + grid[selectedIndex]->setFocus(); + + if (flippingGroup == 0) { + flippingGroup = new QParallelAnimationGroup(this); + + const qreal zoomOut = qreal(.75); + + //slight scaling down while flipping + QVariantAnimation *anim = new QPropertyAnimation(baseItem, "yScale"); + anim->setKeyValueAt(qreal(.5), zoomOut); + anim->setEndValue(1); + anim->setEasingCurve(QEasingCurve::OutInSine); + anim->setDuration(500); + flippingGroup->addAnimation(anim); + + anim = new QPropertyAnimation(baseItem, "xScale"); + anim->setKeyValueAt(qreal(.5), zoomOut); + anim->setEndValue(1); + anim->setEasingCurve(QEasingCurve::OutInSine); + anim->setDuration(500); + flippingGroup->addAnimation(anim); + + rotationXanim = new QPropertyAnimation(baseItem, "xRotation"); + rotationXanim->setEndValue(0); + rotationXanim->setDuration(500); + flippingGroup->addAnimation(rotationXanim); + + rotationYanim = new QPropertyAnimation(baseItem, "yRotation"); + rotationYanim->setEndValue(180); + rotationYanim->setDuration(500); + flippingGroup->addAnimation(rotationYanim); + } + + if (flippingGroup->currentTime() != 0 && flippingGroup->direction() == QAbstractAnimation::Forward) { + flippingGroup->setDirection(QAbstractAnimation::Backward); + } else { + flippingGroup->setDirection(QAbstractAnimation::Forward); + if (flippingGroup->currentTime() == 0) { + //we always make sure when it is at the beginning + rotationXanim->setStartValue(baseItem->xRotation()); + rotationYanim->setStartValue(baseItem->yRotation()); + } + } + flippingGroup->start(); + flipped = !flipped; +} + +QPointF Panel::posForLocation(int index) const +{ + const int x = index % width, + y = index / width; + return QPointF(x * 150, y * 150) + - QPointF((width - 1) * 75, (height - 1) * 75); +} diff --git a/examples/animation/padnavigator-ng/panel.h b/examples/animation/padnavigator-ng/panel.h new file mode 100644 index 0000000..cbceed1 --- /dev/null +++ b/examples/animation/padnavigator-ng/panel.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qgraphicsview.h> +#ifdef QT_EXPERIMENTAL_SOLUTION +#include "qtgraphicswidget.h" +#else +#include <QtGui/qgraphicswidget.h> +#endif + +QT_BEGIN_NAMESPACE +class Ui_BackSide; +QT_END_NAMESPACE; + +class RoundRectItem; +class QAnimationGroup; +class QPropertyAnimation; + +class Panel : public QGraphicsView +{ + Q_OBJECT +public: + Panel(int width, int height); + ~Panel(); + +protected: + void keyPressEvent(QKeyEvent *event); + void resizeEvent(QResizeEvent *event); + +private Q_SLOTS: + void flip(); + +private: + QPointF posForLocation(int index) const; + + QGraphicsWidget *selectionItem; + QGraphicsWidget *baseItem; + RoundRectItem *backItem; + QGraphicsWidget *splash; + int selectedIndex; + + QVector<QGraphicsItem*> grid; + + int width; + int height; + bool flipped; + Ui_BackSide *ui; + + QAnimationGroup *flippingGroup; + QPropertyAnimation *rotationXanim, *rotationYanim; +}; diff --git a/examples/animation/padnavigator-ng/roundrectitem.cpp b/examples/animation/padnavigator-ng/roundrectitem.cpp new file mode 100644 index 0000000..e498538 --- /dev/null +++ b/examples/animation/padnavigator-ng/roundrectitem.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "roundrectitem.h" + +#include <QtGui/QtGui> + +RoundRectItem::RoundRectItem(const QRectF &rect, const QBrush &brush, QWidget *embeddedWidget) + : QGraphicsWidget(), + brush(brush), + proxyWidget(0), + m_rect(rect) +{ + if (embeddedWidget) { + proxyWidget = new QGraphicsProxyWidget(this); + proxyWidget->setFocusPolicy(Qt::StrongFocus); + proxyWidget->setWidget(embeddedWidget); + } +} + +void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + const bool widgetHidden = parentItem() == 0 || qAbs(static_cast<QGraphicsWidget*>(parentItem())->yRotation()) < 90; + + if (proxyWidget) { + if (widgetHidden) { + proxyWidget->hide(); + } else { + if (!proxyWidget->isVisible()) { + proxyWidget->setGeometry(boundingRect().adjusted(25, 25, -25, -25)); + proxyWidget->show(); + proxyWidget->setFocus(); + } + painter->setBrush(brush); + painter->setPen(QPen(Qt::black, 1)); + painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + painter->drawRoundRect(m_rect); + } + } else if (widgetHidden) { + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + painter->drawRoundRect(m_rect.translated(2, 2)); + + QLinearGradient gradient(m_rect.topLeft(), m_rect.bottomRight()); + const QColor col = brush.color(); + gradient.setColorAt(0, col); + gradient.setColorAt(1, col.dark(200)); + painter->setBrush(gradient); + painter->setPen(QPen(Qt::black, 1)); + painter->drawRoundRect(m_rect); + if (!pix.isNull()) { + painter->scale(qreal(1.95), qreal(1.95)); + painter->drawPixmap(-pix.width() / 2, -pix.height() / 2, pix); + } + } + +} + +QRectF RoundRectItem::boundingRect() const +{ + qreal penW = qreal(.5); + qreal shadowW = 2; + return m_rect.adjusted(-penW, -penW, penW + shadowW, penW + shadowW); +} + +void RoundRectItem::setPixmap(const QPixmap &pixmap) +{ + pix = pixmap; + if (scene() && isVisible()) + update(); +} + +void RoundRectItem::keyPressEvent(QKeyEvent *event) +{ + if (event->isAutoRepeat() || event->key() != Qt::Key_Return) { + QGraphicsWidget::keyPressEvent(event); + return; + } + + if (!proxyWidget) { + setXScale(qreal(.9)); + setYScale(qreal(.9)); + } + emit activated(); +} + +void RoundRectItem::keyReleaseEvent(QKeyEvent *event) +{ + if (event->isAutoRepeat() || event->key() != Qt::Key_Return) { + QGraphicsWidget::keyReleaseEvent(event); + return; + } + + if (!proxyWidget) { + setXScale(1); + setYScale(1); + } +} diff --git a/examples/animation/padnavigator-ng/roundrectitem.h b/examples/animation/padnavigator-ng/roundrectitem.h new file mode 100644 index 0000000..56a6d3c --- /dev/null +++ b/examples/animation/padnavigator-ng/roundrectitem.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qobject.h> +#include <QtGui/qbrush.h> +#ifdef QT_EXPERIMENTAL_SOLUTION +#include "qtgraphicswidget.h" +#else +#include <QtGui/qgraphicswidget.h> +#endif + +QT_BEGIN_NAMESPACE +class QGraphicsProxyWidget; +QT_END_NAMESPACE; + +class RoundRectItem : public QGraphicsWidget +{ + Q_OBJECT +public: + RoundRectItem(const QRectF &rect, const QBrush &brush, QWidget *embeddedWidget = 0); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + QRectF boundingRect() const; + + void setPixmap(const QPixmap &pixmap); + +Q_SIGNALS: + void activated(); + +protected: + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + +private: + QRectF m_rect; + QBrush brush; + QPixmap pix; + QGraphicsProxyWidget *proxyWidget; +}; diff --git a/examples/animation/padnavigator-ng/splashitem.cpp b/examples/animation/padnavigator-ng/splashitem.cpp new file mode 100644 index 0000000..84a8945 --- /dev/null +++ b/examples/animation/padnavigator-ng/splashitem.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "splashitem.h" + +#include <QtGui/QtGui> + +SplashItem::SplashItem(QGraphicsItem *parent) + : QGraphicsWidget(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. Please press any key to continue."); + resize(400, 175); +} + +void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setPen(QPen(Qt::black, 2)); + painter->setBrush(QColor(245, 245, 255, 220)); + painter->setClipRect(rect()); + painter->drawRoundRect(3, -100 + 3, 400 - 6, 250 - 6); + + QRectF textRect = rect().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); +} + +void SplashItem::keyPressEvent(QKeyEvent * /* event */) +{ + QVariantAnimation *anim = new QPropertyAnimation(this, "pos"); + anim->setEndValue(QPointF(x(), scene()->sceneRect().top() - rect().height())); + anim->setDuration(350); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + anim = new QPropertyAnimation(this, "opacity"); + anim->setEndValue(0); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + connect(anim, SIGNAL(finished()), SLOT(close())); +} diff --git a/examples/animation/padnavigator-ng/splashitem.h b/examples/animation/padnavigator-ng/splashitem.h new file mode 100644 index 0000000..6428b69 --- /dev/null +++ b/examples/animation/padnavigator-ng/splashitem.h @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qobject.h> +#ifdef QT_EXPERIMENTAL_SOLUTION +#include "qtgraphicswidget.h" +#else +#include <QtGui/qgraphicswidget.h> +#endif + +class SplashItem : public QGraphicsWidget +{ + Q_OBJECT +public: + SplashItem(QGraphicsItem *parent = 0); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +protected: + void keyPressEvent(QKeyEvent *event); + +private: + QString text; +}; diff --git a/examples/animation/photobrowser/main.cpp b/examples/animation/photobrowser/main.cpp new file mode 100644 index 0000000..98f2a9e --- /dev/null +++ b/examples/animation/photobrowser/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "river.h" +#include "menu.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + if (app.arguments().size() == 1) { + qWarning("you have to specifiy a path to look for the photos"); + return 0; + } + + + QGraphicsScene scene; + scene.setSceneRect(QRectF(QPointF(), River::fixedSize())); + + QGraphicsView view(&scene); + view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + const int fw = view.frameWidth() * 2; + view.setFixedSize(River::fixedSize() + QSize(fw,fw)); + + River river(app.arguments()[1]); + scene.addItem(&river); + + Menu menu(&river); + menu.addAction(QLatin1String("River Mode"), &river, SLOT(setRiverMode())); + menu.addAction(QLatin1String("Grid Mode"), &river, SLOT(setGridMode())); + menu.addAction(QLatin1String("Cover Flow"), &river, SLOT(setCoverMode())); + menu.addAction(QLatin1String("Hide Menu"), &menu, SLOT(hide())); + menu.addAction(QLatin1String("Exit"), &app, SLOT(quit())); + menu.setZValue(2); + menu.setFocus(); + + river.menu = &menu; + view.show(); + + return app.exec(); +} diff --git a/examples/animation/photobrowser/menu.cpp b/examples/animation/photobrowser/menu.cpp new file mode 100644 index 0000000..d4efe9c --- /dev/null +++ b/examples/animation/photobrowser/menu.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "menu.h" + +Menu::Menu(QGraphicsItem *parent) : QGraphicsWidget(parent), m_selected(0) +{ + setFlag(QGraphicsItem::ItemIsFocusable); + m_selection = new QGraphicsRectItem(this); + QLinearGradient linearGrad(QPointF(0, 0), QPointF(0,50)); + linearGrad.setColorAt(0, QColor(255,255,255,128)); + linearGrad.setColorAt(1, QColor(255,255,255,16)); + m_selection->setBrush(linearGrad); + m_selection->setPen(QPen(Qt::transparent)); +} + +Menu::~Menu() +{ +} + + +MenuAction *Menu::addAction(const QString &text, QObject *receiver, const char* slot) +{ + MenuAction *action = new MenuAction(text, this); + if (!m_actions.isEmpty()) { + MenuAction *last = m_actions.last(); + action->setPos(last->pos() + last->boundingRect().bottomLeft()); + } + m_actions.append(action); + if (m_selection->boundingRect().width() < action->boundingRect().width()) + m_selection->setRect(action->boundingRect()); + + QObject::connect(action, SIGNAL(triggered()), receiver, slot); + return action; +} + +QRectF Menu::boundingRect() const +{ + QRectF res; + foreach (MenuAction *a, m_actions) + res |= a->boundingRect(); + return res; +} + +void Menu::keyPressEvent (QKeyEvent * event) +{ + switch (event->key()) { + case Qt::Key_Escape: + hide(); + break; + case Qt::Key_Up: + m_selected -= 2; + case Qt::Key_Down: + if (!m_actions.isEmpty()) { + m_selected = (m_selected + 1 + m_actions.count()) % m_actions.count(); + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::Position); + anim->setEndValue(m_actions.at(m_selected)->pos()); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + break; + case Qt::Key_Enter: + case Qt::Key_Return: + if (!m_actions.isEmpty()) { + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::RotationX); + anim->setEndValue(m_selection->xRotation() < 180 ? qreal(360) : qreal(0)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + m_actions.at(m_selected)->trigger(); + hide(); + } + break; + default: + QGraphicsItem::keyPressEvent(event); + } +} + +void Menu::show() +{ + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity); + anim->setEndValue(qreal(1.)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX); + anim->setEndValue(qreal(1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY); + anim->setEndValue(qreal(1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + setFocus(); +} + +void Menu::hide() +{ + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX); + anim->setEndValue(qreal(.1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY); + anim->setEndValue(qreal(.1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(this, QItemAnimation::Opacity); + anim->setEndValue(qreal(0)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + parentItem()->setFocus(); +} + + +MenuAction::MenuAction(const QString &text, Menu * parent) + : QGraphicsTextItem(text,parent) +{ + QFont f = font(); + f.setPointSize(18); + setFont(f); + setDefaultTextColor(Qt::white); +} + +void MenuAction::trigger() +{ + emit triggered(); +} diff --git a/examples/animation/photobrowser/menu.h b/examples/animation/photobrowser/menu.h new file mode 100644 index 0000000..9514cfe --- /dev/null +++ b/examples/animation/photobrowser/menu.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __MENU__H__ +#define __MENU__H__ + +#include <QtGui> + +class MenuAction; + +class Menu : public QGraphicsWidget +{ + Q_OBJECT +public: + Menu(QGraphicsItem *parent); + ~Menu(); + + MenuAction *addAction(const QString&, QObject *receiver = 0, const char* slot = 0 ); + + QRectF boundingRect() const; + void keyPressEvent ( QKeyEvent * event ); +public slots: + void show(); + void hide(); +private: + QList<MenuAction*> m_actions; + QGraphicsRectItem *m_selection; + int m_selected; +}; + +class MenuAction : public QGraphicsTextItem +{ + Q_OBJECT +public: + MenuAction(const QString &text, Menu * parent); + void trigger(); +signals: + void triggered(); +}; + + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/photobrowser.pro b/examples/animation/photobrowser/photobrowser.pro new file mode 100644 index 0000000..21f03d6 --- /dev/null +++ b/examples/animation/photobrowser/photobrowser.pro @@ -0,0 +1,17 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ven. 22. août 13:09:33 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + river.cpp \ + riveritem.cpp \ + menu.cpp +HEADERS += river.h \ + riveritem.h \ + menu.h diff --git a/examples/animation/photobrowser/river.cpp b/examples/animation/photobrowser/river.cpp new file mode 100644 index 0000000..f3dd0746 --- /dev/null +++ b/examples/animation/photobrowser/river.cpp @@ -0,0 +1,561 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "river.h" +#include "riveritem.h" + +#include "qvariantanimation.h" + +#include <QtCore/QDebug> +#include <QtGui/QKeyEvent> +#include <QtGui/QGraphicsScene> +#include <QtGui/QPainter> + + +#define GRID_ROW_COUNT 3 +#define GRID_COLUMN_COUNT 2 +#define GRID_DIMENSIONS (GRID_ROW_COUNT * GRID_COLUMN_COUNT) +#define ITEM_COUNT 12 + +#define RIVER_MAGNIFY(ITEM) (qreal(0.50) + (ITEM)->zValue()*2 ) +#define GRID_MAGNIFY qreal(1.5) +#define GRID_CURRENT_MAGNIFY 2 + +River::River(const QString &path) : +m_images(QDir(path).entryInfoList(QStringList() << QLatin1String("*.jpg") << QLatin1String("*.png"))), +m_currentImage(0), m_mode(RiverMode), m_selectedItem(-1) , m_topLeftIndex(-1) +{ + setFocusPolicy(Qt::StrongFocus); + setGeometry(QRectF( QPointF(), fixedSize())); + + + for (int i = 0; i < ITEM_COUNT; ++i) { + RiverItem * item = new RiverItem(this); + + //here we also randomize the x position (not when looping) + const int x = qrand() % fixedSize().width(); + item->setPos(x, -1); + + m_items.insert(m_currentImage, item); + addUnusedRiverItem(item); + } + +} + +QPointF River::gridItemPosition(int row, int col) const +{ + if (col < 0) { + col += GRID_COLUMN_COUNT; + row --; + } + return QPointF(rect().width()*(col*2 + 1)/(GRID_COLUMN_COUNT*2), + rect().height()*(row*2 + 1)/(GRID_ROW_COUNT*2)); +} + +QPixmap River::pixmap(int index) const +{ + if (index < 0 || index >= m_images.size()) + return QPixmap(); + + if (m_pixmaps.size() <= index) { + m_pixmaps.resize(index+1); + } + + if (m_pixmaps.at(index).isNull()) { + m_pixmaps[index] = QPixmap(m_images.at(index).absoluteFilePath()); + } + + return m_pixmaps.at(index); +} + +void River::addUnusedRiverItem(RiverItem * item) +{ + if (m_images.isEmpty()) + return; + + QRectF realItemRect = item->mapToParent(item->boundingRect()).boundingRect(); + + int y = item->pos().y(); + int x = item->pos().x(); + if (x >= fixedSize().width() || x < -realItemRect.width() || y < 0) { + //we set the new pixmap + + m_items.remove(m_items.key(item)); + + while (m_items.contains(m_currentImage)) + m_currentImage = (m_currentImage + 1 ) % m_images.size(); + + item->setPixmap(pixmap(m_currentImage)); + + m_items.insert(m_currentImage, item); + //this manages looping as well + m_currentImage = (m_currentImage + 1 ) % m_images.size(); + + item->setZValue(qreal(qrand()%100)/200.0); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + realItemRect = item->mapToParent(item->boundingRect()).boundingRect(); + + y = -realItemRect.y() + qrand() % (fixedSize().height() - int(realItemRect.height())); + if (x >= fixedSize().width()) { + x = -realItemRect.width()/2; + } + } + + item->setPos(x, y); + + const QPointF target(QPointF(fixedSize().width() + realItemRect.width()/2, y)); + + const int distance = target.x() - x; + + const int duration = (40 - 50*item->zValue() ) * distance; + QItemAnimation *a = new QItemAnimation(item, QItemAnimation::Position, scene()); + a->setEndValue(target); + a->setDuration(duration); + a->start(QAbstractAnimation::DeleteWhenStopped); + connect(a, SIGNAL(finished()), SLOT(animationFinished())); +} + +void River::animationFinished() +{ + QItemAnimation *anim = qobject_cast<QItemAnimation*>(sender()); + if (!anim || anim->propertyName() != QItemAnimation::Position) + return; + + /*RiverItem *item = static_cast<RiverItem*>(anim->graphicsItem()); + if (m_mode != RiverMode) {*/ + /*int key = m_items.key(item); + if (key < m_topLeftIndex || key >= m_topLeftIndex + GRID_DIMENSIONS) { + delete item; + m_items.remove(key); + }*/ + //return; + + //} + + addUnusedRiverItem(static_cast<RiverItem*>(anim->targetItem())); +} + +void River::switchPaused() +{ + const bool paused = m_pausedAnimations.isEmpty(); + if (paused) + m_pausedAnimations = scene()->findChildren<QItemAnimation*>(); + + foreach(QItemAnimation *anim, m_pausedAnimations) { + if (paused) + anim->pause(); + else + anim->resume(); + } + + if (!paused) + m_pausedAnimations.clear(); +} + +void River::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + painter->fillRect(option->rect, Qt::black); +} + +void River::setMode(Mode m) +{ + if (m_mode == m) + return; + + Mode oldMode = m_mode; + m_mode = m; + switch(m) + { + case RiverMode: + m_mode = oldMode; //some animation may be stopt, and we don't want that animationFinished we were in that mode yet + foreach (RiverItem *item, m_items) { + const int x = qrand() % fixedSize().width(); + const int y = qrand() % fixedSize().width(); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(QPointF(x, y)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + connect(anim, SIGNAL(finished()), SLOT(animationFinished())); + } + m_mode = m; + break; + + case GridMode: + + if (oldMode == GridFullScreenMode) { + currentItem()->setFullScreen(false, GRID_CURRENT_MAGNIFY); + } else { + m_topLeftIndex = -GRID_DIMENSIONS; + foreach (RiverItem *item, m_items) { + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + adjustGrid(m_currentImage - GRID_DIMENSIONS + 1); + setCurrentItem(m_topLeftIndex); + } + break; + case GridFullScreenMode: + //let's put the current item fullscreen + currentItem()->setFullScreen(true, GRID_CURRENT_MAGNIFY); + break; + case CoverMode: + m_gridItem = m_items.values(); + setCurrentItem(m_gridItem.count()/2); + default: + break; + } +} + +River::Mode River::mode() const +{ + return m_mode; +} + +QSize River::fixedSize() +{ + return QSize(352, 416); +} + +//the name of this method is not that good... +void River::makeCenterAvailable(qreal size) +{ + QRectF center(QPointF(), QSizeF(size, size)); + center.moveCenter(rect().center()); + + const QList<QGraphicsItem*> list = scene()->items(center); + + foreach(QGraphicsItem *item, m_items) { + + if (!list.contains(item)) + continue; + + QPointF pos = item->pos(); + + if (pos.y() < rect().center().y()) { + //item is above center + pos.ry() = center.top() - item->boundingRect().height() - 1; + } else { + //item is below the center + pos.ry() = center.bottom() + 1; + } + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(pos); + anim->setDuration(150); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } +} + + +//this is there just to test small interaction +void River::keyPressEvent ( QKeyEvent * keyEvent ) +{ + switch(keyEvent->key()) + { + case Qt::Key_O: + { + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity, scene()); + anim->setDuration(2000); + anim->setEndValue(qreal(.5)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + break; + case Qt::Key_N: + //that's a test + makeCenterAvailable(60); + break; + case Qt::Key_P: + switchPaused(); + break; + case Qt::Key_V: + setMode(GridMode); + break; + case Qt::Key_R: + setMode(RiverMode); + break; + case Qt::Key_C: + setMode(CoverMode); + break; + case Qt::Key_Return: + case Qt::Key_Enter: + if (m_mode == RiverMode) { + setMode(GridMode); + } else if (m_mode == GridMode) { + setMode(GridFullScreenMode); + } else if (m_mode == GridFullScreenMode) { + setMode(GridMode); + } + break; + case Qt::Key_Escape: + if (m_mode == GridFullScreenMode) { + setMode(GridMode); + } else if (m_mode == GridMode || m_mode == CoverMode) { + setMode(RiverMode); + } else if (m_mode == RiverMode) { + menu->show(); + } + break; + case Qt::Key_Right: + if (m_mode == GridMode) { + navigateBy(+1); + } else if (m_mode == CoverMode) { + setCurrentItem(m_selectedItem + 1); + } + break; + case Qt::Key_Left: + if (m_mode == GridMode) { + navigateBy(-1); + } else if (m_mode == CoverMode) { + setCurrentItem(m_selectedItem - 1); + } + break; + case Qt::Key_Down: + if (m_mode == GridMode) { + navigateBy(GRID_COLUMN_COUNT); + } + break; + case Qt::Key_Up: + if (m_mode == GridMode) { + navigateBy(-GRID_COLUMN_COUNT); + } + break; +// case Qt::Key_PageUp: + case Qt::Key_M: + menu->show(); + break; + case Qt::Key_Space: + if (m_mode == GridMode) { + RiverItem *item = currentItem(); + if(!item) + break; + + //stupid sequence. + QPointF pos = item->pos(); + QAnimationGroup *group = new QSequentialAnimationGroup(); + //item->animator()->beginSequence(); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(pos); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(qreal(1.)); + anim->setDuration(500); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(qreal(1.)); + anim->setDuration(500); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::RotationX, scene()); + anim->setEndValue(qreal(0)); + group->addAnimation(anim); + group->start(QAbstractAnimation::DeleteWhenStopped); + } + default: + break; + } + + QGraphicsItem::keyPressEvent(keyEvent); +} + + +void River::setGridMode() +{ + setMode(GridMode); +} + +void River::setRiverMode() +{ + setMode(RiverMode); +} + +void River::setCoverMode() +{ + setMode(CoverMode); +} + + +void River::adjustGrid(int newTopLeft) +{ + for (int i = newTopLeft ; i < newTopLeft + GRID_DIMENSIONS; i++) { + if (!m_items.contains(i)) { + RiverItem *item = createItem(i); + int row = (i - m_topLeftIndex) / GRID_COLUMN_COUNT; + int col = (i - m_topLeftIndex) % GRID_COLUMN_COUNT; + item->setPos(gridItemPosition(row, col)); + item->setXScale(0); + item->setYScale(0); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + } + newTopLeft = newTopLeft - newTopLeft % GRID_COLUMN_COUNT; + + QHash<int, RiverItem *>::iterator it = m_items.begin(); + while (it != m_items.constEnd()) { + const int imageIdx = it.key(); + RiverItem *item = *it; + QSizeF itemSize = item->boundingRect().size(); + if ((imageIdx >= newTopLeft && imageIdx < newTopLeft + GRID_DIMENSIONS) + || boundingRect().adjusted(-itemSize.width()/2, -itemSize.height()/2, itemSize.width()/2, itemSize.height()/2) + .contains(item->pos())) { + int row = (imageIdx-newTopLeft) / GRID_COLUMN_COUNT; + int col = (imageIdx-newTopLeft) % GRID_COLUMN_COUNT; + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(gridItemPosition(row, col)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + ++it; + } else { + ++it; /* ### ideally we should remove the items, but this cause the photobrowser to crash + because the QItemAnimations are not notified the item is deleted + delete item; + it = m_items.erase(it); + */ + } + } + + m_topLeftIndex = newTopLeft; +} + + +RiverItem *River::createItem(int imageIndex) +{ + Q_ASSERT(!m_items.contains(imageIndex)); + RiverItem * item = new RiverItem(this); + item->setPixmap(pixmap(imageIndex)); + m_items.insert(imageIndex,item); + return item; +} + +void River::setCurrentItem(int newCurrentItem) +{ + if (m_mode == CoverMode) + { + m_selectedItem = newCurrentItem; + for (int i = 0; i < m_gridItem.count(); i++) { + QVariantAnimation *anim; + RiverItem *item = m_gridItem.at(i); + + qreal rotation = 0; + qreal width = boundingRect().width() / 2; + qreal x = width; + qreal scale = 3; + qreal z = 1; + qreal y = boundingRect().height()/2; + + if (i < newCurrentItem - 4) { + item->setVisible(false); + item->setPos(QPointF(0, y)); + continue; + } else if(i > newCurrentItem + 4) { + item->setVisible(false); + item->setPos(QPointF(boundingRect().width(), y)); + continue; + } else if (i < newCurrentItem) { + x = (i - newCurrentItem + 4) * width/7; + rotation = -75; + scale = 2; + z = 1.+qreal(i-newCurrentItem)/10.; + } else if (i > newCurrentItem) { + x = width + (i - newCurrentItem + 3) * width/7; + rotation = 75; + scale = 2; + z = 1.-qreal(i-newCurrentItem)/8.; + } + + item->setVisible(true); + item->setZValue(z); + + anim = new QItemAnimation(item, QItemAnimation::RotationY, scene()); + anim->setEndValue(rotation); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(scale); + anim->start(QVariantAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(scale); + anim->start(QVariantAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(QPointF(x,y)); + anim->start(QVariantAnimation::DeleteWhenStopped); + } + return; + } + + + //deselect the current item + if (m_selectedItem >= 0 && m_items.contains(m_selectedItem)) { + RiverItem *item = m_items.value(m_selectedItem); + item->setZValue(qreal(qrand()%100)/200.0); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + + if (newCurrentItem < 0) { + m_selectedItem = newCurrentItem; + return; + } + + //ensure visible; + if (newCurrentItem < m_topLeftIndex) { + adjustGrid(newCurrentItem); + } else if (newCurrentItem >= m_topLeftIndex + GRID_DIMENSIONS) { + adjustGrid(newCurrentItem - GRID_DIMENSIONS + GRID_COLUMN_COUNT); + } + + //select the new one + m_selectedItem = newCurrentItem; + RiverItem *item = currentItem(); + Q_ASSERT(item); + item->setZValue(1); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_CURRENT_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_CURRENT_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); +} + +void River::navigateBy(int offset) +{ + int newSelection = m_selectedItem + offset; + const int imageCount = m_images.size(); + while (newSelection < 0) + newSelection += imageCount; + newSelection %= imageCount; + setCurrentItem(newSelection); +} diff --git a/examples/animation/photobrowser/river.h b/examples/animation/photobrowser/river.h new file mode 100644 index 0000000..25bf62a --- /dev/null +++ b/examples/animation/photobrowser/river.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __RIVER__H__ +#define __RIVER__H__ + +#include <QtCore/QDirIterator> +#include <QtGui/QGraphicsWidget> + +#include "menu.h" + +class RiverItem; + +class River : public QGraphicsWidget +{ + Q_OBJECT +public: + enum Mode + { + RiverMode, + GridMode, + GridFullScreenMode, + CoverMode + }; + + River(const QString &path); + void addUnusedRiverItem(RiverItem * item); + + static QSize fixedSize(); + + void switchPaused(); + + void setMode(Mode m); + Mode mode() const; + + Menu *menu; + +protected: + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void keyPressEvent ( QKeyEvent * keyEvent ); + void makeCenterAvailable(qreal size); + QPointF gridItemPosition(int row, int col) const; + QPixmap pixmap(int index) const; + +protected slots: + void animationFinished(); +public slots: + void setRiverMode(); + void setGridMode(); + void setCoverMode(); + +private: + const QFileInfoList m_images; + int m_currentImage; + mutable QVector<QPixmap> m_pixmaps; + QHash<int, RiverItem*> m_items; + QList<RiverItem*> m_gridItem; + QList<QItemAnimation*> m_pausedAnimations; + Mode m_mode; + + void adjustGrid(int topRight); + RiverItem *currentItem() { return m_items.value(m_selectedItem); } + RiverItem *createItem(int imageIndex); + void setCurrentItem(int currentItem); + void navigateBy(int offset); + + int m_selectedItem; + int m_topLeftIndex; + +}; + + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/riveritem.cpp b/examples/animation/photobrowser/riveritem.cpp new file mode 100644 index 0000000..f6523a7 --- /dev/null +++ b/examples/animation/photobrowser/riveritem.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "riveritem.h" +#include "river.h" + +RiverItem::RiverItem(QGraphicsItem *parent) : QGraphicsPixmapItem(parent), m_fullscreen(false) +{ + setCacheMode(DeviceCoordinateCache); +} + +RiverItem::~RiverItem() +{ +} + +void RiverItem::setPixmap(const QPixmap &pix) +{ + const QSize oldSize = pixmap().size(); + const QSize newSize = pix.size(); + QGraphicsPixmapItem::setPixmap(pix); + + if (newSize != oldSize) { + setOffset(-newSize.width()/2, -newSize.height()/2); + const qreal scaleFactor = qreal(River::fixedSize().height())/(qreal(pix.height()*7)); + setTransform(QTransform().scale(scaleFactor, scaleFactor)); + prepareGeometryChange(); + } +} + + +void RiverItem::setFullScreen(bool b, qreal originScaleFactor) +{ + if (m_fullscreen == b) + return; + + m_fullscreen = b; + + QPointF newPos; + qreal rotationZ; + qreal scaleX, scaleY; + + if (b) { + const QSizeF basePixmapSize = transform().map(boundingRect()).boundingRect().size(); + + newPos = parentItem()->boundingRect().center(); + rotationZ = 90; + scaleY = qreal(River::fixedSize().width()) / basePixmapSize.height() * yScale(); + scaleX = qreal(River::fixedSize().height()) / basePixmapSize.width() * xScale(); + + if (m_nonFSPos.isNull()) { + m_nonFSPos = pos(); //let's save our current (non fullscreen) position + } + + } else { + Q_ASSERT(!m_nonFSPos.isNull()); + rotationZ = 0; + scaleX = originScaleFactor; + scaleY = originScaleFactor; + newPos = m_nonFSPos; + } + + QAnimationGroup *group = new QParallelAnimationGroup(scene()); + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Position); + anim->setEndValue(newPos); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::RotationZ); + anim->setEndValue(rotationZ); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::ScaleFactorX); + anim->setEndValue(scaleX); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::ScaleFactorY); + anim->setEndValue(scaleY); + group->addAnimation(anim); + group->start(QAbstractAnimation::DeleteWhenStopped); +} + +void RiverItem::mousePressEvent(QGraphicsSceneMouseEvent*) +{ + //just let it rotate on itself + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::RotationY); + anim->setEndValue(yRotation() < 180 ? 360 : 0); + anim->setDuration(500); + anim->start(QAbstractAnimation::DeleteWhenStopped); +} + + diff --git a/examples/animation/photobrowser/riveritem.h b/examples/animation/photobrowser/riveritem.h new file mode 100644 index 0000000..39fdcc2 --- /dev/null +++ b/examples/animation/photobrowser/riveritem.h @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __RIVERITEM__H__ +#define __RIVERITEM__H__ + +#include <QtGui/QGraphicsPixmapItem> + +class RiverItemAnimator; + +class RiverItem : public QGraphicsPixmapItem +{ +public: + RiverItem(QGraphicsItem *parent); + ~RiverItem(); + + void setPixmap(const QPixmap &); + void setFullScreen(bool b, qreal originScaleFactor); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); + +private: + QPointF m_nonFSPos; //to save the position when not in fullscreen + bool m_fullscreen; +}; + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/piemenu/main.cpp b/examples/animation/piemenu/main.cpp new file mode 100644 index 0000000..28f62d0 --- /dev/null +++ b/examples/animation/piemenu/main.cpp @@ -0,0 +1,26 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#include "scene.h" +#include "qgraphicspiemenu.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + Scene scene; + + QGraphicsView view(&scene); + view.show(); + + return app.exec(); +} diff --git a/examples/animation/piemenu/piemenu.pro b/examples/animation/piemenu/piemenu.pro new file mode 100644 index 0000000..4d7a067 --- /dev/null +++ b/examples/animation/piemenu/piemenu.pro @@ -0,0 +1,8 @@ +SOURCES += \ + main.cpp \ + qgraphicspiemenu.cpp \ + scene.cpp +HEADERS += \ + qgraphicspiemenu.h \ + qgraphicspiemenu_p.h \ + scene.h diff --git a/examples/animation/piemenu/qgraphicspiemenu.cpp b/examples/animation/piemenu/qgraphicspiemenu.cpp new file mode 100644 index 0000000..c913423 --- /dev/null +++ b/examples/animation/piemenu/qgraphicspiemenu.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicspiemenu.h" +#include "qgraphicspiemenu_p.h" + +#include <QtGui/qaction.h> + +QGraphicsPieMenu::QGraphicsPieMenu(QGraphicsItem *parent) + : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate) +{ + d_ptr->q_ptr = this; + d_ptr->machine = new QStateMachine(); + d_ptr->popupState = new QState(d_ptr->machine->rootState()); + d_ptr->machine->setInitialState(d_ptr->popupState); + d_ptr->menuAction = new QAction(this); +} + +QGraphicsPieMenu::QGraphicsPieMenu(const QString &title, QGraphicsItem *parent) + : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate) +{ + d_ptr->q_ptr = this; + d_ptr->machine = new QStateMachine(); + d_ptr->popupState = new QState(d_ptr->machine->rootState()); + d_ptr->machine->setInitialState(d_ptr->popupState); + d_ptr->menuAction = new QAction(this); + setTitle(title); +} + +QGraphicsPieMenu::QGraphicsPieMenu(const QIcon &icon, const QString &title, QGraphicsItem *parent) + : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate) +{ + d_ptr->q_ptr = this; + d_ptr->machine = new QStateMachine(); + d_ptr->popupState = new QState(d_ptr->machine->rootState()); + d_ptr->machine->setInitialState(d_ptr->popupState); + d_ptr->menuAction = new QAction(this); + setIcon(icon); + setTitle(title); +} + +QGraphicsPieMenu::~QGraphicsPieMenu() +{ + delete d_ptr; +} + +QAction *QGraphicsPieMenu::addAction(const QString &text) +{ + QAction *action = new QAction(text, this); + addAction(action); + return action; +} + +QAction *QGraphicsPieMenu::addAction(const QIcon &icon, const QString &text) +{ + QAction *action = new QAction(icon, text, this); + addAction(action); + return action; +} + +QAction *QGraphicsPieMenu::addAction(const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut) +{ + QAction *action = new QAction(text, this); + action->setShortcut(shortcut); + connect(action, SIGNAL(triggered(bool)), receiver, member); + addAction(action); + return action; +} + +QAction *QGraphicsPieMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut) +{ + QAction *action = new QAction(icon, text, this); + action->setShortcut(shortcut); + connect(action, SIGNAL(triggered(bool)), receiver, member); + addAction(action); + return action; +} + +QAction *QGraphicsPieMenu::addMenu(QGraphicsPieMenu *menu) +{ + QAction *action = menu->menuAction(); + addAction(action); + return action; +} + +QGraphicsPieMenu *QGraphicsPieMenu::addMenu(const QString &title) +{ + QGraphicsPieMenu *menu = new QGraphicsPieMenu(title, this); + addMenu(menu); + return menu; +} + +QGraphicsPieMenu *QGraphicsPieMenu::addMenu(const QIcon &icon, const QString &title) +{ + QGraphicsPieMenu *menu = new QGraphicsPieMenu(icon, title, this); + addMenu(menu); + return menu; +} + +QAction *QGraphicsPieMenu::addSeparator() +{ + QAction *action = new QAction(this); + action->setSeparator(true); + addAction(action); + return action; +} + +QAction *QGraphicsPieMenu::insertMenu(QAction *before, QGraphicsPieMenu *menu) +{ + QAction *action = menu->menuAction(); + insertAction(before, action); + return action; +} + +QAction *QGraphicsPieMenu::insertSeparator(QAction *before) +{ + QAction *action = new QAction(this); + action->setSeparator(true); + insertAction(before, action); + return action; +} + +QAction *QGraphicsPieMenu::menuAction() const +{ + return d_func()->menuAction; +} + +bool QGraphicsPieMenu::isEmpty() const +{ + // ### d->actions + QList<QAction *> actionList = actions(); + bool ret = true; + for (int i = 0; ret && i < actionList.size(); ++i) { + const QAction *action = actionList.at(i); + if (!action->isSeparator() && action->isVisible()) { + ret = false; + break; + } + } + return ret; +} + +void QGraphicsPieMenu::clear() +{ + // ### d->actions + QList<QAction *> actionList = actions(); + for(int i = 0; i < actionList.size(); i++) { + QAction *action = actionList.at(i); + removeAction(action); + if (action->parent() == this && action->associatedGraphicsWidgets().isEmpty()) + delete action; + } +} + +void QGraphicsPieMenu::popup(const QPointF &pos) +{ + Q_UNUSED(pos); + Q_D(QGraphicsPieMenu); + d->machine->start(); +} + +QAction *QGraphicsPieMenu::exec() +{ + return exec(pos()); +} + +QAction *QGraphicsPieMenu::exec(const QPointF &pos) +{ + Q_UNUSED(pos); + return 0; +} + +QAction *QGraphicsPieMenu::exec(QList<QAction *> actions, const QPointF &pos) +{ + QGraphicsPieMenu menu; + for (QList<QAction *>::ConstIterator it = actions.constBegin(); it != actions.constEnd(); ++it) + menu.addAction(*it); + return menu.exec(pos); +} + +QString QGraphicsPieMenu::title() const +{ + Q_D(const QGraphicsPieMenu); + return d->title; +} + +void QGraphicsPieMenu::setTitle(const QString &title) +{ + Q_D(QGraphicsPieMenu); + d->title = title; + updateGeometry(); +} + +QIcon QGraphicsPieMenu::icon() const +{ + Q_D(const QGraphicsPieMenu); + return d->icon; +} + +void QGraphicsPieMenu::setIcon(const QIcon &icon) +{ + Q_D(QGraphicsPieMenu); + d->icon = icon; + updateGeometry(); +} + +QSizeF QGraphicsPieMenu::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +{ + Q_UNUSED(which); + Q_UNUSED(constraint); + return QSizeF(1, 1); +} diff --git a/examples/animation/piemenu/qgraphicspiemenu.h b/examples/animation/piemenu/qgraphicspiemenu.h new file mode 100644 index 0000000..68b4ba9 --- /dev/null +++ b/examples/animation/piemenu/qgraphicspiemenu.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSPIEMENU_H +#define QGRAPHICSPIEMENU_H + +#include <QtGui/qgraphicswidget.h> + +class QGraphicsPieMenuPrivate; +class QGraphicsPieMenu : public QGraphicsWidget +{ + Q_OBJECT +public: + QGraphicsPieMenu(QGraphicsItem *parent = 0); + QGraphicsPieMenu(const QString &title, QGraphicsItem *parent = 0); + QGraphicsPieMenu(const QIcon &icon, const QString &title, QGraphicsItem *parent = 0); + ~QGraphicsPieMenu(); + +#ifdef Q_NO_USING_KEYWORD + inline void addAction(QAction *action) { QGraphicsWidget::addAction(action); } +#else + using QGraphicsWidget::addAction; +#endif + QAction *addAction(const QString &text); + QAction *addAction(const QIcon &icon, const QString &text); + QAction *addAction(const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut = 0); + QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut = 0); + QAction *addMenu(QGraphicsPieMenu *menu); + QGraphicsPieMenu *addMenu(const QString &title); + QGraphicsPieMenu *addMenu(const QIcon &icon, const QString &title); + QAction *addSeparator(); + QAction *insertMenu(QAction *before, QGraphicsPieMenu *menu); + QAction *insertSeparator(QAction *before); + + QAction *menuAction() const; + + bool isEmpty() const; + void clear(); + + void popup(const QPointF &pos); + QAction *exec(); + QAction *exec(const QPointF &pos); + static QAction *exec(QList<QAction *> actions, const QPointF &pos); + + QString title() const; + void setTitle(const QString &title); + + QIcon icon() const; + void setIcon(const QIcon &icon); + +Q_SIGNALS: + void aboutToShow(); + void aboutToHide(); + void triggered(QAction *action); + void hovered(QAction *action); + +protected: + QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + +private: + Q_DISABLE_COPY(QGraphicsPieMenu) + Q_DECLARE_PRIVATE(QGraphicsPieMenu) + QGraphicsPieMenuPrivate *d_ptr; +}; + +#endif diff --git a/examples/animation/piemenu/qgraphicspiemenu_p.h b/examples/animation/piemenu/qgraphicspiemenu_p.h new file mode 100644 index 0000000..87a749c --- /dev/null +++ b/examples/animation/piemenu/qgraphicspiemenu_p.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSPIEMENU_P_H +#define QGRAPHICSPIEMENU_P_H + +#include "qgraphicspiemenu.h" +#include "qgraphicspiemenusection_p.h" + +#include <QtGui/qicon.h> +#include <QtCore/qstate.h> +#include <QtCore/qtransition.h> +#include <QtCore/qstatemachine.h> + +class QAction; +class QEventLoop; +class QGraphicsPieMenuSection; + +class QGraphicsPieMenuPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsPieMenu); +public: + void init(const QIcon &icon = QIcon(), const QString &title = QString()); + + QIcon icon; + QString title; + QStateMachine *machine; + QState *popupState; + //QTransition *transition; + QList<QGraphicsPieMenuSection *> sections; + + QEventLoop *eventLoop; + + QAction *menuAction; + QGraphicsPieMenu *q_ptr; + + void updatePopupState(); +}; + +#endif diff --git a/examples/animation/piemenu/qgraphicspiemenusection_p.h b/examples/animation/piemenu/qgraphicspiemenusection_p.h new file mode 100644 index 0000000..328f742 --- /dev/null +++ b/examples/animation/piemenu/qgraphicspiemenusection_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSPIEMENUSECTION_H +#define QGRAPHICSPIEMENUSECTION_H + +#include <QtGui/qgraphicswidget.h> +#include <QtGui/qpainter.h> + +class QGraphicsPieMenuSection : public QGraphicsWidget +{ + Q_OBJECT + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation) +public: + QGraphicsPieMenuSection(QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), rot(0) + { } + + qreal rotation() const + { + return rot; + } + void setRotation(qreal rotation) + { + rot = rotation; + setTransform(QTransform().rotate(rot)); + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) + { + Q_UNUSED(option); + Q_UNUSED(widget); + painter->setPen(QPen(Qt::black, 1)); + painter->setBrush(QBrush(Qt::gray)); + painter->drawPie(QRectF(-100, -100, 200, 200), 0, -30 * 16); + } + +protected: + QSizeF sizeHint(Qt::SizeHint which, const QSizeF &size = QSizeF()) const + { + Q_UNUSED(which); + Q_UNUSED(size); + return QSizeF(100, 30); + } + +private: + qreal rot; +}; + +#endif diff --git a/examples/animation/piemenu/scene.cpp b/examples/animation/piemenu/scene.cpp new file mode 100644 index 0000000..08aad06 --- /dev/null +++ b/examples/animation/piemenu/scene.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicspiemenu.h" +#include "scene.h" + +#include <QtGui/qaction.h> +#include <QtGui/qgraphicssceneevent.h> + +Scene::Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent) + : QGraphicsScene(x, y, width, height, parent) +{ +} + +Scene::Scene(const QRectF &sceneRect, QObject *parent) + : QGraphicsScene(sceneRect, parent) +{ +} + +Scene::Scene(QObject *parent) + : QGraphicsScene(parent) +{ +} + +Scene::~Scene() +{ +} + +void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsPieMenu *menu = new QGraphicsPieMenu; + for (int i = 0; i < 5; ++i) + menu->addAction(new QAction(QString("Item %1").arg(i), menu)); + menu->popup(event->scenePos()); +} diff --git a/examples/animation/piemenu/scene.h b/examples/animation/piemenu/scene.h new file mode 100644 index 0000000..676f55f --- /dev/null +++ b/examples/animation/piemenu/scene.h @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENE_H +#define SCENE_H + +#include <QtGui/qgraphicsscene.h> + +class Scene : public QGraphicsScene +{ + Q_OBJECT +public: + Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent = 0); + Scene(const QRectF &sceneRect, QObject *parent = 0); + Scene(QObject *parent = 0); + ~Scene(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); +}; + +#endif diff --git a/examples/animation/research/memberfunctions/main.cpp b/examples/animation/research/memberfunctions/main.cpp new file mode 100644 index 0000000..9142f29 --- /dev/null +++ b/examples/animation/research/memberfunctions/main.cpp @@ -0,0 +1,48 @@ +#include <QtGui> +#include "qvalueanimation.h" + +AbstractProperty *qGraphicsItemProperty(QGraphicsItem *item, const char *property) +{ + if (qstrcmp(property, "pos") == 0) { + return new MemberFunctionProperty<QGraphicsItem, QPointF>(item, &QGraphicsItem::pos, &QGraphicsItem::setPos); + } + return 0; +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QGraphicsScene scene; + QGraphicsView view(&scene); + + QGraphicsItem *item = new QGraphicsRectItem(QRectF(0,0, 200, 100)); + scene.addItem(item); + + QValueAnimation *posAnim = new QValueAnimation; + posAnim->setStartValue(QPointF(0,0)); + posAnim->setEndValue(QPointF(400, 0)); + posAnim->setDuration(1000); + // Alternative 1 + //posAnim->setMemberFunction(item, &QGraphicsItem::pos, &QGraphicsItem::setPos); + + // Alternative 2 + //posAnim->setProperty(qMemberFunctionProperty(item, &QGraphicsItem::pos, &QGraphicsItem::setPos)); + + // Alternative 3 + posAnim->setProperty(qGraphicsItemProperty(item, "pos")); + + // Alternative 4, (by implementing the qGraphicsItemProperty QGraphicsItem::property()) + //posAnim->setProperty(item->property("pos")); + + // can also do this, which abstracts away the whole property thing. + // i.e. this interface can also be used for QObject-properties: + //posAnim->setAnimationProperty(animationProperty); + + posAnim->start(); + + view.resize(800,600); + view.show(); + return app.exec(); +} + diff --git a/examples/animation/research/memberfunctions/memberfunctions.pro b/examples/animation/research/memberfunctions/memberfunctions.pro new file mode 100644 index 0000000..6b67895 --- /dev/null +++ b/examples/animation/research/memberfunctions/memberfunctions.pro @@ -0,0 +1,16 @@ +###################################################################### +# Automatically generated by qmake (2.01a) fr 26. sep 13:21:57 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + qvalueanimation.cpp +HEADERS += qvalueanimation.h + +CONFIG += console + diff --git a/examples/animation/research/memberfunctions/qvalueanimation.cpp b/examples/animation/research/memberfunctions/qvalueanimation.cpp new file mode 100644 index 0000000..2fe9be9 --- /dev/null +++ b/examples/animation/research/memberfunctions/qvalueanimation.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + + + +#include "qvalueanimation.h" +#include "qvalueanimation_p.h" + +QT_BEGIN_NAMESPACE + + +void QValueAnimationPrivate::initDefaultStartValue() +{ + Q_Q(QValueAnimation); + if (animProp && !q->startValue().isValid() + && ((currentTime == 0 && (currentIteration || currentIteration == 0)) + || (currentTime == duration && currentIteration == (iterationCount - 1)))) { + setDefaultStartValue(animProp->read()); + } +} + + +QValueAnimation::QValueAnimation(QObject *parent) : QVariantAnimation(*new QValueAnimationPrivate, parent) +{ +} + +QValueAnimation::~QValueAnimation() +{ +} + +void QValueAnimation::setProperty(AbstractProperty *animProp) +{ + Q_D(QValueAnimation); + d->animProp = animProp; +} + +/*! + \reimp + */ +void QValueAnimation::updateCurrentValue(const QVariant &value) +{ + Q_D(QValueAnimation); + if (state() == QAbstractAnimation::Stopped) + return; + + d->animProp->write(value); +} + + +/*! + \reimp +*/ +void QValueAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState) +{ + Q_D(QValueAnimation); + // Initialize start value + if (oldState == QAbstractAnimation::Stopped && newState == QAbstractAnimation::Running) + d->initDefaultStartValue(); +} + + + +#include "moc_qvalueanimation.cpp" + +QT_END_NAMESPACE diff --git a/examples/animation/research/memberfunctions/qvalueanimation.h b/examples/animation/research/memberfunctions/qvalueanimation.h new file mode 100644 index 0000000..a4aa213 --- /dev/null +++ b/examples/animation/research/memberfunctions/qvalueanimation.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QVALUEANIMATION_H +#define QVALUEANIMATION_H + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qvariantanimation.h" +#else +# include <QtCore/qvariantanimation.h> +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGraphicsItem; +class QValueAnimationPrivate; + +QT_MODULE(Gui) + +struct AbstractProperty { + virtual void write(const QVariant &value) = 0; + virtual QVariant read() const = 0; +}; + +# define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember)) +template <typename Target, typename T> +class MemberFunctionProperty : public AbstractProperty { +public: + typedef void (Target::*RefWrite)(const T &); + typedef T (Target::*ValRead)(void) const; + + MemberFunctionProperty(Target *target, ValRead readFunc, RefWrite writeFunc) + : m_target(target), m_readFn(readFunc), m_writeFn(writeFunc) {} + + virtual void write(const QVariant &value) { + CALL_MEMBER_FN(m_target, m_writeFn)(qVariantValue<T>(value)); + } + + virtual QVariant read() const { + if (m_readFn) + return qVariantFromValue<T>(CALL_MEMBER_FN(m_target, m_readFn)()); + return QVariant(); + } + +private: + Target *m_target; + ValRead m_readFn; + RefWrite m_writeFn; +}; + + +class QValueAnimation : public QVariantAnimation +{ + Q_OBJECT + +public: + QValueAnimation(QObject *parent = 0); + ~QValueAnimation(); + + template <typename Target, typename T> + void setMemberFunction(Target *target, + T (Target::*readFunc)(void) const, // ### useValRead typedef + void (Target::*writeFunc)(const T &) // ### use RefWrite typedef + ) { + // ### ownership of MemberFunctionProperty + AbstractProperty *animProp = new MemberFunctionProperty<Target, T>(target, readFunc, writeFunc); + setProperty(animProp); + } + + void updateCurrentValue(const QVariant &value); + void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState); + void setProperty(AbstractProperty *animProp); + +private: + Q_DISABLE_COPY(QValueAnimation); + Q_DECLARE_PRIVATE(QValueAnimation); +}; + +#endif // QVALUEANIMATION_H diff --git a/examples/animation/research/memberfunctions/qvalueanimation_p.h b/examples/animation/research/memberfunctions/qvalueanimation_p.h new file mode 100644 index 0000000..e6e7682 --- /dev/null +++ b/examples/animation/research/memberfunctions/qvalueanimation_p.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QVALUEANIMATION_P_H +#define QVALUEANIMATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of QIODevice. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qvariantanimation_p.h> //### + +QT_BEGIN_NAMESPACE + +class QValueAnimationPrivate : public QVariantAnimationPrivate +{ + Q_DECLARE_PUBLIC(QValueAnimation) +public: + QValueAnimationPrivate() : QVariantAnimationPrivate(), animProp(0) + { + } + + void initDefaultStartValue(); + + AbstractProperty *animProp; + + //###TODO +}; + +QT_END_NAMESPACE + +#endif //QVALUEANIMATION_P_H diff --git a/examples/animation/research/propertytransform/main.cpp b/examples/animation/research/propertytransform/main.cpp new file mode 100644 index 0000000..80002c9 --- /dev/null +++ b/examples/animation/research/propertytransform/main.cpp @@ -0,0 +1,47 @@ +#include <QtGui> + +#include "qpropertytransform.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QGraphicsScene scene; + QGraphicsView view(&scene); + + QGraphicsItem *item = new QGraphicsRectItem(QRectF(0,0, 200, 100)); + scene.addItem(item); + QPropertyTransform transform; + transform.setTargetItem(item); + + QAnimationGroup *group = new QAnimationGroup(QAnimationGroup::Parallel, &scene); + QPropertyAnimation *scaleAnim = new QPropertyAnimation(&transform, "scaleX"); + scaleAnim->setStartValue(1.0); + scaleAnim->setTargetValue(2.0); + scaleAnim->setDuration(10000); + group->add(scaleAnim); + + QPropertyAnimation *scaleAnim2 = new QPropertyAnimation(&transform, "scaleY"); + scaleAnim2->setStartValue(.0); + scaleAnim2->setTargetValue(2.0); + scaleAnim2->setDuration(10000); + QEasingCurve curve(QEasingCurve::InElastic); + curve.setPeriod(2); + curve.setAmplitude(2); + + //scaleAnim2->setEasingCurve(curve); + //scaleAnim2->setEasingCurve(QEasingCurve(QEasingCurve::OutElastic , 2, 2 )); + group->add(scaleAnim2); + + QPropertyAnimation *rotAnim = new QPropertyAnimation(&transform, "rotation"); + rotAnim->setStartValue(0); + rotAnim->setTargetValue(90); + rotAnim->setDuration(10000); + group->add(rotAnim); + + group->start(); + + view.resize(800,600); + view.show(); + return app.exec(); +} diff --git a/examples/animation/research/propertytransform/propertytransform.pro b/examples/animation/research/propertytransform/propertytransform.pro new file mode 100644 index 0000000..94c36b8 --- /dev/null +++ b/examples/animation/research/propertytransform/propertytransform.pro @@ -0,0 +1,14 @@ +###################################################################### +# Automatically generated by qmake (2.01a) fr 26. sep 13:21:57 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp +HEADERS += qpropertytransform.h +CONFIG += console + diff --git a/examples/animation/research/propertytransform/qpropertytransform.h b/examples/animation/research/propertytransform/qpropertytransform.h new file mode 100644 index 0000000..e052625 --- /dev/null +++ b/examples/animation/research/propertytransform/qpropertytransform.h @@ -0,0 +1,78 @@ +#include <QtCore/QObject> +#include <QtCore/QPoint> +#include <QtGui/QGraphicsItem> +#include <QtGui/QTransform> +#include <QtCore/QDebug> + +/** + * Experimental. + * Pros: + * 1. Does not add ugly/confusing API to QGraphicsItem. + * + * Cons: + * 1. apply() /m_item->setTransform() is called too many times. (FIXED NOW?) + * + * + */ +class QPropertyTransform : public QObject { + Q_OBJECT +public: + Q_PROPERTY(QPointF center READ center WRITE setCenter); + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation); + Q_PROPERTY(qreal scaleX READ scaleX WRITE setScaleX); + Q_PROPERTY(qreal scaleY READ scaleY WRITE setScaleY); +public: + QPropertyTransform() : m_item(0), m_rotationZ(0), m_scaleX(1.), m_scaleY(1.) {} + + void setTargetItem(QGraphicsItem *item) { + m_item = item; + } + + void setCenter(const QPointF ¢er) { + m_center = center; + apply(); + } + + QPointF center() const { return m_center; } + + void setRotation(qreal rotation) { + m_rotationZ = rotation; + apply(); + } + + qreal rotation() const { return m_rotationZ; } + + void setScaleX(qreal scale) { + m_scaleX = scale; + apply(); + } + + qreal scaleX() const { return m_scaleX; } + + void setScaleY(qreal scale) { + m_scaleY = scale; + apply(); + } + + qreal scaleY() const { return m_scaleY; } + +private: + QTransform transform() const { + return QTransform().translate(m_center.x(), m_center.y()) + .rotate(m_rotationZ) + .scale(m_scaleX, m_scaleY) + .translate(-m_center.x(), -m_center.y()); + } + + void apply() { + if (m_item) + m_item->setTransform(transform()); + } + + QGraphicsItem *m_item; + QPointF m_center; + qreal m_rotationZ; + qreal m_scaleX; + qreal m_scaleY; +}; + diff --git a/examples/animation/research/sound/main.cpp b/examples/animation/research/sound/main.cpp new file mode 100644 index 0000000..2c9fa47 --- /dev/null +++ b/examples/animation/research/sound/main.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +//The purpose of this example is to show that it is possible to have your own +// animation with undefined duration + +#include <QtGui/QtGui> +#include <phonon> + +class SoundAnimation : public QAbstractAnimation +{ +public: + SoundAnimation(const QString &file) + { + //in an idea case we should also control the errors + Phonon::createPath(&m_media, &m_audio); + m_media.setCurrentSource(file); + connect(&m_media, SIGNAL(finished()), SLOT(stop())); + } + + int duration() const + { + return -1; + } + + void updateCurrentTime(int msecs) + { + //nothing to do here... + qDebug() << "updateCurrentTime" << msecs; + } + + void updateState(State state) + { + switch(state) + { + case Running: + m_media.play(); + break; + case Stopped: + m_media.stop(); + break; + case Paused: + m_media.pause(); + break; + } + } + + +private: + Phonon::MediaObject m_media; + Phonon::AudioOutput m_audio; + +}; + + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(sound); + + SoundAnimation anim(QLatin1String(":/media/sax.mp3")); + app.connect(&anim, SIGNAL(finished()), SLOT(quit())); + anim.start(); + + return app.exec(); +}
\ No newline at end of file diff --git a/examples/animation/research/sound/media/sax.mp3 b/examples/animation/research/sound/media/sax.mp3 Binary files differnew file mode 100644 index 0000000..0a078b1 --- /dev/null +++ b/examples/animation/research/sound/media/sax.mp3 diff --git a/examples/animation/research/sound/sound.pro b/examples/animation/research/sound/sound.pro new file mode 100644 index 0000000..0ad3050 --- /dev/null +++ b/examples/animation/research/sound/sound.pro @@ -0,0 +1,14 @@ +###################################################################### +# Automatically generated by qmake (2.01a) mer. 21. janv. 13:53:26 2009 +###################################################################### + +TEMPLATE = app +QT += phonon +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +RESOURCES = sound.qrc + +# Input +SOURCES += main.cpp diff --git a/examples/animation/research/sound/sound.qrc b/examples/animation/research/sound/sound.qrc new file mode 100644 index 0000000..8919142 --- /dev/null +++ b/examples/animation/research/sound/sound.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> +<file>media/sax.mp3</file> +</qresource> +</RCC> diff --git a/examples/animation/states/accessories-dictionary.png b/examples/animation/states/accessories-dictionary.png Binary files differnew file mode 100644 index 0000000..e9bd55d --- /dev/null +++ b/examples/animation/states/accessories-dictionary.png diff --git a/examples/animation/states/akregator.png b/examples/animation/states/akregator.png Binary files differnew file mode 100644 index 0000000..a086f45 --- /dev/null +++ b/examples/animation/states/akregator.png diff --git a/examples/animation/states/digikam.png b/examples/animation/states/digikam.png Binary files differnew file mode 100644 index 0000000..9de9fb2 --- /dev/null +++ b/examples/animation/states/digikam.png diff --git a/examples/animation/states/help-browser.png b/examples/animation/states/help-browser.png Binary files differnew file mode 100644 index 0000000..db92faa --- /dev/null +++ b/examples/animation/states/help-browser.png diff --git a/examples/animation/states/k3b.png b/examples/animation/states/k3b.png Binary files differnew file mode 100644 index 0000000..bbcafcf --- /dev/null +++ b/examples/animation/states/k3b.png diff --git a/examples/animation/states/kchart.png b/examples/animation/states/kchart.png Binary files differnew file mode 100644 index 0000000..1dd115b --- /dev/null +++ b/examples/animation/states/kchart.png diff --git a/examples/animation/states/main.cpp b/examples/animation/states/main.cpp new file mode 100644 index 0000000..5c004a2 --- /dev/null +++ b/examples/animation/states/main.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qstate.h" +# include "qstatemachine.h" +# include "qtransition.h" +# include "qparallelanimationgroup.h" +# include "qsequentialanimationgroup.h" +# include "qpropertyanimation.h" +#endif + +class Pixmap : public QGraphicsWidget +{ + Q_OBJECT +public: + Pixmap(const QPixmap &pix) : QGraphicsWidget(), p(pix) + { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + painter->drawPixmap(QPointF(), p); + } + +protected: + QSizeF sizeHint(Qt::SizeHint, const QSizeF & = QSizeF()) + { + return QSizeF(p.width(), p.height()); + } + +private: + QPixmap p; +}; + +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 *root = machine.rootState(); + QState *state1 = new QState(root); + QState *state2 = new QState(root); + QState *state3 = new QState(root); + machine.setInitialState(state1); + + // State 1 + state1->setPropertyOnEntry(button, "text", "Switch to state 2"); + state1->setPropertyOnEntry(widget, "geometry", QRectF(0, 0, 400, 150)); + state1->setPropertyOnEntry(box, "geometry", QRect(-200, 150, 200, 150)); + state1->setPropertyOnEntry(p1, "geometry", QRectF(68, 185, 64, 64)); + state1->setPropertyOnEntry(p2, "geometry", QRectF(168, 185, 64, 64)); + state1->setPropertyOnEntry(p3, "geometry", QRectF(268, 185, 64, 64)); + state1->setPropertyOnEntry(p4, "geometry", QRectF(68-150, 48-150, 64, 64)); + state1->setPropertyOnEntry(p5, "geometry", QRectF(168, 48-150, 64, 64)); + state1->setPropertyOnEntry(p6, "geometry", QRectF(268+150, 48-150, 64, 64)); + state1->setPropertyOnEntry(p1, "zRotation", qreal(0)); + state1->setPropertyOnEntry(p2, "zRotation", qreal(0)); + state1->setPropertyOnEntry(p3, "zRotation", qreal(0)); + state1->setPropertyOnEntry(p4, "zRotation", qreal(-270)); + state1->setPropertyOnEntry(p5, "zRotation", qreal(-90)); + state1->setPropertyOnEntry(p6, "zRotation", qreal(270)); + state1->setPropertyOnEntry(boxProxy, "opacity", qreal(0)); + state1->setPropertyOnEntry(p1, "opacity", qreal(1)); + state1->setPropertyOnEntry(p2, "opacity", qreal(1)); + state1->setPropertyOnEntry(p3, "opacity", qreal(1)); + state1->setPropertyOnEntry(p4, "opacity", qreal(0)); + state1->setPropertyOnEntry(p5, "opacity", qreal(0)); + state1->setPropertyOnEntry(p6, "opacity", qreal(0)); + + // State 2 + state2->setPropertyOnEntry(button, "text", "Switch to state 3"); + state2->setPropertyOnEntry(widget, "geometry", QRectF(200, 150, 200, 150)); + state2->setPropertyOnEntry(box, "geometry", QRect(9, 150, 190, 150)); + state2->setPropertyOnEntry(p1, "geometry", QRectF(68-150, 185+150, 64, 64)); + state2->setPropertyOnEntry(p2, "geometry", QRectF(168, 185+150, 64, 64)); + state2->setPropertyOnEntry(p3, "geometry", QRectF(268+150, 185+150, 64, 64)); + state2->setPropertyOnEntry(p4, "geometry", QRectF(64, 48, 64, 64)); + state2->setPropertyOnEntry(p5, "geometry", QRectF(168, 48, 64, 64)); + state2->setPropertyOnEntry(p6, "geometry", QRectF(268, 48, 64, 64)); + state2->setPropertyOnEntry(p1, "zRotation", qreal(-270)); + state2->setPropertyOnEntry(p2, "zRotation", qreal(90)); + state2->setPropertyOnEntry(p3, "zRotation", qreal(270)); + state2->setPropertyOnEntry(p4, "zRotation", qreal(0)); + state2->setPropertyOnEntry(p5, "zRotation", qreal(0)); + state2->setPropertyOnEntry(p6, "zRotation", qreal(0)); + state2->setPropertyOnEntry(boxProxy, "opacity", qreal(1)); + state2->setPropertyOnEntry(p1, "opacity", qreal(0)); + state2->setPropertyOnEntry(p2, "opacity", qreal(0)); + state2->setPropertyOnEntry(p3, "opacity", qreal(0)); + state2->setPropertyOnEntry(p4, "opacity", qreal(1)); + state2->setPropertyOnEntry(p5, "opacity", qreal(1)); + state2->setPropertyOnEntry(p6, "opacity", qreal(1)); + + // State 3 + state3->setPropertyOnEntry(button, "text", "Switch to state 1"); + state3->setPropertyOnEntry(p1, "geometry", QRectF(5, 5, 64, 64)); + state3->setPropertyOnEntry(p2, "geometry", QRectF(5, 5 + 64 + 5, 64, 64)); + state3->setPropertyOnEntry(p3, "geometry", QRectF(5, 5 + (64 + 5) + 64, 64, 64)); + state3->setPropertyOnEntry(p4, "geometry", QRectF(5 + 64 + 5, 5, 64, 64)); + state3->setPropertyOnEntry(p5, "geometry", QRectF(5 + 64 + 5, 5 + 64 + 5, 64, 64)); + state3->setPropertyOnEntry(p6, "geometry", QRectF(5 + 64 + 5, 5 + (64 + 5) + 64, 64, 64)); + state3->setPropertyOnEntry(widget, "geometry", QRectF(138, 5, 400 - 138, 200)); + state3->setPropertyOnEntry(box, "geometry", QRect(5, 205, 400, 90)); + state3->setPropertyOnEntry(p1, "opacity", qreal(1)); + state3->setPropertyOnEntry(p2, "opacity", qreal(1)); + state3->setPropertyOnEntry(p3, "opacity", qreal(1)); + state3->setPropertyOnEntry(p4, "opacity", qreal(1)); + state3->setPropertyOnEntry(p5, "opacity", qreal(1)); + state3->setPropertyOnEntry(p6, "opacity", qreal(1)); + + QParallelAnimationGroup animation1; + + QSequentialAnimationGroup *animation1SubGroup; + animation1SubGroup = new QSequentialAnimationGroup(&animation1); + animation1SubGroup->addPause(250); + animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry")); + + animation1.addAnimation(new QPropertyAnimation(widget, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p1, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p2, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p3, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p4, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p5, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p6, "geometry")); + animation1.addAnimation(new QPropertyAnimation(p1, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p2, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p3, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p4, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p5, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p6, "zRotation")); + animation1.addAnimation(new QPropertyAnimation(p1, "opacity")); + animation1.addAnimation(new QPropertyAnimation(p2, "opacity")); + animation1.addAnimation(new QPropertyAnimation(p3, "opacity")); + animation1.addAnimation(new QPropertyAnimation(p4, "opacity")); + animation1.addAnimation(new QPropertyAnimation(p5, "opacity")); + animation1.addAnimation(new QPropertyAnimation(p6, "opacity")); + + QParallelAnimationGroup animation2; + animation2.addAnimation(new QPropertyAnimation(box, "geometry")); + animation2.addAnimation(new QPropertyAnimation(widget, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p1, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p2, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p3, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p4, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p5, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p6, "geometry")); + animation2.addAnimation(new QPropertyAnimation(p1, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p2, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p3, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p4, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p5, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p6, "zRotation")); + animation2.addAnimation(new QPropertyAnimation(p1, "opacity")); + animation2.addAnimation(new QPropertyAnimation(p2, "opacity")); + animation2.addAnimation(new QPropertyAnimation(p3, "opacity")); + animation2.addAnimation(new QPropertyAnimation(p4, "opacity")); + animation2.addAnimation(new QPropertyAnimation(p5, "opacity")); + animation2.addAnimation(new QPropertyAnimation(p6, "opacity")); + + QParallelAnimationGroup animation3; + animation3.addAnimation(new QPropertyAnimation(box, "geometry")); + animation3.addAnimation(new QPropertyAnimation(widget, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p1, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p2, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p3, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p4, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p5, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p6, "geometry")); + animation3.addAnimation(new QPropertyAnimation(p1, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p2, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p3, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p4, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p5, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p6, "zRotation")); + animation3.addAnimation(new QPropertyAnimation(p1, "opacity")); + animation3.addAnimation(new QPropertyAnimation(p2, "opacity")); + animation3.addAnimation(new QPropertyAnimation(p3, "opacity")); + animation3.addAnimation(new QPropertyAnimation(p4, "opacity")); + animation3.addAnimation(new QPropertyAnimation(p5, "opacity")); + animation3.addAnimation(new QPropertyAnimation(p6, "opacity")); + + state1->addAnimatedTransition(button, SIGNAL(clicked()), state2, &animation1); + state2->addAnimatedTransition(button, SIGNAL(clicked()), state3, &animation2); + state3->addAnimatedTransition(button, SIGNAL(clicked()), state1, &animation3); + + machine.start(); + + QGraphicsView view(&scene); + view.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/states/states.pro b/examples/animation/states/states.pro new file mode 100644 index 0000000..f4d1e0b --- /dev/null +++ b/examples/animation/states/states.pro @@ -0,0 +1,8 @@ +SOURCES += main.cpp +RESOURCES += states.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/animation/states +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS states.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/animation/states +INSTALLS += target sources diff --git a/examples/animation/states/states.qrc b/examples/animation/states/states.qrc new file mode 100644 index 0000000..60ab3f7 --- /dev/null +++ b/examples/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/animation/stickman/animation.cpp b/examples/animation/stickman/animation.cpp new file mode 100644 index 0000000..998632a --- /dev/null +++ b/examples/animation/stickman/animation.cpp @@ -0,0 +1,152 @@ +#include "animation.h" + +#include <QPointF> +#include <QIODevice> +#include <QDataStream> + +class Frame +{ +public: + Frame() { + } + + int nodeCount() const + { + return m_nodePositions.size(); + } + + void setNodeCount(int nodeCount) + { + while (nodeCount > m_nodePositions.size()) + m_nodePositions.append(QPointF()); + + while (nodeCount < m_nodePositions.size()) + m_nodePositions.removeLast(); + } + + 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(); +} + +int Animation::totalFrames() const +{ + return m_frames.size(); +} + +void Animation::setCurrentFrame(int currentFrame) +{ + m_currentFrame = qMax(qMin(currentFrame, totalFrames()-1), 0); +} + +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(); + foreach (Frame *frame, m_frames) { + stream << frame->nodeCount(); + for (int i=0; i<frame->nodeCount(); ++i) + stream << frame->nodePos(i); + } +} + +void Animation::load(QIODevice *device) +{ + if (!m_frames.isEmpty()) + 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); + } +}
\ No newline at end of file diff --git a/examples/animation/stickman/animation.h b/examples/animation/stickman/animation.h new file mode 100644 index 0000000..22afab6 --- /dev/null +++ b/examples/animation/stickman/animation.h @@ -0,0 +1,40 @@ +#ifndef ANIMATION_H +#define ANIMATION_H + +#include <QPointF> +#include <QList> +#include <QString> + +class Frame; +class QIODevice; +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/animation/stickman/animations/chilling b/examples/animation/stickman/animations/chilling Binary files differnew file mode 100644 index 0000000..a81fc7a --- /dev/null +++ b/examples/animation/stickman/animations/chilling diff --git a/examples/animation/stickman/animations/dancing b/examples/animation/stickman/animations/dancing Binary files differnew file mode 100644 index 0000000..462f66f --- /dev/null +++ b/examples/animation/stickman/animations/dancing diff --git a/examples/animation/stickman/animations/dead b/examples/animation/stickman/animations/dead Binary files differnew file mode 100644 index 0000000..9859b4b --- /dev/null +++ b/examples/animation/stickman/animations/dead diff --git a/examples/animation/stickman/animations/jumping b/examples/animation/stickman/animations/jumping Binary files differnew file mode 100644 index 0000000..12661a1 --- /dev/null +++ b/examples/animation/stickman/animations/jumping diff --git a/examples/animation/stickman/graphicsview.cpp b/examples/animation/stickman/graphicsview.cpp new file mode 100644 index 0000000..1b6afa9 --- /dev/null +++ b/examples/animation/stickman/graphicsview.cpp @@ -0,0 +1,15 @@ +#include "graphicsview.h" + +#include <QtGui/QKeyEvent> + +GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) {} + +void GraphicsView::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) + close(); + + emit keyPressed(Qt::Key(e->key())); +} + + diff --git a/examples/animation/stickman/graphicsview.h b/examples/animation/stickman/graphicsview.h new file mode 100644 index 0000000..9ea2cfb --- /dev/null +++ b/examples/animation/stickman/graphicsview.h @@ -0,0 +1,19 @@ +#ifndef GRAPHICSVIEW_H +#define GRAPHICSVIEW + +#include <QtGui/QGraphicsView> + +class GraphicsView: public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *); + +signals: + void keyPressed(int key); +}; + +#endif diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp new file mode 100644 index 0000000..3e92aec --- /dev/null +++ b/examples/animation/stickman/lifecycle.cpp @@ -0,0 +1,176 @@ +#include "lifecycle.h" +#include "stickman.h" +#include "node.h" +#include "animation.h" +#include "graphicsview.h" + +#include <QtCore> +#include <QtGui> + +class KeyPressTransition: public QSignalTransition +{ +public: + KeyPressTransition(GraphicsView *receiver, Qt::Key key) + : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key) + { + } + KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target) + : QSignalTransition(receiver, SIGNAL(keyPressed(int)), QList<QAbstractState*>() << target), m_key(key) + { + } + + virtual bool eventTest(QEvent *e) const + { + if (QSignalTransition::eventTest(e)) { + QVariant key = static_cast<QSignalEvent*>(e)->arguments().at(0); + return (key.toInt() == int(m_key)); + } + + return false; + } +private: + Qt::Key m_key; +}; + +class LightningStrikesTransition: public QEventTransition +{ +public: + LightningStrikesTransition(QAbstractState *target) + : QEventTransition(this, QEvent::Timer, QList<QAbstractState*>() << target) + { + qsrand((uint)QDateTime::currentDateTime().toTime_t()); + startTimer(1000); + } + + virtual bool eventTest(QEvent *e) const + { + return QEventTransition::eventTest(e) && ((qrand() % 50) == 0); + } +}; + +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), "position"); + m_animationGroup->addAnimation(pa); + } + + // Set up intial state graph + m_machine = new QStateMachine(); + m_machine->setGlobalRestorePolicy(QState::RestoreProperties); + + m_alive = new QState(m_machine->rootState()); + m_alive->setObjectName("alive"); + + // Make it blink when lightning strikes before entering dead animation + QState *lightningBlink = new QState(m_machine->rootState()); + lightningBlink->setRestorePolicy(QState::DoNotRestoreProperties); + lightningBlink->setPropertyOnEntry(m_stickMan->scene(), "backgroundBrush", Qt::white); + lightningBlink->setPropertyOnEntry(m_stickMan, "penColor", Qt::black); + lightningBlink->setPropertyOnEntry(m_stickMan, "fillColor", Qt::white); + lightningBlink->setPropertyOnEntry(m_stickMan, "isDead", true); + + m_dead = new QState(m_machine->rootState()); + m_dead->setRestorePolicy(QState::DoNotRestoreProperties); + m_dead->setPropertyOnEntry(m_stickMan->scene(), "backgroundBrush", Qt::black); + m_dead->setPropertyOnEntry(m_stickMan, "penColor", Qt::white); + m_dead->setPropertyOnEntry(m_stickMan, "fillColor", 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)); + m_alive->addTransition(new KeyPressTransition(m_keyReceiver, Qt::Key_L, lightningBlink)); + connectByAnimation(m_machine->rootState(), lightningBlink, m_dead); + + m_machine->setInitialState(m_alive); +} + +void LifeCycle::setResetKey(Qt::Key resetKey) +{ + // When resetKey is pressed, enter the idle state and do a restoration animation + // (requires no animation pointer, since no property is being set in the idle state) + m_alive->addAnimatedTransition(new KeyPressTransition(m_keyReceiver, resetKey, m_idle)); +} + +void LifeCycle::setDeathAnimation(const QString &fileName) +{ + QState *deathAnimation = makeState(m_dead, fileName); + m_dead->setInitialState(deathAnimation); +} + +void LifeCycle::start() +{ + m_machine->start(); +} + +void LifeCycle::connectByAnimation(QState *parentState, + QState *s1, QAbstractState *s2, + QAbstractTransition *transition) +{ + QAnimationState *animationState = new QAnimationState(m_animationGroup, parentState); + + if (transition == 0) + s1->addTransition(animationState); + else { + transition->setTargetStates(QList<QAbstractState*>() << animationState); + s1->addTransition(transition); + } + + animationState->addFinishedTransition(s2); +} + +void LifeCycle::addActivity(const QString &fileName, Qt::Key key) +{ + QState *state = makeState(m_alive, fileName); + connectByAnimation(m_alive, m_alive, state, new KeyPressTransition(m_keyReceiver, key)); +} + +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 = 0; + for (int i=0; i<frameCount; ++i) { + QState *frameState = new QState(topLevel); + + animation.setCurrentFrame(i); + const int nodeCount = animation.nodeCount(); + for (int j=0; j<nodeCount; ++j) + frameState->setPropertyOnEntry(m_stickMan->node(j), "position", animation.nodePos(j)); + + if (previousState == 0) + topLevel->setInitialState(frameState); + else + connectByAnimation(topLevel, previousState, frameState); + previousState = frameState; + } + + // Loop + connectByAnimation(topLevel, previousState, topLevel->initialState()); + + return topLevel; + +} + +LifeCycle::~LifeCycle() +{ + delete m_machine; + delete m_animationGroup; +} diff --git a/examples/animation/stickman/lifecycle.h b/examples/animation/stickman/lifecycle.h new file mode 100644 index 0000000..8094a76 --- /dev/null +++ b/examples/animation/stickman/lifecycle.h @@ -0,0 +1,40 @@ +#ifndef LIFECYCLE_H +#define LIFECYCLE_H + +#include <Qt> + +class StickMan; +class QStateMachine; +class QAnimationGroup; +class QState; +class QAbstractState; +class QAbstractTransition; +class GraphicsView; +class LifeCycle +{ +public: + LifeCycle(StickMan *stickMan, GraphicsView *keyEventReceiver); + ~LifeCycle(); + + void setDeathAnimation(const QString &fileName); + void setResetKey(Qt::Key key); + void addActivity(const QString &fileName, Qt::Key key); + + void start(); + +private: + void connectByAnimation(QState *parentState, QState *s1, QAbstractState *s2, + QAbstractTransition *transition = 0); + 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/animation/stickman/main.cpp b/examples/animation/stickman/main.cpp new file mode 100644 index 0000000..a094e28 --- /dev/null +++ b/examples/animation/stickman/main.cpp @@ -0,0 +1,58 @@ +#include "animation.h" +#include "node.h" +#include "lifecycle.h" +#include "stickman.h" +#include "graphicsview.h" + +#include <QtCore> +#include <QtGui> + +int main(int argc, char **argv) +{ + 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>Press <font color=\"purple\">Return</font> to make him return to his original position.</li>" + "<li>When you are done, press <font color=\"purple\">Escape</font>.</li>" + "</i></p>" + "<p>If you are 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 = new QGraphicsScene(); + scene->addItem(stickMan); + scene->addItem(textItem); + scene->setBackgroundBrush(Qt::black); + + GraphicsView *view = new GraphicsView(); + view->setRenderHints(QPainter::Antialiasing); + view->setTransformationAnchor(QGraphicsView::NoAnchor); + view->setScene(scene); + view->showFullScreen(); + view->setFocus(); + view->setSceneRect(scene->sceneRect()); + + LifeCycle *cycle = new LifeCycle(stickMan, view); + cycle->setResetKey(Qt::Key_Return); + cycle->setDeathAnimation("animations/dead"); + + cycle->addActivity("animations/jumping", Qt::Key_J); + cycle->addActivity("animations/dancing", Qt::Key_D); + cycle->addActivity("animations/chilling", Qt::Key_C); + cycle->start(); + + return app.exec(); +} diff --git a/examples/animation/stickman/node.cpp b/examples/animation/stickman/node.cpp new file mode 100644 index 0000000..f3468d0 --- /dev/null +++ b/examples/animation/stickman/node.cpp @@ -0,0 +1,42 @@ +#include "node.h" + +#include <QRectF> +#include <QPainter> +#include <QGraphicsSceneMouseEvent> + +Node::Node(const QPointF &pos, QGraphicsItem *parent) + : QGraphicsItem(parent), m_dragging(false) +{ + setPos(pos); +} + +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); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + m_dragging = true; +} + +void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragging) + setPos(mapToParent(event->pos())); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + m_dragging = false; +}
\ No newline at end of file diff --git a/examples/animation/stickman/node.h b/examples/animation/stickman/node.h new file mode 100644 index 0000000..b796774 --- /dev/null +++ b/examples/animation/stickman/node.h @@ -0,0 +1,26 @@ +#ifndef NODE_H +#define NODE_H + +#include <QGraphicsItem> + +class Node: public QObject, public QGraphicsItem +{ + Q_OBJECT + Q_PROPERTY(QPointF position READ pos WRITE setPos); +public: + Node(const QPointF &pos, QGraphicsItem *parent = 0); + ~Node(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *); + void mouseMoveEvent(QGraphicsSceneMouseEvent *); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *); + +private: + bool m_dragging; +}; + +#endif diff --git a/examples/animation/stickman/stickman.cpp b/examples/animation/stickman/stickman.cpp new file mode 100644 index 0000000..22d48d3 --- /dev/null +++ b/examples/animation/stickman/stickman.cpp @@ -0,0 +1,299 @@ +#include "stickman.h" +#include "node.h" + +#include <QPainter> +#include <QTimer> + +#define _USE_MATH_DEFINES +#include <math.h> + +static const int NodeCount = 16; +static const 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 const int BoneCount = 24; +static const 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() +{ + m_nodes = new Node*[NodeCount]; + m_sticks = true; + m_isDead = false; + m_pixmap = QPixmap("images/head.png"); + m_penColor = Qt::white; + m_fillColor = Qt::black; + + // 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); + } + + m_perfectBoneLengths = new qreal[BoneCount]; + 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); +} + +StickMan::~StickMan() +{ + delete m_nodes; +} + +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, plus jump height :-) + return QRectF(-125, -200, 250, 450 + 50).adjusted(-55.0, -55.0, 55.0, 55.0); +} + +int StickMan::nodeCount() const +{ + return NodeCount; +} + +Node *StickMan::node(int idx) const +{ + const_cast<StickMan *>(this)->prepareGeometryChange(); + if (idx >= 0 && idx < NodeCount) + return m_nodes[idx]; + else + return 0; +} + +void StickMan::timerEvent(QTimerEvent *e) +{ + prepareGeometryChange(); +} + +void StickMan::stabilize() +{ + 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; + + pos1 -= dist * (0.5 * diff); + pos2 += dist * (0.5 * diff); + + 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 = asin(sinAngle) * 180.0 / M_PI; + + QPointF headPos = node1->pos(); + painter->save(); + painter->translate(headPos); + painter->rotate(-angle); + + painter->setBrush(m_fillColor); + painter->drawEllipse(QPointF(0,0), 50.0, 50.0); + + /*painter->drawArc(QRectF(-20.0, 0.0, 40.0, 20.0), 30.0 * 16, 120.0 * 16); + + painter->setBrush(m_penColor); + painter->drawEllipse(QPointF(-30.0, -30.0), 2.5, 2.5); + painter->drawEllipse(QPointF(30.0, -30.0), 2.5, 2.5);*/ + + 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); + } + + + painter->restore(); + } + } +} + + + diff --git a/examples/animation/stickman/stickman.h b/examples/animation/stickman/stickman.h new file mode 100644 index 0000000..ae406ca --- /dev/null +++ b/examples/animation/stickman/stickman.h @@ -0,0 +1,59 @@ +#ifndef STICKMAN_H +#define STICKMAN_H + +#include <QGraphicsItem> + +const int LimbCount = 16; + +class Node; +class QTimer; +class StickMan: public QObject, public QGraphicsItem +{ + 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(); + ~StickMan(); + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + 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(); + +protected: + void timerEvent(QTimerEvent *e); + +private: + QPointF posFor(int idx) const; + + Node **m_nodes; + qreal *m_perfectBoneLengths; + + uint m_sticks : 1; + uint m_isDead : 1; + uint m_reserved : 30; + + QPixmap m_pixmap; + QColor m_penColor; + QColor m_fillColor; +}; + +#endif // STICKMAN_H diff --git a/examples/animation/stickman/stickman.pro b/examples/animation/stickman/stickman.pro new file mode 100644 index 0000000..136cb44 --- /dev/null +++ b/examples/animation/stickman/stickman.pro @@ -0,0 +1,12 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ti 3. feb 19:50:14 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += stickman.h animation.h node.h lifecycle.h graphicsview.h +SOURCES += main.cpp stickman.cpp animation.cpp node.cpp lifecycle.cpp graphicsview.cpp diff --git a/examples/animation/sub-attaq/animationmanager.cpp b/examples/animation/sub-attaq/animationmanager.cpp new file mode 100644 index 0000000..9f99426 --- /dev/null +++ b/examples/animation/sub-attaq/animationmanager.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "animationmanager.h" + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qabstractanimation.h" +#else +# include <QtCore/QAbstractAnimation> +#endif +#include <QDebug> + +// the universe's only animation manager +AnimationManager *AnimationManager::instance = 0; + +AnimationManager::AnimationManager() +{ +} + +AnimationManager *AnimationManager::self() +{ + if (!instance) + instance = new AnimationManager; + return instance; +} + +void AnimationManager::registerAnimation(QAbstractAnimation *anim) +{ + animations.append(anim); +} + +void AnimationManager::unregisterAnimation(QAbstractAnimation *anim) +{ + animations.removeAll(anim); +} + +void AnimationManager::unregisterAllAnimations() +{ + animations.clear(); +} + +void AnimationManager::pauseAll() +{ + foreach (QAbstractAnimation* animation, animations) + { + if (animation->state() == QAbstractAnimation::Running) + animation->pause(); + } +} +void AnimationManager::resumeAll() +{ + foreach (QAbstractAnimation* animation, animations) + { + if (animation->state() == QAbstractAnimation::Paused) + animation->resume(); + } +} diff --git a/examples/animation/sub-attaq/animationmanager.h b/examples/animation/sub-attaq/animationmanager.h new file mode 100644 index 0000000..fe92680 --- /dev/null +++ b/examples/animation/sub-attaq/animationmanager.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ANIMATIONMANAGER_H +#define ANIMATIONMANAGER_H + +#include <QObject> + +class QAbstractAnimation; + +class AnimationManager : public QObject +{ +Q_OBJECT +public: + AnimationManager(); + void registerAnimation(QAbstractAnimation *anim); + void unregisterAnimation(QAbstractAnimation *anim); + void unregisterAllAnimations(); + static AnimationManager *self(); + +public slots: + void pauseAll(); + void resumeAll(); + +private: + static AnimationManager *instance; + QList<QAbstractAnimation *> animations; +}; + +#endif // ANIMATIONMANAGER_H diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp new file mode 100644 index 0000000..6824f17 --- /dev/null +++ b/examples/animation/sub-attaq/boat.cpp @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "boat.h" +#include "boat_p.h" +#include "bomb.h" +#include "pixmapitem.h" +#include "graphicsscene.h" +#include "animationmanager.h" +#include "custompropertyanimation.h" + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qpropertyanimation.h" +# include "qstatemachine.h" +# include "qhistorystate.h" +# include "qfinalstate.h" +# include "qstate.h" +#include "qsequentialanimationgroup.h" +#include "qanimationstate.h" +#else +#include <QPropertyAnimation> +#include <QStateMachine> +#include <QHistoryState> +#include <QFinalState> +#include <QState> +#include <QSequentialAnimationGroup> +#include <QAnimationState> +#endif + +static QAbstractAnimation *setupDestroyAnimation(Boat *boat) +{ + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(boat); +#if QT_VERSION >=0x040500 + PixmapItem *step1 = new PixmapItem(QString("explosion/boat/step1"),GraphicsScene::Big, boat); + step1->setZValue(6); + PixmapItem *step2 = new PixmapItem(QString("explosion/boat/step2"),GraphicsScene::Big, boat); + step2->setZValue(6); + PixmapItem *step3 = new PixmapItem(QString("explosion/boat/step3"),GraphicsScene::Big, boat); + step3->setZValue(6); + PixmapItem *step4 = new PixmapItem(QString("explosion/boat/step4"),GraphicsScene::Big, boat); + step4->setZValue(6); + step1->setOpacity(0); + step2->setOpacity(0); + step3->setOpacity(0); + step4->setOpacity(0); + CustomPropertyAnimation *anim1 = new CustomPropertyAnimation(boat); + anim1->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim1->setDuration(100); + anim1->setEndValue(1); + CustomPropertyAnimation *anim2 = new CustomPropertyAnimation(boat); + anim2->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim2->setDuration(100); + anim2->setEndValue(1); + CustomPropertyAnimation *anim3 = new CustomPropertyAnimation(boat); + anim3->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim3->setDuration(100); + anim3->setEndValue(1); + CustomPropertyAnimation *anim4 = new CustomPropertyAnimation(boat); + anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim4->setDuration(100); + anim4->setEndValue(1); + group->addAnimation(anim1); + group->addAnimation(anim2); + group->addAnimation(anim3); + group->addAnimation(anim4); +#else + // work around for a bug where we don't transition if the duration is zero. + QtPauseAnimation *anim = new QtPauseAnimation(group); + anim->setDuration(1); + group->addAnimation(anim); +#endif + AnimationManager::self()->registerAnimation(group); + return group; +} + + + +Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) + : QGraphicsWidget(parent,wFlags), speed(0), bombsAlreadyLaunched(0), direction(Boat::None), movementAnimation(0) +{ + pixmapItem = new PixmapItem(QString("boat"),GraphicsScene::Big, this); + setZValue(4); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable); + resize(pixmapItem->boundingRect().size()); + + //The movement animation used to animate the boat + movementAnimation = new QPropertyAnimation(this, "pos"); + AnimationManager::self()->registerAnimation(movementAnimation); + + //We setup the state machien of the boat + QStateMachine *machine = new QStateMachine(this); + QState *moving = new QState(machine->rootState()); + 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->rootState()); + LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this,machine->rootState()); + + //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, SIGNAL(finished()), stopState); + moveStateRight->addTransition(movementAnimation, SIGNAL(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 = moving->addHistoryState(); + launchStateLeft->addTransition(historyState); + launchStateRight->addTransition(historyState); + + QFinalState *final = new QFinalState(machine->rootState()); + + //This state play the destroyed animation + QAnimationState *destroyedState = new QAnimationState(machine->rootState()); + destroyedState->addAnimation(setupDestroyAnimation(this)); + + //Play a nice animation when the boat is destroyed + moving->addTransition(this, SIGNAL(boatDestroyed()),destroyedState); + + //Transition to final state when the destroyed animation is finished + destroyedState->addFinishedTransition(final); + + //The machine has finished to be executed, then the boat is dead + connect(machine,SIGNAL(finished()),this, SIGNAL(boatExecutionFinished())); + + machine->start(); +} + +void Boat::updateBoatMovement() +{ + if (speed == 0 || direction == Boat::None) { + movementAnimation->stop(); + return; + } + + movementAnimation->stop(); + movementAnimation->setStartValue(pos()); + + 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/animation/sub-attaq/boat.h b/examples/animation/sub-attaq/boat.h new file mode 100644 index 0000000..4c4a737 --- /dev/null +++ b/examples/animation/sub-attaq/boat.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __BOAT__H__ +#define __BOAT__H__ + +//Qt +#include <QObject> +#include <QKeyEvent> + +#include <QDebug> + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qgraphicswidget.h" +#else +# include <QtGui/QGraphicsWidget> +#endif + +class PixmapItem; +class Bomb; +class QVariantAnimation; + +class Boat : public QGraphicsWidget +{ +Q_OBJECT +Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + enum Movement { + None = 0, + Left, + Right + }; + enum { Type = UserType + 2 }; + Boat(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); + void destroy(); + + int bombsLaunched() const; + void setBombsLaunched(int number); + + int currentSpeed() const; + void setCurrentSpeed(int speed); + + enum Movement currentDirection() const; + void setCurrentDirection(Movement direction); + + void updateBoatMovement(); + + virtual int type() const; + +Q_SIGNALS: + void boatDestroyed(); + void boatExecutionFinished(); + +private: + int speed; + int bombsAlreadyLaunched; + Movement direction; + QVariantAnimation *movementAnimation; + PixmapItem *pixmapItem; +}; + +#endif //__BOAT__H__ diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h new file mode 100644 index 0000000..8dacaba --- /dev/null +++ b/examples/animation/sub-attaq/boat_p.h @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BOAT_P_H +#define BOAT_P_H + +//Own +#include "bomb.h" +#include "graphicsscene.h" + +// Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qkeyeventtransition.h" +#else +# include <QtGui/QKeyEventTransition> +#endif + +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 *boat, QEvent::Type type, int key) + : QKeyEventTransition(boat,type, key) + { + this->boat = boat; + this->key = key; +#if defined(Q_OS_MAC) + setModifiers(Qt::KeypadModifier); +#endif + } +protected: + virtual bool eventTest(QEvent *event) const + { + Q_UNUSED(event); + if (!QKeyEventTransition::eventTest(event)) + return false; + if (boat->currentSpeed() == 1) + return true; + else + return false; + } +private: + Boat * boat; + int key; +}; + +//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 *boat, QEvent::Type type, int key) + : QKeyEventTransition(boat,type, key) + { + this->boat = boat; + this->key = key; +#if defined(Q_OS_MAC) + setModifiers(Qt::KeypadModifier); +#endif + } +protected: + virtual bool eventTest(QEvent *event) const + { + Q_UNUSED(event); + if (!QKeyEventTransition::eventTest(event)) + return false; + if (boat->currentSpeed() >= 0) + return true; + else + return false; + + } + void onTransition() + { + //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) + { + this->boat = boat; + this->key = key; +#if defined(Q_OS_MAC) + setModifiers(Qt::KeypadModifier); +#endif + } +protected: + virtual bool eventTest(QEvent *event) const + { + Q_UNUSED(event); + if (!QKeyEventTransition::eventTest(event)) + return false; + //We have enough bomb? + if (boat->bombsLaunched() < MAX_BOMB) + return true; + else + return false; + } +private: + Boat * boat; + int key; +}; + +//This state is describing when the boat is moving right +class MoveStateRight : public QState +{ +public: + MoveStateRight(Boat *boat,QState *parent = 0) : QState(parent) + { + this->boat = boat; + } +protected: + void onEntry() + { + boat->setCurrentDirection(Boat::Right); + boat->updateBoatMovement(); + } +private: + Boat * boat; +}; + + //This state is describing when the boat is moving left +class MoveStateLeft : public QState +{ +public: + MoveStateLeft(Boat *boat,QState *parent = 0) : QState(parent) + { + this->boat = boat; + } +protected: + void onEntry() + { + 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: + StopState(Boat *boat,QState *parent = 0) : QState(parent) + { + this->boat = boat; + } +protected: + void onEntry() + { + 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: + LaunchStateRight(Boat *boat,QState *parent = 0) : QState(parent) + { + this->boat = boat; + } +protected: + void onEntry() + { + 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: + LaunchStateLeft(Boat *boat,QState *parent = 0) : QState(parent) + { + this->boat = boat; + } +protected: + void onEntry() + { + 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/animation/sub-attaq/bomb.cpp b/examples/animation/sub-attaq/bomb.cpp new file mode 100644 index 0000000..b6ae5a3 --- /dev/null +++ b/examples/animation/sub-attaq/bomb.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "bomb.h" +#include "submarine.h" +#include "pixmapitem.h" +#include "animationmanager.h" + +//Qt + +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qpropertyanimation.h" +#include "qsequentialanimationgroup.h" +#include "qanimationstate.h" +#include "qstatemachine.h" +#include "qfinalstate.h" +#else +#include <QtCore/QSequentialAnimationGroup> +#include <QtCore/QPropertyAnimation> +#include <QtCore/QAnimationState> +#include <QtCore/QStateMachine> +#include <QtCore/QFinalState> +#endif + +Bomb::Bomb(QGraphicsItem * parent, Qt::WindowFlags wFlags) + : QGraphicsWidget(parent,wFlags), launchAnimation(0) +{ + pixmapItem = new PixmapItem(QString("bomb"),GraphicsScene::Big, this); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFlags(QGraphicsItem::ItemIsMovable); + setZValue(2); + resize(pixmapItem->boundingRect().size()); +} + +void Bomb::launch(Bomb::Direction direction) +{ + 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,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationLaunchValueChanged(const QVariant &))); + + //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(launchAnimation,machine->rootState()); + + machine->setInitialState(launched); + + //End + QFinalState *final = new QFinalState(machine->rootState()); + + //### Add a nice animation when the bomb is destroyed + launched->addTransition(this, SIGNAL(bombExplosed()),final); + + //If the animation is finished, then we move to the final state + launched->addFinishedTransition(final); + + //The machine has finished to be executed, then the boat is dead + connect(machine,SIGNAL(finished()),this, SIGNAL(bombExecutionFinished())); + + machine->start(); + +} + +void Bomb::onAnimationLaunchValueChanged(const QVariant &) +{ + foreach (QGraphicsItem * item , collidingItems(Qt::IntersectsItemBoundingRect)) { + if (item->type() == SubMarine::Type) { + SubMarine *s = static_cast<SubMarine *>(item); + destroy(); + s->destroy(); + } + } +} + +void Bomb::destroy() +{ + launchAnimation->stop(); + emit bombExplosed(); +} diff --git a/examples/animation/sub-attaq/bomb.h b/examples/animation/sub-attaq/bomb.h new file mode 100644 index 0000000..9191e6e --- /dev/null +++ b/examples/animation/sub-attaq/bomb.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __BOMB__H__ +#define __BOMB__H__ + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qanimationgroup.h" +# include "qgraphicswidget.h" +#else +# include <QtGui/QGraphicsWidget> +# include <QtCore/QAnimationGroup> +#endif + +class PixmapItem; + +class Bomb : public QGraphicsWidget +{ +Q_OBJECT +Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + enum Direction { + Left = 0, + Right + }; + Bomb(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0); + void launch(Direction direction); + void destroy(); + +Q_SIGNALS: + void bombExplosed(); + void bombExecutionFinished(); + +private slots: + void onAnimationLaunchValueChanged(const QVariant &); + +private: + QAnimationGroup *launchAnimation; + PixmapItem *pixmapItem; +}; + +#endif //__BOMB__H__ diff --git a/examples/animation/sub-attaq/custompropertyanimation.cpp b/examples/animation/sub-attaq/custompropertyanimation.cpp new file mode 100644 index 0000000..45997af --- /dev/null +++ b/examples/animation/sub-attaq/custompropertyanimation.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "custompropertyanimation.h" +#include "custompropertyanimation_p.h" + +// Qt +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + + +void CustomPropertyAnimationPrivate::initDefaultStartValue() +{ + if (!animProp) + return; + QVariant def = animProp->read(); + if (def.isValid()) + convertValues(def.userType()); + if (animProp && !defaultStartValue.isValid() + && ((currentTime == 0 && (currentIteration || currentIteration == 0)) + || (currentTime == duration && currentIteration == (iterationCount - 1)))) { + setDefaultStartValue(def); + } +} + + +CustomPropertyAnimation::CustomPropertyAnimation(QObject *parent) : + QVariantAnimation(*new CustomPropertyAnimationPrivate, parent) +{ +} + +CustomPropertyAnimation::~CustomPropertyAnimation() +{ +} + +void CustomPropertyAnimation::setProperty(AbstractProperty *animProp) +{ + Q_D(CustomPropertyAnimation); + if (d->animProp == animProp) + return; + delete d->animProp; + d->animProp = animProp; +} + +/*! + \reimp + */ +void CustomPropertyAnimation::updateCurrentValue(const QVariant &value) +{ + Q_D(CustomPropertyAnimation); + if (!d->animProp || state() == QAbstractAnimation::Stopped) + return; + + d->animProp->write(value); +} + + +/*! + \reimp +*/ +void CustomPropertyAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState) +{ + Q_D(CustomPropertyAnimation); + // Initialize start value + if (oldState == QAbstractAnimation::Stopped) + d->initDefaultStartValue(); + + QVariantAnimation::updateState(oldState, newState); +} + + + +#include "moc_custompropertyanimation.cpp" + +QT_END_NAMESPACE diff --git a/examples/animation/sub-attaq/custompropertyanimation.h b/examples/animation/sub-attaq/custompropertyanimation.h new file mode 100644 index 0000000..ba6ef55 --- /dev/null +++ b/examples/animation/sub-attaq/custompropertyanimation.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMPROPERTYANIMATION_H +#define CUSTOMPROPERTYANIMATION_H + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qvariantanimation.h" +#else +# include <QtCore/qvariantanimation.h> +#endif + +class QGraphicsItem; +class CustomPropertyAnimationPrivate; + +struct AbstractProperty +{ + virtual QVariant read() const = 0; + virtual void write(const QVariant &value) = 0; +}; + + +class CustomPropertyAnimation : public QVariantAnimation +{ + Q_OBJECT + + template <typename Target, typename T, typename T2 = T> + class MemberFunctionProperty : public AbstractProperty + { + public: + typedef T (Target::*Getter)(void) const; + typedef void (Target::*Setter)(T2); + + MemberFunctionProperty(Target* target, Getter getter, Setter setter) + : m_target(target), m_getter(getter), m_setter(setter) {} + + virtual void write(const QVariant &value) + { + if (m_setter) (m_target->*m_setter)(qVariantValue<T>(value)); + } + + virtual QVariant read() const + { + if (m_getter) return qVariantFromValue<T>((m_target->*m_getter)()); + return QVariant(); + } + + private: + Target *m_target; + Getter m_getter; + Setter m_setter; + }; + +public: + CustomPropertyAnimation(QObject *parent = 0); + ~CustomPropertyAnimation(); + + template<class Target, typename T> + void setMemberFunctions(Target* target, T (Target::*getter)() const, void (Target::*setter)(const T& )) + { + setProperty(new MemberFunctionProperty<Target, T, const T&>(target, getter, setter)); + } + + template<class Target, typename T> + void setMemberFunctions(Target* target, T (Target::*getter)() const, void (Target::*setter)(T)) + { + setProperty(new MemberFunctionProperty<Target, T>(target, getter, setter)); + } + + void updateCurrentValue(const QVariant &value); + void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState); + void setProperty(AbstractProperty *animProp); + +private: + Q_DISABLE_COPY(CustomPropertyAnimation); + Q_DECLARE_PRIVATE(CustomPropertyAnimation); +}; + +#endif // CUSTOMPROPERTYANIMATION_H diff --git a/examples/animation/sub-attaq/custompropertyanimation_p.h b/examples/animation/sub-attaq/custompropertyanimation_p.h new file mode 100644 index 0000000..89fc757 --- /dev/null +++ b/examples/animation/sub-attaq/custompropertyanimation_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMPROPERTYANIMATION_P_H +#define CUSTOMPROPERTYANIMATION_P_H + +#ifdef QT_EXPERIMENTAL_SOLUTION +# include "qvariantanimation_p.h" +#else +# include <private/qvariantanimation_p.h> +#endif + +class CustomPropertyAnimationPrivate : public QVariantAnimationPrivate +{ + Q_DECLARE_PUBLIC(CustomPropertyAnimation) +public: + CustomPropertyAnimationPrivate() : QVariantAnimationPrivate(), animProp(0) + { + } + + void initDefaultStartValue(); + + AbstractProperty *animProp; +}; + +#endif //QTCUSTOMPROPERTYANIMATION_P_H diff --git a/examples/animation/sub-attaq/data.xml b/examples/animation/sub-attaq/data.xml new file mode 100644 index 0000000..41d4754 --- /dev/null +++ b/examples/animation/sub-attaq/data.xml @@ -0,0 +1,15 @@ +<?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="2"/> + </level> + <level id="1" name="Seaman apprentice"> + <subinstance type="0" nb="4"/> + </level> + </levels> +</subattaq> diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp new file mode 100644 index 0000000..a7f4c1b --- /dev/null +++ b/examples/animation/sub-attaq/graphicsscene.cpp @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "graphicsscene.h" +#include "states.h" +#include "boat.h" +#include "submarine.h" +#include "torpedo.h" +#include "bomb.h" +#include "pixmapitem.h" +#include "custompropertyanimation.h" +#include "animationmanager.h" + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qpropertyanimation.h" +#include "qsequentialanimationgroup.h" +#include "qparallelanimationgroup.h" +#include "qstatemachine.h" +#include "qanimationstate.h" +#include "qfinalstate.h" +#include "qpauseanimation.h" +#else +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QParallelAnimationGroup> +#include <QStateMachine> +#include <QAnimationState> +#include <QFinalState> +#include <QPauseAnimation> +#endif +#include <QAction> +#include <QDir> +#include <QApplication> +#include <QMessageBox> +#include <QGraphicsView> +#include <QGraphicsSceneMouseEvent> +#include <QXmlStreamReader> + +//helper function that creates an animation for position and inserts it into group +static CustomPropertyAnimation *addGraphicsItemPosAnimation(QSequentialAnimationGroup *group, + QGraphicsItem *item, const QPointF &endPos) +{ + CustomPropertyAnimation *ret = new CustomPropertyAnimation(group); + ret->setMemberFunctions(item, &QGraphicsItem::pos, &QGraphicsItem::setPos); + ret->setEndValue(endPos); + ret->setDuration(200); + ret->setEasingCurve(QEasingCurve::OutElastic); + group->addPause(50); + return ret; +} + +//helper function that creates an animation for opacity and inserts it into group +static void addGraphicsItemFadeoutAnimation(QAnimationGroup *group, QGraphicsItem *item) +{ +#if QT_VERSION >=0x040500 + CustomPropertyAnimation *anim = new CustomPropertyAnimation(group); + anim->setMemberFunctions(item, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim->setDuration(800); + anim->setEndValue(0); + anim->setEasingCurve(QEasingCurve::OutQuad); +#else + // work around for a bug where we don't transition if the duration is zero. + QtPauseAnimation *anim = new QtPauseAnimation(group); + anim->setDuration(1); +#endif +} + +GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode) + : QGraphicsScene(x,y,width,height), mode(mode), newAction(0), quitAction(0), boat(0) +{ + backgroundItem = new PixmapItem(QString("background"),mode); + backgroundItem->setZValue(1); + backgroundItem->setPos(0,0); + addItem(backgroundItem); + + PixmapItem *surfaceItem = new PixmapItem(QString("surface"),mode); + surfaceItem->setZValue(3); + surfaceItem->setPos(0,sealLevel() - surfaceItem->boundingRect().height()/2); + addItem(surfaceItem); + + //parse the xml that contain all data of the game + QXmlStreamReader reader; + QFile file(QDir::currentPath() + "/data.xml"); + file.open(QIODevice::ReadOnly); + reader.setDevice(&file); + LevelDescription currentLevel; + while (!reader.atEnd()) { + reader.readNext(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == "submarine") + { + SubmarineDescription desc; + desc.name = reader.attributes().value("name").toString(); + desc.points = reader.attributes().value("points").toString().toInt(); + desc.type = reader.attributes().value("type").toString().toInt(); + submarinesData.append(desc); + } + if (reader.name() == "level") + { + currentLevel.id = reader.attributes().value("id").toString().toInt(); + currentLevel.name = reader.attributes().value("name").toString(); + } + if (reader.name() == "subinstance") + { + currentLevel.submarines.append(qMakePair(reader.attributes().value("type").toString().toInt(),reader.attributes().value("nb").toString().toInt())); + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement) { + if (reader.name() == "level") + { + levelsData.insert(currentLevel.id,currentLevel); + currentLevel.submarines.clear(); + } + } + } +} + +qreal GraphicsScene::sealLevel() const +{ + if (mode == Big) + return 220; + else + return 160; +} + +void GraphicsScene::setupScene(const QList<QAction *> &actions) +{ + newAction = actions.at(0); + quitAction = actions.at(1); + + QGraphicsItem *logo_s = addWelcomeItem(QPixmap(":/logo-s")); + QGraphicsItem *logo_u = addWelcomeItem(QPixmap(":/logo-u")); + QGraphicsItem *logo_b = addWelcomeItem(QPixmap(":/logo-b")); + QGraphicsItem *logo_dash = addWelcomeItem(QPixmap(":/logo-dash")); + QGraphicsItem *logo_a = addWelcomeItem(QPixmap(":/logo-a")); + QGraphicsItem *logo_t = addWelcomeItem(QPixmap(":/logo-t")); + QGraphicsItem *logo_t2 = addWelcomeItem(QPixmap(":/logo-t2")); + QGraphicsItem *logo_a2 = addWelcomeItem(QPixmap(":/logo-a2")); + QGraphicsItem *logo_q = addWelcomeItem(QPixmap(":/logo-q")); + QGraphicsItem *logo_excl = addWelcomeItem(QPixmap(":/logo-excl")); + logo_s->setZValue(3); + logo_u->setZValue(4); + logo_b->setZValue(5); + logo_dash->setZValue(6); + logo_a->setZValue(7); + logo_t->setZValue(8); + logo_t2->setZValue(9); + logo_a2->setZValue(10); + logo_q->setZValue(11); + logo_excl->setZValue(12); + logo_s->setPos(QPointF(-1000, -1000)); + logo_u->setPos(QPointF(-800, -1000)); + logo_b->setPos(QPointF(-600, -1000)); + logo_dash->setPos(QPointF(-400, -1000)); + logo_a->setPos(QPointF(1000, 2000)); + logo_t->setPos(QPointF(800, 2000)); + logo_t2->setPos(QPointF(600, 2000)); + logo_a2->setPos(QPointF(400, 2000)); + logo_q->setPos(QPointF(200, 2000)); + logo_excl->setPos(QPointF(0, 2000)); + + QSequentialAnimationGroup * lettersGroupMoving = new QSequentialAnimationGroup(this); + QParallelAnimationGroup * lettersGroupFading = new QParallelAnimationGroup(this); + + //creation of the animations for moving letters + addGraphicsItemPosAnimation(lettersGroupMoving, logo_s, QPointF(300, 150)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_u, QPointF(350, 150)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_b, QPointF(400, 120)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_dash, QPointF(460, 150)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_a, QPointF(350, 250)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_t, QPointF(400, 250)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_t2, QPointF(430, 250)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_a2, QPointF(465, 250)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_q, QPointF(510, 250)); + addGraphicsItemPosAnimation(lettersGroupMoving, logo_excl, QPointF(570, 220)); + + //creation of the animations for fading out the letters + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_s); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_u); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_b); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_dash); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_a); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_t); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_t2); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_a2); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_q); + addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_excl); + connect(lettersGroupFading, SIGNAL(finished()), this, SLOT(onIntroAnimationFinished())); + + QStateMachine *machine = new QStateMachine(this); + + //This state is when the player is playing + PlayState *gameState = new PlayState(this,machine->rootState()); + + //Final state + QFinalState *final = new QFinalState(machine->rootState()); + + //Animation when the player enter in the game + QAnimationState *animationState = new QAnimationState(lettersGroupMoving, machine->rootState()); + animationState->addAnimatedTransition(newAction, SIGNAL(triggered()),gameState,lettersGroupFading); + + //New Game is triggered then player start playing + gameState->addTransition(newAction, SIGNAL(triggered()),gameState); + + //Wanna quit, then connect to CTRL+Q + gameState->addTransition(quitAction, SIGNAL(triggered()),final); + animationState->addTransition(quitAction, SIGNAL(triggered()),final); + + //Welcome screen is the initial state + machine->setInitialState(animationState); + + machine->start(); + + //We reach the final state, then we quit + connect(machine,SIGNAL(finished()),this, SLOT(onQuitGameTriggered())); +} + +void GraphicsScene::addItem(Bomb *bomb) +{ + bombs.insert(bomb); + connect(bomb,SIGNAL(bombExecutionFinished()),this, SLOT(onBombExecutionFinished())); + QGraphicsScene::addItem(bomb); +} + +void GraphicsScene::addItem(Torpedo *torpedo) +{ + torpedos.insert(torpedo); + connect(torpedo,SIGNAL(torpedoExecutionFinished()),this, SLOT(onTorpedoExecutionFinished())); + QGraphicsScene::addItem(torpedo); +} + +void GraphicsScene::addItem(SubMarine *submarine) +{ + submarines.insert(submarine); + connect(submarine,SIGNAL(subMarineExecutionFinished()),this, SLOT(onSubMarineExecutionFinished())); + QGraphicsScene::addItem(submarine); +} + +void GraphicsScene::addItem(QGraphicsItem *item) +{ + QGraphicsScene::addItem(item); +} + +void GraphicsScene::mousePressEvent (QGraphicsSceneMouseEvent * event) +{ + event->ignore(); +} + +void GraphicsScene::onQuitGameTriggered() +{ + qApp->closeAllWindows(); +} + +void GraphicsScene::onBombExecutionFinished() +{ + Bomb *bomb = qobject_cast<Bomb *>(sender()); + bombs.remove(bomb); + bomb->deleteLater(); + if (boat) + boat->setBombsLaunched(boat->bombsLaunched() - 1); +} + +void GraphicsScene::onTorpedoExecutionFinished() +{ + Torpedo *torpedo = qobject_cast<Torpedo *>(sender()); + torpedos.remove(torpedo); + torpedo->deleteLater(); +} + +void GraphicsScene::onSubMarineExecutionFinished() +{ + SubMarine *submarine = qobject_cast<SubMarine *>(sender()); + submarines.remove(submarine); + if (submarines.count() == 0) { + emit allSubMarineDestroyed(submarine->points()); + } else { + emit subMarineDestroyed(submarine->points()); + } + submarine->deleteLater(); +} + +int GraphicsScene::remainingSubMarines() const +{ + return submarines.count(); +} + +void GraphicsScene::clearScene() +{ + foreach (SubMarine *sub,submarines) { + sub->destroy(); + delete sub; + } + + foreach (Torpedo *torpedo,torpedos) { + torpedo->destroy(); + delete torpedo; + } + + foreach (Bomb *bomb,bombs) { + bomb->destroy(); + delete bomb; + } + + submarines.clear(); + bombs.clear(); + torpedos.clear(); + + AnimationManager::self()->unregisterAllAnimations(); + + if (boat) { + delete boat; + boat = 0; + } +} + +QGraphicsPixmapItem *GraphicsScene::addWelcomeItem(const QPixmap &pm) +{ + QGraphicsPixmapItem *item = addPixmap(pm); + welcomeItems << item; + return item; +} + +void GraphicsScene::onIntroAnimationFinished() +{ + qDeleteAll(welcomeItems); + welcomeItems.clear(); +} + diff --git a/examples/animation/sub-attaq/graphicsscene.h b/examples/animation/sub-attaq/graphicsscene.h new file mode 100644 index 0000000..875f59f --- /dev/null +++ b/examples/animation/sub-attaq/graphicsscene.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __GRAPHICSSCENE__H__ +#define __GRAPHICSSCENE__H__ + +//Qt +#include <QGraphicsScene> +#include <QSet> + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qstate.h" +#else +# include <QState> +#endif + + +class Boat; +class SubMarine; +class Torpedo; +class Bomb; +class PixmapItem; +class QAction; + +class GraphicsScene : public QGraphicsScene +{ +Q_OBJECT +public: + enum Mode { + Big = 0, + Small + }; + + struct SubmarineDescription { + int type; + int points; + QString name; + }; + + struct LevelDescription { + int id; + QString name; + QList<QPair<int,int> > submarines; + }; + + GraphicsScene(int x, int y, int width, int height, Mode mode = Big); + qreal sealLevel() const; + void setupScene(const QList<QAction *> &actions); + void addItem(Bomb *bomb); + void addItem(Torpedo *torpedo); + void addItem(SubMarine *submarine); + void addItem(QGraphicsItem *item); + int remainingSubMarines() const; + void clearScene(); + QGraphicsPixmapItem *addWelcomeItem(const QPixmap &pm); + +Q_SIGNALS: + void subMarineDestroyed(int); + void allSubMarineDestroyed(int); + +protected: + void mousePressEvent (QGraphicsSceneMouseEvent * event); + +private slots: + void onQuitGameTriggered(); + void onBombExecutionFinished(); + void onTorpedoExecutionFinished(); + void onSubMarineExecutionFinished(); + void onIntroAnimationFinished(); + +private: + Mode mode; + PixmapItem *backgroundItem; + QAction * newAction; + QAction * quitAction; + Boat *boat; + QSet<SubMarine *> submarines; + QSet<Bomb *> bombs; + QSet<Torpedo *> torpedos; + QVector<QGraphicsPixmapItem *> welcomeItems; + QVector<SubmarineDescription> submarinesData; + QHash<int, LevelDescription> levelsData; + + friend class PauseState; + friend class PlayState; + friend class LostState; + friend class WinState; +}; + +#endif //__GRAPHICSSCENE__H__ + diff --git a/examples/animation/sub-attaq/main.cpp b/examples/animation/sub-attaq/main.cpp new file mode 100644 index 0000000..ffaa86f --- /dev/null +++ b/examples/animation/sub-attaq/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(subattaq); + + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + + MainWindow w; + w.show(); + + return app.exec(); +} diff --git a/examples/animation/sub-attaq/mainwindow.cpp b/examples/animation/sub-attaq/mainwindow.cpp new file mode 100644 index 0000000..c25b9ef --- /dev/null +++ b/examples/animation/sub-attaq/mainwindow.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "mainwindow.h" +#include "graphicsscene.h" + +#ifndef QT_NO_OPENGL + #include <QtOpenGL/QtOpenGL> +#endif +//Qt +#include <QGraphicsView> + +MainWindow::MainWindow() : QMainWindow(0) +{ + QMenuBar *menuBar = new QMenuBar; + QMenu *file = new QMenu(tr("&File"),menuBar); + + QAction *newAction = new QAction(tr("New Game"),file); + newAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N)); + file->addAction(newAction); + QAction *quitAction = new QAction(tr("Quit"),file); + quitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); + file->addAction(quitAction); + + menuBar->addMenu(file); + setMenuBar(menuBar); + + QStringList list = QApplication::arguments(); + if (list.contains("-fullscreen")) { + scene = new GraphicsScene(0, 0, 750, 400,GraphicsScene::Small); + setWindowState(Qt::WindowFullScreen); + } else { + scene = new GraphicsScene(0, 0, 880, 630); + layout()->setSizeConstraint(QLayout::SetFixedSize); + } + + view = new QGraphicsView(scene,this); + view->setAlignment(Qt::AlignLeft | Qt::AlignTop); + QList<QAction *> actions; + actions << newAction << quitAction; + scene->setupScene(actions); +#ifndef QT_NO_OPENGL + view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); +#endif + + setCentralWidget(view); + +} + +MainWindow::~MainWindow() +{ +} + diff --git a/examples/animation/sub-attaq/mainwindow.h b/examples/animation/sub-attaq/mainwindow.h new file mode 100644 index 0000000..6289b3f --- /dev/null +++ b/examples/animation/sub-attaq/mainwindow.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __MAINWINDOW__H__ +#define __MAINWINDOW__H__ + +//Qt +#include <QMainWindow> + +class GraphicsScene; +class QGraphicsView; + +class MainWindow : public QMainWindow +{ +Q_OBJECT +public: + MainWindow(); + ~MainWindow(); + +private: + GraphicsScene *scene; + QGraphicsView *view; +}; + +#endif //__MAINWINDOW__H__ diff --git a/examples/animation/sub-attaq/pics/big/background.png b/examples/animation/sub-attaq/pics/big/background.png Binary files differnew file mode 100644 index 0000000..9f58157 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/background.png diff --git a/examples/animation/sub-attaq/pics/big/boat.png b/examples/animation/sub-attaq/pics/big/boat.png Binary files differnew file mode 100644 index 0000000..be82dff --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/boat.png diff --git a/examples/animation/sub-attaq/pics/big/bomb.png b/examples/animation/sub-attaq/pics/big/bomb.png Binary files differnew file mode 100644 index 0000000..3af5f2f --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/bomb.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png Binary files differnew file mode 100644 index 0000000..c9fd8b0 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png Binary files differnew file mode 100644 index 0000000..7528f2d --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png Binary files differnew file mode 100644 index 0000000..aae9c9c --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png Binary files differnew file mode 100644 index 0000000..d697c1b --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png Binary files differnew file mode 100644 index 0000000..88ca514 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png Binary files differnew file mode 100644 index 0000000..524f589 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png Binary files differnew file mode 100644 index 0000000..2cca1e8 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png Binary files differnew file mode 100644 index 0000000..82100a8 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png diff --git a/examples/animation/sub-attaq/pics/big/submarine.png b/examples/animation/sub-attaq/pics/big/submarine.png Binary files differnew file mode 100644 index 0000000..df435dc --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/submarine.png diff --git a/examples/animation/sub-attaq/pics/big/surface.png b/examples/animation/sub-attaq/pics/big/surface.png Binary files differnew file mode 100644 index 0000000..4eba29e --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/surface.png diff --git a/examples/animation/sub-attaq/pics/big/torpedo.png b/examples/animation/sub-attaq/pics/big/torpedo.png Binary files differnew file mode 100644 index 0000000..f9c2687 --- /dev/null +++ b/examples/animation/sub-attaq/pics/big/torpedo.png diff --git a/examples/animation/sub-attaq/pics/scalable/background-n810.svg b/examples/animation/sub-attaq/pics/scalable/background-n810.svg new file mode 100644 index 0000000..ece9f7a --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/background.svg b/examples/animation/sub-attaq/pics/scalable/background.svg new file mode 100644 index 0000000..0be2680 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/boat.svg b/examples/animation/sub-attaq/pics/scalable/boat.svg new file mode 100644 index 0000000..5298821b --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/bomb.svg b/examples/animation/sub-attaq/pics/scalable/bomb.svg new file mode 100644 index 0000000..294771a --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/sand.svg b/examples/animation/sub-attaq/pics/scalable/sand.svg new file mode 100644 index 0000000..8af11b7 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/see.svg b/examples/animation/sub-attaq/pics/scalable/see.svg new file mode 100644 index 0000000..0666691 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/sky.svg b/examples/animation/sub-attaq/pics/scalable/sky.svg new file mode 100644 index 0000000..1546c08 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/sub-attaq.svg b/examples/animation/sub-attaq/pics/scalable/sub-attaq.svg new file mode 100644 index 0000000..b075179 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/submarine.svg b/examples/animation/sub-attaq/pics/scalable/submarine.svg new file mode 100644 index 0000000..8a0ffdd --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/surface.svg b/examples/animation/sub-attaq/pics/scalable/surface.svg new file mode 100644 index 0000000..40ed239 --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/scalable/torpedo.svg b/examples/animation/sub-attaq/pics/scalable/torpedo.svg new file mode 100644 index 0000000..48e429d --- /dev/null +++ b/examples/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/animation/sub-attaq/pics/small/background.png b/examples/animation/sub-attaq/pics/small/background.png Binary files differnew file mode 100644 index 0000000..5ad3db6 --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/background.png diff --git a/examples/animation/sub-attaq/pics/small/boat.png b/examples/animation/sub-attaq/pics/small/boat.png Binary files differnew file mode 100644 index 0000000..114ccc3 --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/boat.png diff --git a/examples/animation/sub-attaq/pics/small/bomb.png b/examples/animation/sub-attaq/pics/small/bomb.png Binary files differnew file mode 100644 index 0000000..3af5f2f --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/bomb.png diff --git a/examples/animation/sub-attaq/pics/small/submarine.png b/examples/animation/sub-attaq/pics/small/submarine.png Binary files differnew file mode 100644 index 0000000..0c0c350 --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/submarine.png diff --git a/examples/animation/sub-attaq/pics/small/surface.png b/examples/animation/sub-attaq/pics/small/surface.png Binary files differnew file mode 100644 index 0000000..06d0e47 --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/surface.png diff --git a/examples/animation/sub-attaq/pics/small/torpedo.png b/examples/animation/sub-attaq/pics/small/torpedo.png Binary files differnew file mode 100644 index 0000000..f9c2687 --- /dev/null +++ b/examples/animation/sub-attaq/pics/small/torpedo.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-a.png b/examples/animation/sub-attaq/pics/welcome/logo-a.png Binary files differnew file mode 100644 index 0000000..67dd76d --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-a.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-a2.png b/examples/animation/sub-attaq/pics/welcome/logo-a2.png Binary files differnew file mode 100644 index 0000000..17668b0 --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-a2.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-b.png b/examples/animation/sub-attaq/pics/welcome/logo-b.png Binary files differnew file mode 100644 index 0000000..cf6c045 --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-b.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-dash.png b/examples/animation/sub-attaq/pics/welcome/logo-dash.png Binary files differnew file mode 100644 index 0000000..219233c --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-dash.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-excl.png b/examples/animation/sub-attaq/pics/welcome/logo-excl.png Binary files differnew file mode 100644 index 0000000..8dd0a2e --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-excl.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-q.png b/examples/animation/sub-attaq/pics/welcome/logo-q.png Binary files differnew file mode 100644 index 0000000..86e588d --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-q.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-s.png b/examples/animation/sub-attaq/pics/welcome/logo-s.png Binary files differnew file mode 100644 index 0000000..7b6a36e --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-s.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-t.png b/examples/animation/sub-attaq/pics/welcome/logo-t.png Binary files differnew file mode 100644 index 0000000..b2e3526 --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-t.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-t2.png b/examples/animation/sub-attaq/pics/welcome/logo-t2.png Binary files differnew file mode 100644 index 0000000..b11a778 --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-t2.png diff --git a/examples/animation/sub-attaq/pics/welcome/logo-u.png b/examples/animation/sub-attaq/pics/welcome/logo-u.png Binary files differnew file mode 100644 index 0000000..24eede8 --- /dev/null +++ b/examples/animation/sub-attaq/pics/welcome/logo-u.png diff --git a/examples/animation/sub-attaq/pixmapitem.cpp b/examples/animation/sub-attaq/pixmapitem.cpp new file mode 100644 index 0000000..aa8b552 --- /dev/null +++ b/examples/animation/sub-attaq/pixmapitem.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "pixmapitem.h" + +//Qt +#include <QDir> + +PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent) : QGraphicsPixmapItem(parent),name(fileName) +{ + loadPixmap(mode); +} + +void PixmapItem::loadPixmap(GraphicsScene::Mode mode) +{ + if (mode == GraphicsScene::Big) + setPixmap(":/big/" + name); + else + setPixmap(":/small/" + name); +} diff --git a/examples/animation/sub-attaq/pixmapitem.h b/examples/animation/sub-attaq/pixmapitem.h new file mode 100644 index 0000000..f3c1a41 --- /dev/null +++ b/examples/animation/sub-attaq/pixmapitem.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __PIXMAPITEM__H__ +#define __PIXMAPITEM__H__ + +//Own +#include "graphicsscene.h" + +//Qt +#include <QGraphicsPixmapItem> + +class PixmapItem : public QGraphicsPixmapItem +{ +public: + PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem * parent = 0); + +private: + void loadPixmap(GraphicsScene::Mode mode); + + QString name; + QPixmap pixmap; +}; + +#endif //__PIXMAPITEM__H__ diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp new file mode 100644 index 0000000..32e0bb8 --- /dev/null +++ b/examples/animation/sub-attaq/states.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "states.h" +#include "graphicsscene.h" +#include "boat.h" +#include "submarine.h" +#include "torpedo.h" +#include "animationmanager.h" + +//Qt +#include <QMessageBox> +#include <QGraphicsView> +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qstatemachine.h" +#include "qkeyeventtransition.h" +#include "qsignalevent.h" +#include "qfinalstate.h" +#else +#include <QtCore/QStateMachine> +#include <QtGui/QKeyEventTransition> +#include <QtCore/QSignalEvent> +#include <QFinalState> +#endif + +PlayState::PlayState(GraphicsScene *scene, QState *parent) + : QState(parent), + scene(scene), + machine(0), + currentLevel(0), + score(0) +{ +} + +PlayState::~PlayState() +{ +} + +void PlayState::onEntry() +{ + //We are now playing? + if (machine) { + machine->stop(); + scene->clearScene(); + delete machine; + } + + machine = new QStateMachine(this); + + //This state is when player is playing + QState *playState = new QState(machine->rootState()); + + initializeLevel(); + + //This state is when the game is paused + PauseState *pauseState = new PauseState(scene, machine->rootState()); + + //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(playState); + + //Pause "P" is triggered, the player pause the game + playState->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->rootState()); + + //This state is when player have won + WinState *winState = new WinState(scene, this, machine->rootState()); + + //The boat has been destroyed then the game is finished + playState->addTransition(scene->boat, SIGNAL(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 + playState->addTransition(winTransition); + + //This state is an animation when the score changed + UpdateScoreState *scoreState = new UpdateScoreState(this, machine->rootState()); + + //This transition update the score when a submarine die + UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, scoreState); + + //The boat has been destroyed then the game is finished + playState->addTransition(scoreTransition); + + //We go back to play state + scoreState->addFinishedTransition(playState); + + //We start playing!!! + machine->setInitialState(playState); + + //Final state + QFinalState *final = new QFinalState(machine->rootState()); + + //We win we should reach the final state + winState->addFinishedTransition(final); + + //We lost we should reach the final state + lostState->addFinishedTransition(final); + + machine->start(); +} + +void PlayState::initializeLevel() +{ + scene->boat = new Boat(); + scene->addItem(scene->boat); + scene->setFocusItem(scene->boat,Qt::OtherFocusReason); + scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height()); + + GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(currentLevel); + + for (int i = 0; i < currentLevelDescription.submarines.size(); ++i ) { + + QPair<int,int> subContent = currentLevelDescription.submarines.at(i); + 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 = (qrand() % 15 + 1); + qreal x = random == 13 || random == 5 ? 0 : scene->width() - sub->size().width(); + qreal y = scene->height() -(qrand() % 150 + 1) - sub->size().height(); + sub->setPos(x,y); + sub->setCurrentDirection(x == 0 ? SubMarine::Right : SubMarine::Left); + sub->setCurrentSpeed(qrand() % 3 + 1); + } + } +} + +/** Pause State */ +PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent),scene(scene) +{ +} +void PauseState::onEntry() +{ + AnimationManager::self()->pauseAll(); + scene->boat->setEnabled(false); +} +void PauseState::onExit() +{ + 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() +{ + //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 have only one view + QMessageBox::information(scene->views().at(0),"You lose",message); +} + +/** Win State */ +WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) +{ +} + +void WinState::onEntry() +{ + //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.").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 have only one view + QMessageBox::information(scene->views().at(0),"You win",message); +} + +/** UpdateScore State */ +UpdateScoreState::UpdateScoreState(PlayState *game, QState *parent) : QAnimationState(parent) +{ + this->game = game; +} +void UpdateScoreState::onEntry() +{ + //### Make a nice anim to update the score in the scene + QAnimationState::onEntry(); +} + +/** Win transition */ +UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) + : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int)), QList<QAbstractState*>() << target), + game(game) +{ +} + +bool UpdateScoreTransition::eventTest(QEvent *event) const +{ + if (!QSignalTransition::eventTest(event)) + return false; + else { + QSignalEvent *se = static_cast<QSignalEvent*>(event); + game->score += se->arguments().at(0).toInt(); + return true; + } +} + +/** Win transition */ +WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) + : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int)), QList<QAbstractState*>() << target), + game(game) +{ +} + +bool WinTransition::eventTest(QEvent *event) const +{ + if (!QSignalTransition::eventTest(event)) + return false; + else { + QSignalEvent *se = static_cast<QSignalEvent*>(event); + game->score += se->arguments().at(0).toInt(); + return true; + } +} diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h new file mode 100644 index 0000000..1001827 --- /dev/null +++ b/examples/animation/sub-attaq/states.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STATES_H +#define STATES_H + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qstate.h" +#include "qsignaltransition.h" +#include "qanimationstate.h" +#include "qpropertyanimation.h" +#else +#include <QState> +#include <QSignalTransition> +#include <QAnimationState> +#include <QPropertyAnimation> +#endif +#include <QSet> + +class GraphicsScene; +class Boat; +class SubMarine; +class QStateMachine; + +class PlayState : public QState +{ +public: + PlayState(GraphicsScene *scene, QState *parent = 0); + ~PlayState(); + void initializeLevel(); + + protected: + void onEntry(); + +private : + GraphicsScene *scene; + QStateMachine *machine; + int currentLevel; + int score; + QState *parallelChild; + + friend class UpdateScoreState; + friend class UpdateScoreTransition; + friend class WinTransition; + friend class WinState; + friend class LostState; +}; + +class PauseState : public QState +{ +public: + PauseState(GraphicsScene *scene, QState *parent = 0); + +protected: + void onEntry(); + void onExit(); +private : + GraphicsScene *scene; + Boat *boat; +}; + +class LostState : public QState +{ +public: + LostState(GraphicsScene *scene, PlayState *game, QState *parent = 0); + +protected: + void onEntry(); +private : + GraphicsScene *scene; + PlayState *game; +}; + +class WinState : public QState +{ +public: + WinState(GraphicsScene *scene, PlayState *game, QState *parent = 0); + +protected: + void onEntry(); +private : + GraphicsScene *scene; + PlayState *game; +}; + +class UpdateScoreState : public QAnimationState +{ +public: + UpdateScoreState(PlayState *game, QState *parent); +protected: + void onEntry(); +private: + QPropertyAnimation *scoreAnimation; + PlayState *game; +}; + +//These transtion is used to update the score +class UpdateScoreTransition : public QSignalTransition +{ +public: + UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target); +protected: + virtual bool eventTest(QEvent *event) const; +private: + PlayState * game; +}; + +//These transtion test if we have won the game +class WinTransition : public QSignalTransition +{ +public: + WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target); +protected: + virtual bool eventTest(QEvent *event) const; +private: + PlayState * game; +}; + +#endif // STATES_H diff --git a/examples/animation/sub-attaq/sub-attaq.pro b/examples/animation/sub-attaq/sub-attaq.pro new file mode 100644 index 0000000..d8de6f5 --- /dev/null +++ b/examples/animation/sub-attaq/sub-attaq.pro @@ -0,0 +1,36 @@ +# ##################################################################### +# Automatically generated by qmake (2.01a) Thu Oct 9 10:53:30 2008 +# ##################################################################### +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . +QT+= xml +contains(QT_CONFIG, opengl):QT += opengl + +# Input +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 \ + custompropertyanimation_p.h \ + custompropertyanimation.h +SOURCES += boat.cpp \ + bomb.cpp \ + main.cpp \ + mainwindow.cpp \ + submarine.cpp \ + torpedo.cpp \ + pixmapitem.cpp \ + graphicsscene.cpp \ + animationmanager.cpp \ + states.cpp \ + custompropertyanimation.cpp +RESOURCES += subattaq.qrc diff --git a/examples/animation/sub-attaq/subattaq.qrc b/examples/animation/sub-attaq/subattaq.qrc new file mode 100644 index 0000000..c76f8ef --- /dev/null +++ b/examples/animation/sub-attaq/subattaq.qrc @@ -0,0 +1,38 @@ +<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> + </qresource> +</RCC> diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp new file mode 100644 index 0000000..481c748 --- /dev/null +++ b/examples/animation/sub-attaq/submarine.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "submarine.h" +#include "submarine_p.h" +#include "torpedo.h" +#include "pixmapitem.h" +#include "graphicsscene.h" +#include "animationmanager.h" +#include "custompropertyanimation.h" + +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qpropertyanimation.h" +#include "qstatemachine.h" +#include "qfinalstate.h" +#include "qanimationstate.h" +#include "qsequentialanimationgroup.h" +#else +#include <QPropertyAnimation> +#include <QStateMachine> +#include <QFinalState> +#include <QAnimationState> +#include <QSequentialAnimationGroup> +#endif + +static QAbstractAnimation *setupDestroyAnimation(SubMarine *sub) +{ + QSequentialAnimationGroup *group = new QSequentialAnimationGroup(sub); +#if QT_VERSION >=0x040500 + PixmapItem *step1 = new PixmapItem(QString("explosion/submarine/step1"),GraphicsScene::Big, sub); + step1->setZValue(6); + PixmapItem *step2 = new PixmapItem(QString("explosion/submarine/step2"),GraphicsScene::Big, sub); + step2->setZValue(6); + PixmapItem *step3 = new PixmapItem(QString("explosion/submarine/step3"),GraphicsScene::Big, sub); + step3->setZValue(6); + PixmapItem *step4 = new PixmapItem(QString("explosion/submarine/step4"),GraphicsScene::Big, sub); + step4->setZValue(6); + step1->setOpacity(0); + step2->setOpacity(0); + step3->setOpacity(0); + step4->setOpacity(0); + CustomPropertyAnimation *anim1 = new CustomPropertyAnimation(sub); + anim1->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim1->setDuration(100); + anim1->setEndValue(1); + CustomPropertyAnimation *anim2 = new CustomPropertyAnimation(sub); + anim2->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim2->setDuration(100); + anim2->setEndValue(1); + CustomPropertyAnimation *anim3 = new CustomPropertyAnimation(sub); + anim3->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim3->setDuration(100); + anim3->setEndValue(1); + CustomPropertyAnimation *anim4 = new CustomPropertyAnimation(sub); + anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim4->setDuration(100); + anim4->setEndValue(1); + group->addAnimation(anim1); + group->addAnimation(anim2); + group->addAnimation(anim3); + group->addAnimation(anim4); +#else + // work around for a bug where we don't transition if the duration is zero. + QtPauseAnimation *anim = new QtPauseAnimation(group); + anim->setDuration(1); + group->addAnimation(anim); +#endif + AnimationManager::self()->registerAnimation(group); + return group; +} + + +SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * parent, Qt::WindowFlags wFlags) + : QGraphicsWidget(parent,wFlags), subType(type), subName(name), subPoints(points), speed(0), direction(SubMarine::None) +{ + pixmapItem = new PixmapItem(QString("submarine"),GraphicsScene::Big, this); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setZValue(5); + setFlags(QGraphicsItem::ItemIsMovable); + resize(pixmapItem->boundingRect().width(),pixmapItem->boundingRect().height()); + setTransformOrigin(boundingRect().center()); + + //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->rootState()); + + //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, SIGNAL(subMarineStateChanged()),moving); + + //This is the initial state of the machine + machine->setInitialState(moving); + + //End + QFinalState *final = new QFinalState(machine->rootState()); + + //If the moving animation is finished we move to the return state + movement->addFinishedTransition(rotation); + + //If the return animation is finished we move to the moving state + rotation->addFinishedTransition(movement); + + //This state play the destroyed animation + QAnimationState *destroyedState = new QAnimationState(machine->rootState()); + destroyedState->addAnimation(setupDestroyAnimation(this)); + + //Play a nice animation when the submarine is destroyed + moving->addTransition(this, SIGNAL(subMarineDestroyed()),destroyedState); + + //Transition to final state when the destroyed animation is finished + destroyedState->addFinishedTransition(final); + + //The machine has finished to be executed, then the submarine is dead + connect(machine,SIGNAL(finished()),this, SIGNAL(subMarineExecutionFinished())); + + machine->start(); +} + +int SubMarine::points() +{ + return subPoints; +} + +void SubMarine::setCurrentDirection(SubMarine::Movement direction) +{ + if (this->direction == direction) + return; + if (direction == SubMarine::Right && this->direction == SubMarine::None) { + setYRotation(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(x(), y()); + torp->setCurrentSpeed(speed); + torp->launch(); +} + +void SubMarine::destroy() +{ + emit subMarineDestroyed(); +} + +int SubMarine::type() const +{ + return Type; +} diff --git a/examples/animation/sub-attaq/submarine.h b/examples/animation/sub-attaq/submarine.h new file mode 100644 index 0000000..562b4cf --- /dev/null +++ b/examples/animation/sub-attaq/submarine.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __SUBMARINE__H__ +#define __SUBMARINE__H__ + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qvariantanimation.h" +#include "qgraphicswidget.h" +#else +#include <QVariantAnimation> +#include <QGraphicsWidget> +#endif + +class PixmapItem; + +class Torpedo; + +class SubMarine : public QGraphicsWidget +{ +Q_OBJECT +public: + enum Movement { + None = 0, + Left, + Right + }; + enum { Type = UserType + 1 }; + SubMarine(int type, const QString &name, int points, QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0); + + int points(); + + void setCurrentDirection(Movement direction); + enum Movement currentDirection() const; + + void setCurrentSpeed(int speed); + int currentSpeed() const; + + void launchTorpedo(int speed); + void destroy(); + + virtual int type() const; + +Q_SIGNALS: + void subMarineDestroyed(); + void subMarineExecutionFinished(); + void subMarineStateChanged(); + +private: + int subType; + QString subName; + int subPoints; + int speed; + Movement direction; + PixmapItem *pixmapItem; +}; + +#endif //__SUBMARINE__H__ diff --git a/examples/animation/sub-attaq/submarine_p.h b/examples/animation/sub-attaq/submarine_p.h new file mode 100644 index 0000000..5aa84b6 --- /dev/null +++ b/examples/animation/sub-attaq/submarine_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SUBMARINE_P_H +#define SUBMARINE_P_H + +//Own +#include "animationmanager.h" +#include "submarine.h" + +//Qt +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qanimationstate.h" +#include "qpropertyanimation.h" +#else +#include <QAnimationState> +#include <QPropertyAnimation> +#endif +#include <QGraphicsScene> + + +//This state is describing when the boat is moving right +class MovementState : public QAnimationState +{ +Q_OBJECT +public: + MovementState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent) + { + movementAnimation = new QPropertyAnimation(submarine, "pos"); + connect(movementAnimation,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationMovementValueChanged(const QVariant &))); + addAnimation(movementAnimation); + AnimationManager::self()->registerAnimation(movementAnimation); + this->submarine = submarine; + } +protected slots: + void onAnimationMovementValueChanged(const QVariant &) + { + if (qrand() % 200 + 1 == 3) + submarine->launchTorpedo(qrand() % 3 + 1); + } +protected: + void onEntry() + { + 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); + } + movementAnimation->setStartValue(submarine->pos()); + QAnimationState::onEntry(); + } + + void onExit() + { + movementAnimation->stop(); + QAnimationState::onExit(); + } +private: + SubMarine *submarine; + QPropertyAnimation *movementAnimation; +}; + +//This state is describing when the boat is moving right +class ReturnState : public QAnimationState +{ +public: + ReturnState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent) + { + returnAnimation = new QPropertyAnimation(submarine, "yRotation"); + AnimationManager::self()->registerAnimation(returnAnimation); + addAnimation(returnAnimation); + this->submarine = submarine; + } +protected: + void onEntry() + { + returnAnimation->stop(); + returnAnimation->setStartValue(submarine->yRotation()); + returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.); + returnAnimation->setDuration(500); + QAnimationState::onEntry(); + } + + void onExit() + { + returnAnimation->stop(); + submarine->currentDirection() == SubMarine::Right ? submarine->setCurrentDirection(SubMarine::Left) : submarine->setCurrentDirection(SubMarine::Right); + QAnimationState::onExit(); + } +private: + SubMarine *submarine; + QPropertyAnimation *returnAnimation; +}; + +#endif // SUBMARINE_P_H diff --git a/examples/animation/sub-attaq/torpedo.cpp b/examples/animation/sub-attaq/torpedo.cpp new file mode 100644 index 0000000..4964192 --- /dev/null +++ b/examples/animation/sub-attaq/torpedo.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//Own +#include "torpedo.h" +#include "pixmapitem.h" +#include "boat.h" +#include "graphicsscene.h" +#include "animationmanager.h" + +#if defined(QT_EXPERIMENTAL_SOLUTION) +#include "qpropertyanimation.h" +#include "qstatemachine.h" +#include "qfinalstate.h" +#include "qanimationstate.h" +#else +#include <QPropertyAnimation> +#include <QAnimationState> +#include <QStateMachine> +#include <QFinalState> +#endif + +Torpedo::Torpedo(QGraphicsItem * parent, Qt::WindowFlags wFlags) + : QGraphicsWidget(parent,wFlags), currentSpeed(0), launchAnimation(0) +{ + pixmapItem = new PixmapItem(QString::fromLatin1("torpedo"),GraphicsScene::Big, this); + setZValue(2); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFlags(QGraphicsItem::ItemIsMovable); + resize(pixmapItem->boundingRect().size()); +} + +void Torpedo::launch() +{ + 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,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationLaunchValueChanged(const QVariant &))); + + //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(launchAnimation,machine->rootState()); + + machine->setInitialState(launched); + + //End + QFinalState *final = new QFinalState(machine->rootState()); + + //### Add a nice animation when the torpedo is destroyed + launched->addTransition(this, SIGNAL(torpedoExplosed()),final); + + //If the animation is finished, then we move to the final state + launched->addFinishedTransition(final); + + //The machine has finished to be executed, then the boat is dead + connect(machine,SIGNAL(finished()),this, SIGNAL(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 &) +{ + foreach (QGraphicsItem *item , collidingItems(Qt::IntersectsItemBoundingRect)) { + if (item->type() == Boat::Type) { + Boat *b = static_cast<Boat *>(item); + b->destroy(); + } + } +} + +void Torpedo::destroy() +{ + launchAnimation->stop(); + emit torpedoExplosed(); +} diff --git a/examples/animation/sub-attaq/torpedo.h b/examples/animation/sub-attaq/torpedo.h new file mode 100644 index 0000000..33bbc04 --- /dev/null +++ b/examples/animation/sub-attaq/torpedo.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __TORPEDO__H__ +#define __TORPEDO__H__ + +//Qt +#include <QObject> + +#if defined(QT_EXPERIMENTAL_SOLUTION) +# include "qvariantanimation.h" +# include "qgraphicswidget.h" +#else +# include <QVariantAnimation> +# include <QtGui/QGraphicsWidget> +#endif + +class PixmapItem; + +class Torpedo : public QGraphicsWidget +{ +Q_OBJECT +Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + Torpedo(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0); + void launch(); + void setCurrentSpeed(int speed); + void destroy(); + +Q_SIGNALS: + void torpedoExplosed(); + void torpedoExecutionFinished(); + +private slots: + void onAnimationLaunchValueChanged(const QVariant &); + +private: + int currentSpeed; + PixmapItem *pixmapItem; + QVariantAnimation *launchAnimation; +}; + +#endif //__TORPEDO__H__ diff --git a/examples/declarative/animation/animation.qml b/examples/declarative/animation/animation.qml new file mode 100644 index 0000000..1d60ac0 --- /dev/null +++ b/examples/declarative/animation/animation.qml @@ -0,0 +1,28 @@ +<Rect width="400" height="200" color="white"> + <Rect width="40" height="40" y="80" color="#FF0000" radius="10"> + + <x> + <!-- + Animate the x property. Setting repeat to true makes the + animation repeat indefinitely, otherwise it would only run once. + --> + <SequentialAnimation running="true" repeat="true"> + <!-- Move from 0 to 360 in 500ms, using the easeInOutQuad easing function --> + <NumericAnimation from="0" to="360" easing="easeInOutQuad" duration="500"/> + <!-- Then pause for 200ms --> + <PauseAnimation duration="200"/> + <!-- Then move back to 0 in 2 seconds, using the easeInOutElastic easing function --> + <NumericAnimation from="360" to="0" easing="easeInOutElastic" duration="2000"/> + </SequentialAnimation> + </x> + + <color> + <!-- Alternate color between red and green --> + <SequentialAnimation running="true" repeat="true"> + <ColorAnimation from="#FF0000" to="#00FF00" duration="5000"/> + <ColorAnimation from="#00FF00" to="#FF0000" duration="5000"/> + </SequentialAnimation> + </color> + + </Rect> +</Rect> diff --git a/examples/declarative/behaviours/MyRect.qml b/examples/declarative/behaviours/MyRect.qml new file mode 100644 index 0000000..e40bd1b --- /dev/null +++ b/examples/declarative/behaviours/MyRect.qml @@ -0,0 +1,4 @@ +<Rect radius="15" pen.color="black" width="100" height="100" id="Page"> + <MouseRegion anchors.fill="{parent}" onClicked="bluerect.parent = Page; bluerect.x=0" /> +</Rect> + diff --git a/examples/declarative/behaviours/test.qml b/examples/declarative/behaviours/test.qml new file mode 100644 index 0000000..a544028 --- /dev/null +++ b/examples/declarative/behaviours/test.qml @@ -0,0 +1,37 @@ +<Rect color="lightsteelblue" width="800" height="600" id="Page"> + <MouseRegion anchors.fill="{parent}" onClicked="bluerect.parent = Page; bluerect.x = mouseX;" /> + + <MyRect color="green" x="200" y="200" /> + <MyRect color="red" x="400" y="200" /> + <MyRect color="yellow" x="400" y="400" /> + <MyRect color="orange" x="400" y="500" /> + <MyRect color="pink" x="400" y="0" /> + <MyRect color="lightsteelblue" x="100" y="500" /> + <MyRect color="black" x="0" y="200" /> + <MyRect color="white" x="400" y="0" /> + + <Rect color="blue" x="0" y="0" width="100" height="100" id="bluerect"> + <x> + <Behaviour> + <SequentialAnimation> + <NumericAnimation target="{bluerect}" properties="y" from="0" to="10" easing="easeOutBounce(amplitude:30)" duration="250" /> + <NumericAnimation target="{bluerect}" properties="y" from="10" to="0" easing="easeOutBounce(amplitude:30)" duration="250" /> + </SequentialAnimation> + <NumericAnimation target="{bluerect}" property="x" duration="500" /> + </Behaviour> + </x> + + <parent> + <Behaviour> + <SequentialAnimation> + <NumericAnimation target="{bluerect}" properties="opacity" to="0" duration="150" /> + <SetPropertyAction target="{bluerect}" property="parent" /> + <NumericAnimation target="{bluerect}" properties="opacity" to="1" duration="150"/> + </SequentialAnimation> + </Behaviour> + </parent> + + </Rect> + + +</Rect> diff --git a/examples/declarative/connections/connections.qml b/examples/declarative/connections/connections.qml new file mode 100644 index 0000000..3146338 --- /dev/null +++ b/examples/declarative/connections/connections.qml @@ -0,0 +1,9 @@ +<Rect id="rect" color="blue" width="40" height="30"> + <Rect id="dot" color="red" width="3" height="3" x="{rect.width/2}" y="{rect.height/2}"/> + <MouseRegion id="mr" anchors.fill="{rect}"/> + <Connection sender="{mr}" signal="clicked(x,y)"> + color="green"; + dot.x = x-1; + dot.y = y-1; + </Connection> +</Rect> diff --git a/examples/declarative/contacts/contacts.pro b/examples/declarative/contacts/contacts.pro new file mode 100644 index 0000000..18293ee --- /dev/null +++ b/examples/declarative/contacts/contacts.pro @@ -0,0 +1,22 @@ +TEMPLATE = app +TARGET = contacts + +MOC_DIR = .moc +OBJECTS_DIR = .obj + +QT += declarative script sql + +unix { + sqlitedb.output = ${QMAKE_FILE_BASE}.sqlite + sqlitedb.commands = rm -f ${QMAKE_FILE_OUT}; if which sqlite3 ; then sqlite3 ${QMAKE_FILE_OUT} < ${QMAKE_FILE_NAME} ; fi + sqlitedb.input = SQL_SOURCES + sqlitedb.CONFIG += no_link target_predeps + + QMAKE_EXTRA_COMPILERS += sqlitedb + QMAKE_EXTRA_TARGETS = sqlitedb +} + +SQL_SOURCES += data/contacts.sql + +SOURCES += main.cpp + diff --git a/examples/declarative/contacts/contacts.qml b/examples/declarative/contacts/contacts.qml new file mode 100644 index 0000000..d4647f9 --- /dev/null +++ b/examples/declarative/contacts/contacts.qml @@ -0,0 +1,44 @@ +<Rect id="page" width="320" height="480" color="white"> + <resources> + <Component id="contactDelegate"> + <Rect id="wrapper" x="20" width="{List.width-40}" color="#FEFFEE" pen.color="#FFBE4F" radius="5"> + <filter><Shadow xOffset="5" yOffset="5" /></filter> + <MouseRegion id="pageMouse" anchors.fill="{parent}" onClicked="if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';}"/> + <Image id="portraitPic" src="{portrait}" x="10" y="10" /> + <Text id="name" text="{firstName + ' ' + lastName}" anchors.left="{portraitPic.right}" anchors.leftMargin="10" + anchors.top="{portraitPic.top}" anchors.right="{wrapper.right}" anchors.rightMargin="10" + font.family="Comic Sans MS" font.bold="true" font.size="11"/> + <VerticalLayout id="email_layout" anchors.left="{name.left}" anchors.top="{name.bottom}" anchors.topMargin="10"> + <Repeater id="email_list" dataSource="{emails}" > + <Component> + <Text text="{modelData}" height="18" font.italic="true" color="midnightblue" /> + </Component> + </Repeater> + </VerticalLayout> + <height>{Math.max(email_layout.height + name.height + 25, portraitPic.height+20)}</height> + + <states> + <State name="Details"> + <SetProperty target="{wrapper}" property="color" value="white" /> + <SetProperty target="{wrapper}" property="x" value="0" /> + <SetProperty target="{wrapper}" property="height" value="{List.height}" /> + <SetProperty target="{wrapper}" property="width" value="{List.width}" /> + <SetProperty target="{wrapper.ListView.view}" property="yPosition" value="{wrapper.y}"/> + <SetProperty target="{wrapper.ListView.view}" property="locked" value="1"/> + </State> + </states> + + <transitions> + <Transition> + <ParallelAnimation> + <ColorAnimation duration="500" /> + <NumericAnimation duration="150" properties="x,yPosition,height,width"/> + </ParallelAnimation> + </Transition> + </transitions> + </Rect> + </Component> + </resources> + + <ListView id="List" model="{contactModel}" width="320" height="480" clip="true" delegate="{contactDelegate}"/> +</Rect> diff --git a/examples/declarative/contacts/dummydata/contactModel.qml b/examples/declarative/contacts/dummydata/contactModel.qml new file mode 100644 index 0000000..341b7a6 --- /dev/null +++ b/examples/declarative/contacts/dummydata/contactModel.qml @@ -0,0 +1,103 @@ +<ListModel> + <Contact> + <firstName>Aaron</firstName> + <lastName>Kennedy</lastName> + <portrait>contact.png</portrait> + <emails> + <Email address="akennedy@trolltech.com"/> + <Email address="aaron.kennedy@trolltech.com"/> + </emails> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>1</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>2</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>3</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>4</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>5</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>6</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>7</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>8</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Contact</firstName> + <lastName>9</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Alan</firstName> + <lastName>Alpert</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Betty</firstName> + <lastName>Boo</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Foo</firstName> + <lastName>Bar</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Marius</firstName> + <lastName>Bugge Monsen</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Martin</firstName> + <lastName>Jones</lastName> + <portrait>contact.png</portrait> + <emails> + <Email address="mjones@trolltech.com"/> + <Email address="martin.jones@trolltech.com"/> + </emails> + </Contact> + <Contact> + <firstName>Michael</firstName> + <lastName>Brasser</lastName> + <portrait>contact.png</portrait> + <emails> + <Email address="mbrasser@trolltech.com"/> + </emails> + </Contact> + <Contact> + <firstName>Yann</firstName> + <lastName>Bodson</lastName> + <portrait>contact.png</portrait> + </Contact> + <Contact> + <firstName>Yogi</firstName> + <lastName>Bear</lastName> + <portrait>contact.png</portrait> + </Contact> +</ListModel> diff --git a/examples/declarative/contacts/main.cpp b/examples/declarative/contacts/main.cpp new file mode 100644 index 0000000..6bf9daf --- /dev/null +++ b/examples/declarative/contacts/main.cpp @@ -0,0 +1,80 @@ +#include "qml.h" +#include <qfxview.h> + +#include <QWidget> +#include <QApplication> +#include <QFile> +#include <QTime> +#include <QVBoxLayout> + +const char *defaultFileName("contacts.xml"); + +class Contacts : public QWidget +{ +Q_OBJECT +public: + Contacts(const QString &fileName, int = 240, int = 320, QWidget *parent=0, Qt::WindowFlags flags=0); + +public slots: + void sceneResized(QSize size) + { + if(size.width() > 0 && size.height() > 0) + canvas->setFixedSize(size.width(), size.height()); + } + +private: + QFxView *canvas; +}; + +Contacts::Contacts(const QString &fileName, int width, int height, QWidget *parent, Qt::WindowFlags flags) +: QWidget(parent, flags), canvas(0) +{ + setAttribute(Qt::WA_OpaquePaintEvent); + setAttribute(Qt::WA_NoSystemBackground); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setMargin(0); + setLayout(vbox); + + canvas = new QFxView(this); + QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize))); + canvas->setFixedSize(width, height); + vbox->addWidget(canvas); + + QFile file(fileName); + file.open(QFile::ReadOnly); + QString xml = file.readAll(); + canvas->setXml(xml, fileName); + + canvas->execute(); +} + +int main(int argc, char ** argv) +{ + QApplication app(argc, argv); + + bool frameless = false; + + int width = 240; + int height = 320; + + QString fileName; + for (int i = 1; i < argc; ++i) { + QString arg = argv[i]; + if (arg == "-frameless") { + frameless = true; + } else { + fileName = arg; + break; + } + } + if (fileName.isEmpty()) + fileName = QLatin1String(defaultFileName); + + Contacts contacts(fileName, width, height, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget); + contacts.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/declarative/declarative.pro b/examples/declarative/declarative.pro new file mode 100644 index 0000000..3083800 --- /dev/null +++ b/examples/declarative/declarative.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG = ordered + +SUBDIRS += minehunt \ diff --git a/examples/declarative/dial/DialLibrary/Dial.qml b/examples/declarative/dial/DialLibrary/Dial.qml new file mode 100644 index 0000000..acff119 --- /dev/null +++ b/examples/declarative/dial/DialLibrary/Dial.qml @@ -0,0 +1,13 @@ +<Item width="210" height="210"> + <properties><Property name="value" type="real" value="0"/></properties> + <Image id="Background" src="background.svg"/> + <Item x="102" y="98" rotation="-130"> + <rotation><Follow spring="1.4" damping=".15" source="{Math.min(Math.max(-130, value*2.2 - 130), 133)}"/></rotation> + <Image src="needle.svg" x="-102" y="-98"/> + </Item> + <Item x="104" y="102" rotation="-130"> + <rotation><Follow spring="1.4" damping=".15" source="{Math.min(Math.max(-130, value*2.2 - 130), 133)}"/></rotation> + <Image src="needle_shadow.svg" x="-104" y="-102"/> + </Item> + <Image src="overlay.svg"/> +</Item> diff --git a/examples/declarative/dial/DialLibrary/background.svg b/examples/declarative/dial/DialLibrary/background.svg new file mode 100644 index 0000000..415320d --- /dev/null +++ b/examples/declarative/dial/DialLibrary/background.svg @@ -0,0 +1,385 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> +]> +<svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="210px" height="210px" viewBox="0 0 210 210" enable-background="new 0 0 210 210" xml:space="preserve"> +<defs> +</defs> +<radialGradient id="SVGID_1_" cx="0.8066" cy="-16.5908" r="92.0159" gradientTransform="matrix(0.9944 0 0 -0.9944 101.1987 90.0014)" gradientUnits="userSpaceOnUse"> + <stop offset="0.1264" style="stop-color:#E0E0E0"/> + <stop offset="0.3421" style="stop-color:#C7C7C7"/> + <stop offset="0.5495" style="stop-color:#B3B3B3"/> + <stop offset="0.721" style="stop-color:#B1B1B1"/> + <stop offset="0.7828" style="stop-color:#AAAAAA"/> + <stop offset="0.8269" style="stop-color:#9E9E9E"/> + <stop offset="0.8625" style="stop-color:#8D8D8D"/> + <stop offset="0.893" style="stop-color:#777777"/> + <stop offset="0.92" style="stop-color:#5C5C5C"/> + <stop offset="0.9445" style="stop-color:#3C3C3C"/> + <stop offset="0.9662" style="stop-color:#171717"/> + <stop offset="0.978" style="stop-color:#000000"/> +</radialGradient> +<circle fill="url(#SVGID_1_)" cx="102" cy="98" r="85"/> +<path opacity="0.5" fill="#FFFFFF" fill-opacity="0.8" enable-background="new " d="M57,169c0,0,20.146,5.732,45.001,5.732 + C126.855,174.732,147,169,147,169s-20.145,12.846-44.999,12.846C77.146,181.846,57,169,57,169z"/> +<image overflow="visible" opacity="0.75" enable-background="new " width="206" height="206" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAM8AAADPCAYAAABSgYVfAAAACXBIWXMAAAsSAAALEgHS3X78AAAA +GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAIVhJREFUeNrsnQtz27oOhKGH7SRN +m3P//588p83DdmzptjPiFNksQMqWHdkGZzRO0zbxg58WWIKgSIwYMWLEiHHOUcVbcDXvex9va8Bz +re9rdaL3vz/iezECnlm9h1Xm++dQnt74uz6ACnjm8p5VBY+VA1V1Imj0Y+/8XQ66GM5o4y04CBgL +jpr8HbtOCY91pb/vMnAFSAHPSYDxrjrzaEFUTQCOBUyXeczBFiAFPJMCUwMYpRcCdUwIx0ItBkjp +1cPXAVLAMzkw6WrIo75q+JqBVE0IT+8Asx8u/TV+Tz92AVLAUwrNGGDS1TqPLYGpcVRoipyHqc2e +XLvh2juP+wxIXUA0XcJ6DSpTZ4BpAZCF8diSf9uCSqH6HPo5YL6D4HQEFn29G487A6R9Jme6OYja +G4OGOWO1EYIhDAtyLeHPDCSmPlbecyhAqDxMbRCUdG3hz+8EKK1MHkg3pUbtjULjhWMWLEvjQoha +Ax78vTKh8oiT6zDF0dBsjQvB8lSpu8WQrr1ycHLQjIFlNVxL9bg01KdxwGFmwRR5T+/kPVo9UHXS +tRmuLXncFoCE8F49QO2VQiNG4o8qkwOFXfrfpP/bAjgYquXWd0rv1lbJj7Xe0xmmQQIgAbEBgLxr +C/AhSDcDUXvF0FSQyzCVYaDcGY+W4rDcBteD2MT3ymrGmB7ez8b1G5YLWQr051oPF36NyoSKxHKj +qysDqq4IHGYzeyqjYbkfHvFCxVk40ORCst5RiDEAVWLb7FLw+3sjJ7IgWsP1BkBtILx7d0I6b80o +4JlJiGZBo4FJ0OgrfS/9G602LDRjyT86YGPLYyyAStalrLIg7zl2JKR7Jyr0BgC9EZg2hhpZEF20 +ClUXDg4L0Sxo7gCah+FCgLTaoINWk3AMJ2IvfNXeWngcM5nYzcKrgEALvnKAR5AYRAgPu5gaMSW6 +eBWqLvg5W9C0kJcwYB4IPHeQ3+iwTE84Ic4WS8rZ1wygzgjpSnO6kkqIxjEzcMFWvy4W0jGAXtWl +v+9BdPEq1F6J2mgjYElCMw3Lt+FCcFaQzzRkUllJN1uI3El+bYTlAjm3bUwJEVvoZd/HvE3/jA5C +unuiQgmcF/W4HP5uMfy7ZgCodlToogBqLxScGhy0FF4xaDQsDBwdorWgMgyYd2L1vkOy/G5AxODJ +FV968FhWvFUd0crnRV3Paq/U9/DGpCHSYe+L+gwSTBrajXp/Kng/LsqNay8EGjEMAQ1N+lBRZR4B +mgeiNlppBICx3ChvZT5X3tIVOFB9oWFgLf6yOjyvUsJzExFMlkeWOJWvw8/YqOfLbioXAVF7QWpT +EUMgfej6zqeBeVRfa3BKoMGE2VpEZPAcWhdWAo84LltTAJC3ILwkjwtQ5VJThi0sL4jCpffMs/UD +niPDNPzQ9IelQ7JHuNL3MURrVHiGcb1OjjdiLxRuiOKw8pVO7DqwMQuIpVXhjeRLkBg81gKxlQ+2 +mSUBD552eC9rR4VmrUDtTKHxwjRUGx2efR8uVJx7Ak2llAZVZk3WMdYAz9YBxyrn70au7ZQ6jtYC +sVeStCAKdEcsffweQlSr97U1fq5VC8jWzC4mF2pnrDbopuncBkM0Dc13Bc49fOAamp1K+reZNYwc +OCWFkmOabxwCkMi4vUltAUD3wheS79T/0SbLgrifDNSF8CqN9fDcLyKMa2cMDiaoS/WBplDsO1yP +AA6qTa/Cs61hueIjq+kaC01OaY6Bp1SJSiFaOVb/PRgud8Sp1Iux+LPZHqgFWU/Ta0/pfZW5KVA7 +Q3BqeOMX4KSh2vwAcB7Uh9pCXpNymg1Zo2CLfQycXE5TstOyP9F7mHPlqoKciAH0qgB6I0Ch3V+p +mxYzeRaO+uCGwXf1+c0qhGtnDs6SrNl8J+B8V/lNiq/TB9GpvGYr9sIeA8daId/J+IYZ5wg7qoyx +kLO3sUJDQ/QKywDpPXpQNyx900rv/9JYk1tkch/s8bBTEM0CoGaGjppWmwTNo4Ll6ff1z3A9Ddd3 +CNVS6JDUJhU2/gHl1+/r5+/rP3L9+f7zcL0MFwNp54D0lXv8WdW2/rPXlsrarsB2oVpbEHROx5xS +qzFKI35jlF5mWErWzAycloRpCRwNTbqS8qQ730K9pr1SmgTNLwOa9HcJHFSfXJVwJ/NthmEZFB5Q +pSDhTQQBEvFLiNj29GqO+c2c4MmBo520H4XgpPxmr/KatwEGT20SOC/ysbCRQdOJvcnrUmqycv2s +c9u4cx13GEDWlpGmIFybLUjNDMHRisPAeRq+/zhAtgS1eVch2jNA8y8J0XTOsybGgKUycmHQ5ICy +2vXmQLKKX3vIT3IAsQrvWVvVzYWA8z/Ibx7VWkOjEsqtMgG02iA0vwAcndMwaG6lP1muE6l2FhEW +1o0U37dcB1ZsyyVODndT8DC3Z1EIzj9gDKT8pgZT4FWpzU/HEGDQbIVXB9xiUz+voYjXlZQB1RtG +QpUBqCoEqL8VePR+kdZw1XKOGoKDpsB/JEz7mTEDMGa/6U6YhaFdrid2NyIHYpcQiLwF57N/Vs0Z +wfFCtW+ZHAfBqcBNe86Eac9gCLC8JqAZH85hQ5FO7E1/uRCutL/d1JUaB4/2zODotZylfKwa0Os4 +T8oYSI7aSj3fBI520zQ82nrWwGyEr08ENOXgVAUh3E7KdtOmn71UN9UxhoblGnbn+BzbM4HDVEfX +qeEC6BOxorWjhjb0fwocFqJ5DlpAcxxEnjPn5UMIwkrNj6owB2PrVWdTo+YM8OCWaW8BFM0BvYZT +KXBeHRs6uWnaFNgSeK6qh9jM8iGmTNZ77YVvrOLAaud1djOhPTE4WCGN4dojhGo/5O8azoO6G4nh +qDFonuVjNbQO09haTYBzvCNnTe7cKXW9My+b4fP3fmafya2qU37G7YnBwY1srDr6hwIIwWkJOJYx +kNTmRTlpqTpgX3AHjHFcKNcZYZQFUq7xic6BmNrkjInu1PlPc0JwKrEXQb8rtfFcNYFQDcH5V/6u +6TwDOFsAJ8K0rw3jvJ4NuV50nmV9TBPJ2SoPGgRL+bz784e6Ejjoqlmhmg7X0IZGCzrCtK8L44S4 +YSL55o4CJsJK7F7be0OJROxzg2anPMxZY5Y0qk4K1/QCKNrRFjjaVdP7bvYRps1OgaTQPKgkfwiy +l/ecJdJoTgBOJZ+b5N0b4GhLOhV56sqBMeAwxQlw5guTFLpvzIETACjXD/wkc2BqeKydoNpZY2U3 +D/J3oUyX3Oh1HA1NgHMdEAlxxgRA8bYrWEWrZynqbSYEp8qA81142Q0ugu4UONY6zkuAc1UA5cwD +7wwkq+G+ZyLMBh7PXcMKAtyTk5w1tKStLQWhONetQF7Y5p3q4J1YcbLwbSp4WLh2T8I1XbeWNrOh +QfCaAedFmQMBznU5dd55sta2Be/8VQ+e/qvhyblrrP/AkzIIkhWZdoAmS9orucGtBAHOdYBTGrox +8+BQgL4cnlzBJ3PXMM/RW6d/OuBEqHY7w2sa0gjvdbAfCVD/VfAw1cn1INC9B7DY02oLpcFZh+Lc +ZOjmta3SEFnbI7zdwWeHp9QkwHAt1a2hLc3Wc9BZS0We7wHO1Y4qYxzoUxnYoco6dMNGJZOHb8fC +oztN4q7QJ8NdS3lOarbObGl01tbi16rFuC6A2A2anTtknRd7FoCaI8DRWw1SJUEqwcEdoUl1cBu1 +DtcsZ20NzlonJ/LtY8wGnpxhgOep6vANbWvvTNgvg4dtNWC9CHArdVKdFK6xPOcZDIKtAicU57oV +Rwoct9YAqBJeOGqdZnHUXGqOuCvg+ZTaJPgh+cXQdUZ1MFzLbaCKcR3gVAXGAZ7sjdUHCaAEC7ZK +3k0Rvh0KD+4M1QuiT4bqYLuoV/ncKopVSb+H6tx8+Gad6GABlHIfr9f2/ivgwd2haV0HF0Rxcxuu +6TCToHQ9J8bt5T6V2GcKIUAC6oMnPLAjYkbPreaAF4MntqHDpvsRPILq4K7QUnctFCfCOA8eBKgi +rlvp0Sgng0f77bhXhzXy0DtD+4zq4DZqDNdi3LZxYJkGCA/mPgyekt59k8HDDqBaGg4bU51kTVtt +cXWrKKxbC9UJmLBVs3W6N3PeEB7vBIxRc6w+UHkaoj54YnJSnHRCmz7WEI8w1DlOLITGYK1809zY +qDmj55Eu3Uqb63RqoednOnpzYZgNJ4GHOW0reHL6hGQ8N2dNXjhrhbuPcC2GkbdsFEB4A16rm2+a +34vMHMVSn2pKeHIH7uKx4+ncnFZJ585RnXWoTowD1GedUZ8O8vM7mKeoPtihtJoCHhG73/SSPKGV +cte06jC5XYtftxYjBgNoq+aOpT6dyusXBCCmPsXgTAGPPmp8pWhOJKeEjR3hrrcYxDaDGKXqs1Nz +xptTSX0qkp9reJby2eaeBJ4xIZs2CTDX2ao7w5vww6WO8txj3ETugwBh+IZpQCcfW6FZN/uF8C3e +1VQ5DwvZVuRJtGATviuJfRP/DNBQnRil6qPNgzW5KesFdlybROU5KHSbAp47yHUaYhRs4MWtw12L +MaH7tiYAMdu6VH2OhscK2TzlacEo2MGLW4t9XHuoToxD1GdL5lhSpDS30lzPRUyjQrfSnMcL2ZaQ +dNUQsuGL24jf/SZGjFLnTUc2CNCWhG7NCICOznmsc3bwl6fyCF3RunfuCngCdRz/EWOM+uB2A+8G +vVehW+Pc/CeDx9rFp5UHLwzZLNXxwrUYMQ5RHzbXcC+YgHGwPDZ0K8l5EBxN7pIkWyxk03cCrTon +7SUc46rBwf06W2O+eaHbEuAZpT7H5DxLMAq0y8bi0a2hOuGyxTjUdWPqszXyah26tYYAnCRss0I2 +TWv6WZ1xJ2CqE+DEmAKgXcGcw9BtYcxnBlBx2GY1226MX9pCyNaRO0FOdSJki3GIceCpz1Z4Dwzc +UmOFbKg+1RjlkUzOg1tfRZkF7IW8G6oT0MQ4Nv/BXgXWDTsN3Inq5TxyqGHAtr4u4NK/iBXvpRfA +du/FIbsxDgVHhPdoeycA6WgHd0SznajWMY7FylNLWdOFRj422mbKw7qWRLgWY8rwzYIH553I5x7r +C7GbKNaH5jwlvbK0y6Ztaq/dT0AT4xThm9UpB7swYRcoq4VVPSbnqQoBQnAqyHd2wruUTNYnOEYM +sY9U9OagNsNKel+LBdAY5fF+kRjOxy7jsEW+E2OKvKcfOf8kIwgHKY8AmaxHcEsSK1Ehm9XiNOzp +GKfOe7rM/NurOVcyrw8qz/F6BFtH22G5RIRrMeYSvmE5mAg/dQ7DtlomqG3TJxFbbXqsM1F26vsB +T4xzmAad+AdbiQGQdeK2lMBTid1guzbiQXTa9sIPFYpcJ8a5ch9rDqLj5s3t2mDhIOVhF4Zs7CTi +Tuxu9AFQjKnBKZmLPTHFMIRz13hKDYPKAaeCF4JPmoVrAU6MUwDE0odO/H7UbH7r70lpzsMsuYr8 +QEZkTxTGO/skwIlxipyHuW/WfBSiPpXYLtsnPkr28wgBR0i+0ztPNOzpGHMACOcgi7AqI98pMgxQ +qtgPqZwn3hU86RgxzgVQn1GdHDiMj1HKY30v9ySjsUeMOUHE8m3LYfYYKILHC+PGPGF0RWLEmAM4 +HjyVEYmNgqeke2J/wJOOEeMU0MhIcEpTk6OVJweORKgWYwYQWUDlUpPKyf0nh6c3/hzWdIxLGJZB +djblYeBI5DgxZg5NNTKnPyk8MWJcu0IFPDFiHJmeBDwxbhqGPpOzf3nYVny+Y4wYMwGpGKB6AjhY +shXAxLjk8KwIoKmUx7P8JGCKMdP8pWRRvz8lPBYsRScKx4hxglRBMjdzL3QrXl6pC0ntC57wwQV2 +MWJMnF+XzMOcwmRrMscqD/6i3BMuKrCLEeMEEJXc0BlAxdUxdSEsue9521kjfIsxJ4BYFJQrai6C +p3ckq7Ss2+t3EADF+ApoWNMacVSnd1gYrTzYmUT/0BJwAqAYXwFOnYmGcCPnqG00tRP/Cfmh2JNA +P/Fci6owD2J8JTiW+rCWVWyOf+KjdhSntC8BA4h1YBy92ShGjEJwUBCsDrcMnJK+G6Nr28a08LFO +VGgyKhQAxZgCHNbEw5uLrFlniUBkDQOv+4jVtB3PO9Gd51nX+QAnxikBsuZgQ/Kd3Nw2FWiM8rAO +jL0hl/pJt0b4FiPG1DmPnmctmYs1yfOtDrejlccL2VLj7L0BUKWetHXeScAT49TwWOfutEbIhocT +7EtDtxLDwDrvRAMkMv6cx4AoxpQu25jzc6VwXo82DHqSTO2dX9QZYdsCHpswDWKcONcpnX8in8+S +YlFVJ86aj1dhwABiv0iTidQvInyL8YXhGpuDOrLyBKGTTPHoGOXJnfOoHbcFPHmkP8CJcSqzgM27 +BXHaxpyfW6Q86EL0huroI7rZIanpCS+HywMoIIoxRb6D4Oi5hye39/Lx1Ox3Q31YpUEWHivn0b8s +XfoX6RexdODBM00DoBiH5jsYriE8S4BHCwLO5Z34h2EVK48Q5Um/ZEtkTiDvWRCAtGUY4VuMKfOd +NjPvGvV/MVzbEoDckK0k52F5jwZoC79Mr/Xgi1hmnLeAKMYh4Vrt3LD1nEtzTc/lrQNO9vzcMes8 +O4AGf6m2rHXYthouLaGoPjFiHAIRqo4357RFzURgayjPQYWhUgDQBtSnV45ba7wQS31ixDgEHKY6 +es61ymnrQXU2BeDI2JzHA+fd+MU6dGvUi1ll1KeK/CfGAXlOlVGdlbpZNxCyMQF4HwtQadjGlGcD +ALHQLQF0N1wrQ30CnBiHAISqs1JzDfMdHbJtyRz2cp6ThW0bUB8duuk7AQLUgqSGcRCj1CjQqUFL +wNHKgyGbdfOfNGzLwbMx4GGh253xwkJ9YhyrOuwGfVcQsm0yyjNJzlMSuuknkEK39OLYC8uFbwFR +DEt1cuGavkHr9Z1uBDjZkK1EeZj64BNYq6/Tk0ihW6uU53649Atk8MSIkXPZNDwaHD3HUmSTQrZ0 +02fzFiOnopa7h8CDyrNWT0QbBzp0W5EXt3IACvWJUaI6K2duYci2c+bs6JBtTM6DoVtOfZJxUBN4 +HuBFYu4TChTDUhyW61jzaiF/a9n2I1SnKGQrVR4Nka4JQorfQH0SPBi6PcALXTrmQUAU0FgmQW5O +tQoePV/fjGhJL/RPejKcFbppeNKlSRalPlpa04tlzkg4bzE8hw0dXA1Ogmeh5raOlHCubg4N2Q7J +eXr5WBvEaF5D7oPq80DuFElmF6E+MRzVWRhpgL4Za9XRuc7aiJJ0bWY/tWGgIWJ7ezbqCb0B0dq2 +ttTnPmMexIhch5kE947qoD3tzVHW9KNoHHI+j+W6vakLc58qoz73oT4xRqjOfUZ1Ksh11sb8tPbv +FI3myBflbX9leylE/L4IxW1/YtwEOKg4f4D59vv6/vt6Gq5/fl8/fl+Pw98vhv+7HyB5+X39+n39 +HK5fw/UygKQX90flPM3IF8Wsw5JdfLo4z+qLkIMnILqtUI0VF38bIHmC6/ugPqthTvcDFH/geFbg +pOsPOK8kdDup8pSqj9U1JweQ1y84xm05awjOwwDOdwDnxwDV3fB/ZJhL6wGSBMx/Snle5LMz3I2d +a4eEbVZM2hIFWhh5jA7frKZzB72gGFcBTu2Eaz8AnscBrKVy2JLq/AJ4finVSfDom/Wo0Uz4Yq2G +cxi6seMdvH7BEbrdXp6j13Puler8UHnOPwNMTHXeHNV5hVyHNe88adiWC9+wVzCzoHXVAjvmwetW +HxBdb57TFIRr2iRA1dkMgPwi4DwT1dkfojrH5jw59cGuodbeHdatfu+YBwHO9YZruH2fuWvaJPgm +fze89YOSJJPg1wBOup4d1ZFzwVNiHrDjHdoCgKyDhsI8uK08Z6nAeQTF0aqTwrUKTAINTgrdnuXj +Gs/ReXVz5IvO5T+NA1Aj/GDVzgjdOgjZAqLry3N0wec3I8/5MajOPTEJXgdIGDgpXNsog6o75gU0 +J7qD5FQIzyoVyZ+Bin2DA57rAAc74HgGgV7TuYNwbQ3hml4UTQuia/m8rnNwNNNM/EZgWyBLgfC4 +ETHCt9EnFMe4OHDQIEjh2g8I1/Sazr18XtN5BXftP6I62OH2qHk0Rc6Ty4G0C9eQr9kWhA5A6iP3 +uVpwWgLOd1CdJ3DXFiRcS+7av/J5QTTlOlhBfdSYMmxjKsQUiB2y2hADAbdC9BG6XS04yVl7BHD+ +B+Gadtc6cNd+grv2S5kEk4ZrU4dtJepTy+djvb3T4qwj7XtQpxiXC06qIHjI5DkpXEsdcXrHXbPC +NSzDOXo0J36jcgqklccDyIIpwrfLB+fecNaeIFxLe3VE/lZMvxrgsKrp3dRhf3OCN8r6Gh242gAJ +9/BUJETrCFQxLhOcpDi4lvMPAQerCJ4dcFLV9HbqcO0U8FQjFKg2AKpBgWr4eb0BTQB02eBoxfmf +Upy0nrNS4KQ854U4a2cJ104ZtpWYCZYK1eTydpOyotGA6DLMASvH0QuhD8QgWBNwdJ7juWuT3mSb +MwCjRy22ld0YAFlhnBBY+sLnFeP8arNU5sA3xxzQ2wz05radfNwZmqD5Vz4WfrISnJPkx80Jwcnl +Q7XYVQm1EcYxFaqMN6YPcL4EHLa+hz3WWI7zBIqzUvPTAseypU8arp0zbCsN4UovL4yr4I0KYL4+ +TNPgPIpvR3vg4DYDBOf11O7aV8FTFbzhHkxeOCcGTAkkL+QLuKaHRne6SbVqVuUALoImcFoCzrOh +OKyK4Cw7kc9tGFj5UOWEcrk8yAvpcvDGmD5MW4DiPBjgsLIbDc4ewPmpchy9R+flnHnOOeGpjoSt +zuRHtfBzTRlQhwAWw1cbrIpmG9lSmIYLoP84odpe/hZ7ojnAFkKtos+TjuYLP4B+RDhQAo4FUlUY +4gVE40I0q2ffnfCqAaxVG5vjeOC8C++C018jPJ4rZt3d6hH5UClMng0eEPnQNIbaPBjgsFAtbWgr +NQewgoA5a2fruPQVbpu1LuO94NIqhdziqwZJxLa+A6L89pKWqI3VrMOqVWPrOMwc0KqDu0Inr5ae +IzxscbMi8PRODlRJWaUCg4kZDrk1JHGculvJaSpDbfSpbFptvou/hpNaRelatV2BOWBtbNvJF/X3 +a2bygfUGQFbPNm+BFfcNWdsfWM5UYjBUNwBN7YRoK/l4UoGGJhempW0FGpx0isGLYw54ivNlmySb +GX14ua0HJXfHUoCsau4xRsM1nN5QjYBmKZ+P97DAQTftm/ytU0tWNNaqeeaAF6p92e7iZmYfpgeQ +lxd5CW2uDVYuNypRoeoKoGkMF806wpD1jbYqBtLpBSm/SWs4b2KX3DBzYDbgzBEeC5wuo0al/eMW +BkAeSFauZDl1c1SknPWvX/cClEYfSKaVhjUi1GqT3LTUW43lN6w6WlcPMFdtFuDMFR5PgTrja2uS +lAJUqkhepUMOpuoLVcWDhjXoT9CgGWCFaLqL56MyBbQNrcM0NAZYrZpex9G91mZzflM7E0jSmytG +mMaawePBWOm6k4+HaqXktHXuqK9w6Q8tlX1s5fOJDrnWWD1xF/sTgyNGbuatmyFES8hx2PmfDyqX +0Yczr9QNSJ/QlsDRodovleskaHR+g4ozqw5K7YxURgO0g79nrXjTB4LXTj4eEoyNR9jdNU0MBhBC +9G5ApO+InZOzyYk+9Cpj7dckv/GUh70/+ihM70zZCtRmoxQHwdHQsPxmluDMBR4GUA/g9AY8CBDG +xSuiQg25u94PsCBEFkAWRCVqZBkf/QGgMOevRGUsaHLg3MvHU8zvyHtcyccT07UxkCBh0GCd2hbe +19k1fZkLPGzy7Em+g+eZvhvwpDf/gahQI/zksTsF0YN8PAB2DRBtD4SoI7ncsfBgTlUfCA2qsQ5r +9XWn8pklQJOcNKY2LwoYDNGsMG3Wp2TMCR4MayrDhfPUBye1lv0VfNit8HavadKsVYy+LgDoXT4f +TFwS0o0N57zwzArNcM1mUQDOHcCiocEjY3qlNvp09FelOBoYHaK9kTCNHa8pMrP+FHODxwrhmAKx +3EdPaAyz7kmYUYFdrSHaqLsne2Rh3HtBTmQZC2OVp7QzESrNwgjTVur9wccVgUbnNTtQmzflqD0T +aF7gprSVCzwRfY7weBCx5u87R4E2cOkEd6lyoAoUCQseN+rnbQ14MIzTk8EyFqaEh0HDDhpbEsXR +gODjAnIafarFXr3fWm1eARYNzSvJbS4iTLskeErCuJwCbUBB1mCtrsjESDBhOMdyqq0BTw6g7giA +ctazBw6DR18LUBh2kvneUBvtVCIwL5DbbBy1uZhe5HOHxwvjuoyFbcGjIbpzQhJtLOwVRBqKreH0 +sfDNmiR9gYFQum5jnYe0IOqjYcJzY/XhY9oIYO8vA+eFKM2b+izeidpc3AkYlwBPSS5kmQhbAOfP +B/hNfZhoubJkWOdF1u/yFm13honQZcyDnFmQ63/XGhDlKiqwV7gHzRpCtRd4fCMmSy63uZimlZcE +DwvjLBsbP2wdk7/BuoVlweqJxmxfZl7sIUTbZ8DpRtjWlvrUGYBKtmcwYDpyI9oCNG8Azyt836rQ +sHZ9XlS310uDh73BneHGoYnA7pbWGsaKJMzWfqB++Hs9GZjDVgLOWKvaA4g5bxXkLwyYvTICMPxl +4LyRNTEPmqs54fwa9qOI5PfYLwxb9l4+Lgbq9Y2VAZF1LCSe5sCKWI9d6yld42HdhKzn6JkuOmd8 +I/CsCTAbYpzsr0VtrgkeK4m2EmirDAVhujNUaGm4UdbxKKiY3o5ZGQGPBZAU/P5cjrg11GZNYMmV +LeUMkqu4c18LQFKw9sHUiNV0rQhAJRBheFTSoH7sHTjX+RRrAztI/kug2UCyz2r8mMrk1rREruQk +i2vcj2+Fcl75vRXaWVf6dzmrlylSKUxjPjdv/xMzM9BqZ4u/1oX2fOk2jauB5prhERK+jCmUZDVf +TKFQgTAnasU+tGvqzXF9gfPIimmtciZ83BoKkyuEFbnig8euvZ0SS7BrsRuGWCB5K/MLYihYayi1 +YTJUBwLDkn9r6wYrYfKqJd4LgMF8ppMbOmzslnqRScahKqkLw4upzsKAhzUYOfYzQGePrTuxBVy2 +jYNtKiypzxuzVhXwXKGxUFrO3xKgco1FWvEbL06hPCxc60Apdg5IuwJ1GbNT9ubuyLcMEYZ0pSv3 +7NHqE2f1z54i3+mcfIep0N55zFVC3FRoFvAcFtKVrOAzhbL6Z+dMg2okMDmzACFiQHXCqyFK9x31 +MXFiHALS2CMhq0y+cww8IryKofTqA5iA59wglZTHlPZ3O8YwsCZ8J2XlQQFMwHNWkNjXtfinOpyi +abwVwlkJvbUGE8AEPGcHKfeYO4t1anhE/FMmvGQ/gAl4vvQ9LDl5+xTvuwdBn/l+jIBn1u/rqQ4R +7o/4XoyAJ973gCNGjBgxYsS49vF/AQYAwYoCo3RnAfgAAAAASUVORK5CYII="> +</image> +<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-15.9541" y1="83.9062" x2="13.6193" y2="-106.171" gradientTransform="matrix(1 0 0 -1 102.5 88)"> + <stop offset="0" style="stop-color:#B3B3B3"/> + <stop offset="0.151" style="stop-color:#AFAFAF"/> + <stop offset="0.301" style="stop-color:#A3A3A3"/> + <stop offset="0.4506" style="stop-color:#8F8F8F"/> + <stop offset="0.6001" style="stop-color:#737373"/> + <stop offset="0.7495" style="stop-color:#4F4F4F"/> + <stop offset="0.8968" style="stop-color:#232323"/> + <stop offset="1" style="stop-color:#000000"/> +</linearGradient> +<path fill="url(#SVGID_2_)" d="M101,187.999c-50.178,0-91-40.821-91-91c0-50.178,40.822-91,91-91c50.178,0,91,40.822,91,91 + C191.999,147.178,151.178,187.999,101,187.999L101,187.999z M101,13c-46.316,0-84,37.684-84,84c0,46.316,37.684,84,84,84 + c46.316,0,84-37.684,84-84C185,50.683,147.316,13,101,13L101,13z"/> +<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-79.4551" y1="-54.0073" x2="76.4557" y2="36.0078" gradientTransform="matrix(1 0 0 -1 102.5 88)"> + <stop offset="0" style="stop-color:#ECECEC"/> + <stop offset="0.0105" style="stop-color:#DDDDDD"/> + <stop offset="0.0399" style="stop-color:#B7B7B7"/> + <stop offset="0.0704" style="stop-color:#979797"/> + <stop offset="0.1021" style="stop-color:#7F7F7F"/> + <stop offset="0.1353" style="stop-color:#6E6E6E"/> + <stop offset="0.1712" style="stop-color:#636363"/> + <stop offset="0.2143" style="stop-color:#606060"/> + <stop offset="0.4615" style="stop-color:#FFFFFF"/> + <stop offset="0.5195" style="stop-color:#CFCFCF"/> + <stop offset="0.5899" style="stop-color:#9A9A9A"/> + <stop offset="0.6512" style="stop-color:#747474"/> + <stop offset="0.7002" style="stop-color:#5D5D5D"/> + <stop offset="0.7308" style="stop-color:#545454"/> + <stop offset="1" style="stop-color:#ECECEC"/> +</linearGradient> +<path fill="url(#SVGID_3_)" d="M101,7C51.294,7,11,47.294,11,97s40.294,90,90,90c49.705,0,90-40.294,90-90S150.705,7,101,7z + M101,182c-46.945,0-85-38.057-85-85c0-46.944,38.055-85,85-85c46.943,0,85,38.056,85,85C186,143.943,147.943,182,101,182z"/> +<circle fill="none" cx="102" cy="98.001" r="65"/> +<text transform="matrix(-0.6383 -0.7436 0.7588 -0.6513 54.624 142.6035)" font-family="'MyriadPro-Regular'" font-size="12">0</text> +<text transform="matrix(-0.589 -0.7833 0.7993 -0.601 50.7637 138.0234)" font-family="'MyriadPro-Regular'" font-size="12.0005"> </text> +<text transform="matrix(-0.3613 -0.911 0.9296 -0.3686 42.665 124.7539)" font-family="'MyriadPro-Regular'" font-size="12">1</text> +<text transform="matrix(-0.275 -0.9406 0.9598 -0.2807 40.4512 119.1719)" font-family="'MyriadPro-Regular'" font-size="12">0</text> +<text transform="matrix(-0.213 -0.9566 0.9761 -0.2173 38.8223 113.4023)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.0159 -0.9799 0.9999 0.0162 36.96 100.019)" font-family="'MyriadPro-Regular'" font-size="12.0004">2</text> +<text transform="matrix(0.104 -0.9745 0.9944 0.1061 37.0518 94.0215)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text> +<text transform="matrix(0.167 -0.9657 0.9854 0.1704 37.7407 88.0718)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.3752 -0.9053 0.9238 0.3828 40.7725 75.9199)" font-family="'MyriadPro-Regular'" font-size="12">3</text> +<text transform="matrix(0.4573 -0.8669 0.8845 0.4666 43.0674 70.3799)" font-family="'MyriadPro-Regular'" font-size="11.9993">0</text> +<text transform="matrix(0.5127 -0.8352 0.8523 0.5231 45.9121 65.1069)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.6672 -0.7178 0.7325 0.6808 52.3262 55.9673)" font-family="'MyriadPro-Regular'" font-size="12">4</text> +<text transform="matrix(0.7301 -0.6537 0.6671 0.745 56.4102 51.5703)" font-family="'MyriadPro-Regular'" font-size="12">0</text> +<text transform="matrix(0.7708 -0.6052 0.6176 0.7865 60.9082 47.6182)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.8905 -0.4092 0.4175 0.9087 72.1504 40.165)" font-family="'MyriadPro-Regular'" font-size="12">5</text> +<text transform="matrix(0.9246 -0.3249 0.3315 0.9435 77.6006 37.6587)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text> +<text transform="matrix(0.944 -0.2633 0.2687 0.9632 83.2959 35.7197)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.9797 -0.0248 0.0253 0.9997 97.3081 33.0972)" font-family="'MyriadPro-Regular'" font-size="12">6</text> +<text transform="matrix(0.9779 0.0643 -0.0656 0.9978 103.3198 32.9438)" font-family="'MyriadPro-Regular'" font-size="11.9994">0</text> +<text transform="matrix(0.9717 0.1274 -0.13 0.9915 109.2959 33.3921)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.9148 0.3514 -0.3586 0.9335 122.4863 36.2207)" font-family="'MyriadPro-Regular'" font-size="12">7</text> +<text transform="matrix(0.8783 0.4348 -0.4437 0.8962 128.0967 38.375)" font-family="'MyriadPro-Regular'" font-size="12">0</text> +<text transform="matrix(0.8481 0.4911 -0.5011 0.8654 133.4463 41.085)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.719 0.6659 -0.6795 0.7337 143.9395 48.2495)" font-family="'MyriadPro-Regular'" font-size="12">8</text> +<text transform="matrix(0.6551 0.7289 -0.7438 0.6684 148.3438 52.3242)" font-family="'MyriadPro-Regular'" font-size="12">0</text> +<text transform="matrix(0.6067 0.7696 -0.7853 0.6191 152.3047 56.814)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.4267 0.8822 -0.9002 0.4354 159.2344 67.0146)" font-family="'MyriadPro-Regular'" font-size="11.9996">9</text> +<text transform="matrix(0.3433 0.9179 -0.9366 0.3503 161.8438 72.4062)" font-family="'MyriadPro-Regular'" font-size="11.9996">0</text> +<text transform="matrix(0.2823 0.9384 -0.9576 0.2881 163.8945 78.0513)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(0.1113 0.9737 -0.9935 0.1136 166.2334 87.54)" font-family="'MyriadPro-Regular'" font-size="12">1</text> +<text transform="matrix(0.0217 0.9798 -0.9998 0.0221 166.917 93.5156)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text> +<text transform="matrix(-0.067 0.9777 -0.9977 -0.0684 167.0527 99.502)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text> +<text transform="matrix(-0.1305 0.9713 -0.9911 -0.1331 166.5859 105.5)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(-0.2564 0.9459 -0.9652 -0.2616 165.5303 112.1348)" font-family="'MyriadPro-Regular'" font-size="12">1</text> +<text transform="matrix(-0.3429 0.918 -0.9368 -0.3499 163.9658 117.918)" font-family="'MyriadPro-Regular'" font-size="12">1</text> +<text transform="matrix(-0.4267 0.8822 -0.9002 -0.4354 161.8613 123.5527)" font-family="'MyriadPro-Regular'" font-size="11.9996">0</text> +<text transform="matrix(-0.4834 0.8525 -0.8699 -0.4932 159.1973 128.9287)" font-family="'MyriadPro-Regular'" font-size="12"> </text> +<text transform="matrix(-0.5948 0.7788 -0.7947 -0.607 155.5195 135.0195)" font-family="'MyriadPro-Regular'" font-size="12">1</text> +<text transform="matrix(-0.6637 0.721 -0.7357 -0.6773 151.8789 139.791)" font-family="'MyriadPro-Regular'" font-size="12">2</text> +<text transform="matrix(-0.7269 0.6572 -0.6707 -0.7418 147.8154 144.2051)" font-family="'MyriadPro-Regular'" font-size="12.0006">0</text> +<path fill="#333333" d="M141.121,133.456l7.08,6.485l-0.436,0.475l-7.08-6.484L141.121,133.456z"/> +<path fill="#333333" d="M143.077,132.336l4.927,4.186l-0.541,0.637l-4.926-4.186L143.077,132.336z"/> +<path fill="#333333" d="M144.354,130.73l5.092,4l-0.518,0.658l-5.091-4L144.354,130.73z"/> +<path fill="#333333" d="M145.572,129.104l5.234,3.806l-0.492,0.676l-5.233-3.806L145.572,129.104z"/> +<path fill="#333333" d="M146.73,127.412l5.379,3.6l-0.465,0.694l-5.379-3.601L146.73,127.412z"/> +<path fill="#333333" d="M147.157,125.37l8.179,5.036l-0.338,0.548l-8.18-5.035L147.157,125.37z"/> +<path fill="#333333" d="M148.854,123.91l5.637,3.178l-0.41,0.729l-5.637-3.178L148.854,123.91z"/> +<path fill="#333333" d="M149.814,122.104l5.75,2.963l-0.383,0.742l-5.75-2.963L149.814,122.104z"/> +<path fill="#333333" d="M150.709,120.241l5.861,2.735l-0.354,0.756l-5.861-2.734L150.709,120.241z"/> +<path fill="#333333" d="M151.516,118.376l5.965,2.51l-0.322,0.771l-5.965-2.51L151.516,118.376z"/> +<path fill="#333333" d="M151.539,116.303l8.988,3.389l-0.229,0.603l-8.986-3.388L151.539,116.303z"/> +<path fill="#333333" d="M152.928,114.539l6.141,2.047l-0.266,0.792l-6.14-2.047L152.928,114.539z"/> +<path fill="#333333" d="M153.525,112.57l6.211,1.811l-0.232,0.803l-6.212-1.812L153.525,112.57z"/> +<path fill="#333333" d="M154.046,110.602l6.272,1.562l-0.201,0.812l-6.273-1.563L154.046,110.602z"/> +<path fill="#333333" d="M154.482,108.585l6.336,1.326l-0.172,0.817l-6.334-1.326L154.482,108.585z"/> +<path fill="#333333" d="M154.117,106.549l9.461,1.604l-0.107,0.634l-9.461-1.603L154.117,106.549z"/> +<path fill="#333333" d="M155.132,104.559l6.417,0.833l-0.107,0.828l-6.416-0.833L155.132,104.559z"/> +<path fill="#333333" d="M155.338,102.516l6.448,0.586l-0.075,0.832l-6.447-0.586L155.338,102.516z"/> +<path fill="#333333" d="M155.477,100.476l6.459,0.34l-0.043,0.833l-6.459-0.339L155.477,100.476z"/> +<path fill="#333333" d="M155.529,98.425l6.469,0.103l-0.014,0.835l-6.469-0.103L155.529,98.425z"/> +<path fill="#333333" d="M154.777,96.482l9.6-0.213l0.014,0.643l-9.598,0.214L154.777,96.482z"/> +<path fill="#333333" d="M155.406,94.336l6.458-0.391l0.051,0.833l-6.459,0.391L155.406,94.336z"/> +<path fill="#333333" d="M155.232,92.29l6.438-0.627l0.081,0.831l-6.438,0.627L155.232,92.29z"/> +<path fill="#333333" d="M154.979,90.257l6.407-0.874l0.112,0.827l-6.407,0.874L154.979,90.257z"/> +<path fill="#333333" d="M154.639,88.227l6.377-1.121l0.146,0.823l-6.377,1.121L154.639,88.227z"/> +<path fill="#333333" d="M153.539,86.475l9.384-2.029l0.138,0.629l-9.386,2.029L153.539,86.475z"/> +<path fill="#333333" d="M153.756,84.251l6.264-1.604l0.207,0.809l-6.264,1.604L153.756,84.251z"/> +<path fill="#333333" d="M153.188,82.293l6.203-1.852l0.237,0.801l-6.201,1.852L153.188,82.293z"/> +<path fill="#333333" d="M152.545,80.339l6.13-2.088l0.271,0.791l-6.131,2.088L152.545,80.339z"/> +<path fill="#333333" d="M151.84,78.426l6.036-2.324l0.301,0.779l-6.036,2.324L151.84,78.426z"/> +<path fill="#333333" d="M150.427,76.915l8.819-3.784l0.254,0.592l-8.82,3.784L150.427,76.915z"/> +<path fill="#333333" d="M150.199,74.675l5.841-2.777l0.358,0.754l-5.842,2.777L150.199,74.675z"/> +<path fill="#333333" d="M149.271,72.855L155,69.852l0.389,0.74l-5.729,3.003L149.271,72.855z"/> +<path fill="#333333" d="M148.271,71.069l5.614-3.22l0.415,0.726l-5.615,3.219L148.271,71.069z"/> +<path fill="#333333" d="M147.204,69.314l5.481-3.435l0.442,0.707l-5.481,3.436L147.204,69.314z"/> +<path fill="#333333" d="M145.529,68.108l7.936-5.401l0.362,0.531l-7.935,5.402L145.529,68.108z"/> +<path fill="#333333" d="M144.887,65.962l5.215-3.836l0.494,0.673l-5.214,3.836L144.887,65.962z"/> +<path fill="#333333" d="M143.63,64.343l5.062-4.031l0.521,0.653l-5.062,4.031L143.63,64.343z"/> +<path fill="#333333" d="M142.307,62.78l4.904-4.228l0.546,0.634l-4.905,4.227L142.307,62.78z"/> +<path fill="#333333" d="M140.932,61.255l4.74-4.401l0.568,0.612l-4.741,4.401L140.932,61.255z"/> +<path fill="#333333" d="M139.052,60.387l6.774-6.806l0.456,0.454l-6.774,6.806L139.052,60.387z"/> +<path fill="#333333" d="M138.008,58.389l4.393-4.752l0.613,0.567l-4.392,4.751L138.008,58.389z"/> +<path fill="#333333" d="M136.467,57.041l4.207-4.916l0.635,0.543l-4.207,4.916L136.467,57.041z"/> +<path fill="#333333" d="M134.871,55.746l4.021-5.07l0.654,0.52l-4.021,5.07L134.871,55.746z"/> +<path fill="#333333" d="M133.227,54.52l3.825-5.224l0.675,0.493l-3.826,5.225L133.227,54.52z"/> +<path fill="#333333" d="M131.211,54.016l5.371-7.966l0.534,0.36l-5.371,7.965L131.211,54.016z"/> +<path fill="#333333" d="M129.803,52.251l3.414-5.503l0.711,0.441l-3.414,5.502L129.803,52.251z"/> +<path fill="#333333" d="M128.047,51.223l3.198-5.626l0.726,0.413l-3.197,5.625L128.047,51.223z"/> +<path fill="#333333" d="M126.244,50.255l2.982-5.739l0.739,0.386l-2.981,5.738L126.244,50.255z"/> +<path fill="#333333" d="M124.404,49.366l2.757-5.853l0.755,0.356l-2.756,5.852L124.404,49.366z"/> +<path fill="#333333" d="M122.325,49.252l3.754-8.835l0.592,0.252l-3.754,8.835L122.325,49.252z"/> +<path fill="#333333" d="M120.621,47.796l2.304-6.047l0.781,0.297l-2.304,6.047L120.621,47.796z"/> +<path fill="#333333" d="M118.693,47.118l2.066-6.13l0.791,0.267l-2.066,6.13L118.693,47.118z"/> +<path fill="#333333" d="M116.725,46.524l1.832-6.212l0.801,0.236l-1.83,6.212L116.725,46.524z"/> +<path fill="#333333" d="M114.779,46.004l1.582-6.273l0.812,0.204l-1.584,6.273L114.779,46.004z"/> +<path fill="#333333" d="M112.713,46.28l1.998-9.385l0.629,0.135l-1.999,9.384L112.713,46.28z"/> +<path fill="#333333" d="M110.762,45.182l1.102-6.377l0.822,0.143l-1.101,6.376L110.762,45.182z"/> +<path fill="#333333" d="M108.746,44.895l0.854-6.417l0.828,0.109l-0.854,6.418L108.746,44.895z"/> +<path fill="#333333" d="M106.686,44.667l0.607-6.438l0.831,0.078l-0.606,6.438L106.686,44.667z"/> +<path fill="#333333" d="M104.646,44.531l0.36-6.458l0.833,0.046l-0.359,6.459L104.646,44.531z"/> +<path fill="#333333" d="M102.68,45.202l0.183-9.598l0.644,0.013l-0.184,9.598L102.68,45.202z"/> +<path fill="#333333" d="M100.542,44.489l-0.123-6.469l0.835-0.017l0.123,6.469L100.542,44.489z"/> +<path fill="#333333" d="M98.505,44.581l-0.37-6.458l0.833-0.048l0.37,6.458L98.505,44.581z"/> +<path fill="#333333" d="M96.458,44.747l-0.606-6.438l0.831-0.078l0.606,6.438L96.458,44.747z"/> +<path fill="#333333" d="M94.423,45.004l-0.854-6.418l0.828-0.109l0.854,6.417L94.423,45.004z"/> +<path fill="#333333" d="M92.632,46.025l-1.633-9.46l0.634-0.109l1.633,9.46L92.632,46.025z"/> +<path fill="#333333" d="M90.413,45.722l-1.347-6.324l0.816-0.174l1.347,6.324L90.413,45.722z"/> +<path fill="#333333" d="M88.408,46.207l-1.584-6.273l0.811-0.204l1.583,6.273L88.408,46.207z"/> +<path fill="#333333" d="M86.447,46.767l-1.83-6.212l0.802-0.236l1.83,6.212L86.447,46.767z"/> +<path fill="#333333" d="M84.515,47.387l-2.067-6.13l0.791-0.267l2.067,6.129L84.515,47.387z"/> +<path fill="#333333" d="M82.944,48.742l-3.418-8.972l0.602-0.229l3.418,8.973L82.944,48.742z"/> +<path fill="#333333" d="M80.687,48.877l-2.53-5.954l0.769-0.327l2.53,5.955L80.687,48.877z"/> +<path fill="#333333" d="M78.817,49.73l-2.756-5.852l0.755-0.356l2.757,5.853L78.817,49.73z"/> +<path fill="#333333" d="M77.015,50.641l-2.982-5.738l0.74-0.386l2.982,5.739L77.015,50.641z"/> +<path fill="#333333" d="M75.205,51.646l-3.198-5.626l0.726-0.413l3.199,5.626L75.205,51.646z"/> +<path fill="#333333" d="M73.931,53.274l-5.066-8.163l0.547-0.34l5.066,8.164L73.931,53.274z"/> +<path fill="#333333" d="M71.764,53.824l-3.62-5.368l0.692-0.468l3.62,5.368L71.764,53.824z"/> +<path fill="#333333" d="M70.097,55.016l-3.826-5.225l0.675-0.493l3.825,5.225L70.097,55.016z"/> +<path fill="#333333" d="M68.474,56.267l-4.021-5.07l0.655-0.521l4.021,5.07L68.474,56.267z"/> +<path fill="#333333" d="M66.896,57.584l-4.206-4.916l0.634-0.543l4.207,4.916L66.896,57.584z"/> +<path fill="#333333" d="M65.941,59.427l-6.515-7.05l0.472-0.437l6.516,7.05L65.941,59.427z"/> +<path fill="#333333" d="M63.906,60.392l-4.566-4.587l0.592-0.59l4.566,4.587L63.906,60.392z"/> +<path fill="#333333" d="M62.501,61.867l-4.741-4.401l0.568-0.612l4.741,4.402L62.501,61.867z"/> +<path fill="#333333" d="M61.145,63.415l-4.906-4.227l0.546-0.634l4.905,4.228L61.145,63.415z"/> +<path fill="#333333" d="M59.848,64.996l-5.06-4.031l0.521-0.653l5.06,4.031L59.848,64.996z"/> +<path fill="#333333" d="M59.263,66.991L51.526,61.3l0.381-0.519l7.736,5.691L59.263,66.991z"/> +<path fill="#333333" d="M57.446,68.317l-5.358-3.63l0.469-0.691l5.358,3.63L57.446,68.317z"/> +<path fill="#333333" d="M56.349,70.033l-5.492-3.425l0.442-0.709l5.491,3.425L56.349,70.033z"/> +<path fill="#333333" d="M55.312,71.795l-5.615-3.219l0.415-0.726l5.615,3.22L55.312,71.795z"/> +<path fill="#333333" d="M54.34,73.605l-5.738-2.993l0.386-0.74l5.739,2.992L54.34,73.605z"/> +<path fill="#333333" d="M54.141,75.654l-8.667-4.12l0.275-0.58l8.667,4.119L54.141,75.654z"/> +<path fill="#333333" d="M52.61,77.307l-5.944-2.551l0.33-0.768l5.944,2.551L52.61,77.307z"/> +<path fill="#333333" d="M51.851,79.216l-6.037-2.314l0.299-0.779l6.037,2.314L51.851,79.216z"/> +<path fill="#333333" d="M51.177,81.153l-6.13-2.088l0.27-0.791l6.13,2.088L51.177,81.153z"/> +<path fill="#333333" d="M50.569,83.094l-6.201-1.851l0.238-0.801l6.202,1.852L50.569,83.094z"/> +<path fill="#333333" d="M50.768,85.146l-9.293-2.38l0.159-0.623l9.293,2.38L50.768,85.146z"/> +<path fill="#333333" d="M49.584,87.067l-6.325-1.368l0.177-0.816l6.325,1.368L49.584,87.067z"/> +<path fill="#333333" d="M49.213,89.074l-6.377-1.121l0.146-0.823l6.376,1.121L49.213,89.074z"/> +<path fill="#333333" d="M48.907,91.083l-6.406-0.874l0.112-0.827l6.407,0.874L48.907,91.083z"/> +<path fill="#333333" d="M48.687,93.121l-6.438-0.628l0.081-0.831l6.438,0.628L48.687,93.121z"/> +<path fill="#333333" d="M49.276,95.13l-9.583-0.564l0.038-0.643l9.583,0.564L49.276,95.13z"/> +<path fill="#333333" d="M48.475,97.23l-6.47-0.144l0.019-0.835l6.47,0.144L48.475,97.23z"/> +<path fill="#333333" d="M48.483,99.283l-6.47,0.103L42,98.551l6.469-0.103L48.483,99.283z"/> +<path fill="#333333" d="M48.568,101.321l-6.458,0.35l-0.046-0.833l6.459-0.35L48.568,101.321z"/> +<path fill="#333333" d="M48.737,103.374l-6.448,0.586l-0.075-0.832l6.448-0.587L48.737,103.374z"/> +<path fill="#333333" d="M49.688,105.223l-9.521,1.235l-0.083-0.638l9.521-1.236L49.688,105.223z"/> +<path fill="#333333" d="M49.291,107.421l-6.377,1.08l-0.139-0.823l6.376-1.08L49.291,107.421z"/> +<path fill="#333333" d="M49.691,109.426l-6.335,1.327l-0.172-0.817l6.335-1.326L49.691,109.426z"/> +<path fill="#333333" d="M50.159,111.432l-6.273,1.563l-0.202-0.812l6.274-1.562L50.159,111.432z"/> +<path fill="#333333" d="M50.707,113.372l-6.212,1.81l-0.233-0.802l6.212-1.81L50.707,113.372z"/> +<path fill="#333333" d="M51.998,115.01l-9.109,3.037l-0.204-0.609l9.11-3.037L51.998,115.01z"/> +<path fill="#333333" d="M52.037,117.253l-6.058,2.283l-0.294-0.782l6.058-2.281L52.037,117.253z"/> +<path fill="#333333" d="M52.807,119.146l-5.966,2.509l-0.323-0.771l5.965-2.51L52.807,119.146z"/> +<path fill="#333333" d="M53.652,121.018l-5.862,2.735l-0.353-0.757l5.862-2.735L53.652,121.018z"/> +<path fill="#333333" d="M54.565,122.846l-5.749,2.963l-0.382-0.742l5.749-2.963L54.565,122.846z"/> +<path fill="#333333" d="M56.144,124.195l-8.362,4.716l-0.315-0.562l8.361-4.715L56.144,124.195z"/> +<path fill="#333333" d="M56.606,126.384l-5.513,3.394l-0.438-0.711l5.513-3.395L56.606,126.384z"/> +<path fill="#333333" d="M57.731,128.107l-5.379,3.6l-0.464-0.693l5.378-3.601L57.731,128.107z"/> +<path fill="#333333" d="M58.918,129.779l-5.235,3.805l-0.491-0.676l5.235-3.805L58.918,129.779z"/> +<path fill="#333333" d="M60.164,131.405l-5.08,4l-0.517-0.655l5.08-4.001L60.164,131.405z"/> +<path fill="#333333" d="M61.971,132.432l-7.31,6.226l-0.417-0.49l7.31-6.226L61.971,132.432z"/> +<path fill="#FFF200" d="M137.911,69.32l3.624-2.875c-5.367-6.779-12.527-12.29-21.146-15.7l-1.701,4.304 + C126.523,58.147,133.029,63.156,137.911,69.32z"/> +<path fill="#FFB700" d="M147.43,91.292l4.574-0.677c-1.314-8.823-4.932-17.174-10.469-24.17l-3.624,2.875 + C142.945,75.68,146.232,83.27,147.43,91.292z"/> +<path fill="#FFF200" d="M94.898,52.31l-0.677-4.574c-8.823,1.314-17.173,4.932-24.167,10.469l2.875,3.623 + C79.287,56.793,86.878,53.505,94.898,52.31z"/> +<path fill="#FFB700" d="M72.93,61.827l-2.875-3.623c-6.781,5.367-12.291,12.525-15.702,21.146l4.303,1.701 + C61.755,73.216,66.765,66.707,72.93,61.827z"/> +<path fill="#59DE00" d="M118.688,55.049l1.701-4.304c-8.621-3.408-17.613-4.285-26.167-3.01l0.677,4.574 + C102.676,51.151,110.85,51.948,118.688,55.049z"/> +</svg> diff --git a/examples/declarative/dial/DialLibrary/needle.svg b/examples/declarative/dial/DialLibrary/needle.svg new file mode 100644 index 0000000..dce7d7e --- /dev/null +++ b/examples/declarative/dial/DialLibrary/needle.svg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> +]> +<svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="210px" height="210px" viewBox="-98 -35 210 210" enable-background="new -98 -35 210 210" + xml:space="preserve"> +<defs> +</defs> +<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-102.5" y1="-13.5" x2="-94.5" y2="-13.5" gradientTransform="matrix(1 0 0 -1 102.5 18)"> + <stop offset="0" style="stop-color:#EC1C24"/> + <stop offset="0.0782" style="stop-color:#E51B23"/> + <stop offset="0.3901" style="stop-color:#CA181F"/> + <stop offset="0.5495" style="stop-color:#F0C7C9"/> + <stop offset="0.5972" style="stop-color:#D98D90"/> + <stop offset="0.6452" style="stop-color:#C4595D"/> + <stop offset="0.687" style="stop-color:#B53339"/> + <stop offset="0.7206" style="stop-color:#AC1C22"/> + <stop offset="0.7418" style="stop-color:#A9141A"/> + <stop offset="1" style="stop-color:#EC1C24"/> +</linearGradient> +<path fill="url(#SVGID_1_)" d="M8,61c0,1.104-2.343,2-4,2l0,0c-1.657,0-4-0.896-4-2L2.5,2C2.5,0.896,3,0,4,0l0,0 + c1,0,1.5,0.896,1.5,2L8,61z"/> +</svg> diff --git a/examples/declarative/dial/DialLibrary/needle_shadow.svg b/examples/declarative/dial/DialLibrary/needle_shadow.svg new file mode 100644 index 0000000..6aab197 --- /dev/null +++ b/examples/declarative/dial/DialLibrary/needle_shadow.svg @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> +]> +<svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="210px" height="210px" viewBox="-90 -30 210 210" enable-background="new -90 -30 210 210" + xml:space="preserve"> +<defs> +</defs> +<image overflow="visible" opacity="0.5" enable-background="new " width="26" height="81" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAABSCAYAAAClg6/xAAAACXBIWXMAAAsSAAALEgHS3X78AAAA +GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAydJREFUeNrsmetu2zAMhUVaS9pu +2Pu/5dY2vaSJ7dkAOZ8y1M3Jjw6zAUKx4ugLJZo+FkPYjhsc1Hidd/1o2tUwhKAhCC0LpQJIjcG0 +TwEDmAU3webBO7EInxXWi53h89AK038/D/xNbCdtBNgMOU32Ie1JgK53OZh6M0PuwHbi8SCQd7AP +8PIC1iVguj6zJ/vJ7if7AfYgUJ3SIbF21TCdwtmb7wL5Ke09wAazbklYLIR7B949gFdRBu+kPco0 +dub3YwkWTMjjuul0KmwUyE762LkXi7Ac8E681eirArXANDLxFiC4FboaGGcgwckenWM2u4QUlBty +IxtP2fQXcy03JmE2EHYSNK2BhUQiThmVPIsNGb8zSXlw1o2uCX12Mr9G4GieBDZImj2zYY9PgADn +VeEfK9bJ3mN7ack8drrS+sVCBCoIYTvwDGERcqObH3OJ2Hpmp3J0QAwRTmvWLAUcE6DkmvHK0E+l +LGqBUSFzsElXXMgk1JJBPGjuPKzNjWvU8VWw1JRQZuqv8owy0o9a3hu+1DTe9NhgG2yDJZPvWmsW +qWt04yqtn9L5pT5q1fqlJ3SseGJXSzlPnFrrzXkRGAtTaIUOtoM594QqpWBUUMO2HZx+TxX/1Y6x +oBnZmUbrmSfnXO3IFTrfrlupj1uikSpkXFch57IwSqybNyAXvneFUqtubE5Ra6RcreC5+gU+pw+p +IO+2h+cG22BfEFaTiv6N19zS22Su3pL9LVfmRa/IkysYNG8BBjPoOSy1F5JW+/C65s1N9GQe7CN8 +rrv0AnuH784ZTy9gtvDWA2ge9GWy57DUaE5y/hL8os/F2saEVwh6m+ww2WNYKhXaPkv/Qa6rrjLZ +CoVVT0EGmQd8nexpst+T/RJ7FPhrWOppn6CdE50MG5soo7FedgCY2pP0z98fw1JxGlIhiqUsrZtp +OcuWsnozzQdZvzeBnQCY1BkM07cX04LPPix1mFEGPEKUHsXOJjqTNx9ndr1xHxgD6QR29qYwJ8co +8cKHG854i2h1sM9lFqpItuxsZHo3/2imrbqam9tvtLAQblCBr71+DP/98UeAAQDKLu+cxVe7aAAA +AABJRU5ErkJggg=="> +</image> +</svg> diff --git a/examples/declarative/dial/DialLibrary/overlay.svg b/examples/declarative/dial/DialLibrary/overlay.svg new file mode 100644 index 0000000..8530dd5 --- /dev/null +++ b/examples/declarative/dial/DialLibrary/overlay.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> +]> +<svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="210px" height="210px" viewBox="-21.12 -18.396 210 210" enable-background="new -21.12 -18.396 210 210" + xml:space="preserve"> +<defs> +</defs> +<image overflow="visible" opacity="0.5" enable-background="new " width="48" height="48" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAAAxCAYAAABznEEcAAAACXBIWXMAAAsSAAALEgHS3X78AAAA +GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/JJREFUeNrsWolum0AQZQHfOdrc +//93bZO2OVwTx2YL0hvpaTK7C7iJUhSkJ2wMu/N2jp0ZnGWfx8c43BuPx9+9+s1/FBKOzs4YM0TC +09kfSsod8JxGblzLjNVn1MY1/9YktNCCAuBrztCECC7YA3ytNxk3gAALXQIToFRkNAkWftfgBdgB +TKozEdeDgAgmgk+BGWEKMkxEDibQCr5t8EzYAkKINXMwCV59WfV5gwWwBBa4PlUaYRKigVbYqsGm +wR9gA1SknX0XIq4HgQkEFMGPGhwTVkRkEiHxQgTWDR4JT0Roi3uTRFwPAjMS/qTBaYMvwAkREbMq +yC88kRAzEgIPDX4D9/guZJ67EHEJJ2YCKwjaCn/W4BznMxAZSqIV/idwh/M9flsrIqazlwktiA8s +oIGWwAVwhfM5rh9DU7MO5vSMlX7EuAs8x894I+zWXUmwFkrY+BImcwbBbxpcN7jEtVPyCQm1oegk +oXUDAkw8N+7dKzJOEykTvjBVWjiHBq6BltBXaEFWs1SmpPcJiVBzFc1yQ2NbtYeY+0fRgcAxBBUT +ugEuDVOa014xoT2lJHLWtYII643wJeXcRcQXxJnFkUUDN/gsBLRJlLSyevcuAqmKIzPRm+E2FW41 +CZlANrQjRJ4LrLz4wQVFpGVgp3YR8D1sdjWtfAUSFUWonRWlLBIxU7pSfqCdMjfSc2ek6i6QqnP0 +qtQuvg2F2jJQG+SUH0mKsQKW5MRWnuQ6ZAie7ue9SLKBlcoA2PlZTp+pEGhlqhMiwoneJBCF+iSU +obyM55kbpvqqVskTGSsPPqUBYyl33/rk4LnyRN3AUaQIFD+HFFg6oKTmcykSlvPlEbiBwqdMKzaf +FRxMTaQqu/fqwnSeqw+JQUX8wKPXXHngQauor42C/l/0j7yRtYbms1o9pia8UdRr8OBDm2HeyHBT +85kaCpGwuhKcw1gp8lAtHDxXHtECJ2KV6kyECnk/0ISYAM9TBZI/H/MJHlh3JdaAFPK6/q07OCX/ +VhvVnnQ/ZC7Om3ahBSs6pB0zKmAWgdTDRXqwMZ/bUca6Rm3d1tm3DX7g8y80D6RxoMm8IqGJcHdv +Rs0yKx3IEl1vHzAf0fIDmgQtge8gcYtGwiO1cfYqoAQ1YeU0sYrMJUymplRbN9AsAkJCOh/rkBZS +mnCRnMZKBVKheacqtk2CwC1M6cnQQpJE6N1DHilmaiUs18hb1XfdULvmXhH4BggB0UKlqrqsCwld +eDhl59o8QgJzdSZR54m6fndKA0LgDgRECxLSzcg3ig7gqHuxo+mKj+b9xGjeFI3mnd1o3p6O5j12 +alfPsv/oHwVdx3uX/3Z8Hh/l+CvAAIH3kc3b00M7AAAAAElFTkSuQmCC" transform="matrix(1 0 0 1 57.8799 59.604)"> +</image> +<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-26.0957" y1="-12.2373" x2="-17.2345" y2="-44.2323" gradientTransform="matrix(1 0 0 -1 102.5 51.208)"> + <stop offset="0" style="stop-color:#FFFFFF"/> + <stop offset="1" style="stop-color:#000000"/> +</linearGradient> +<circle fill="url(#SVGID_1_)" cx="80.88" cy="79.604" r="15"/> +<radialGradient id="SVGID_2_" cx="-28.9624" cy="-17.0811" r="25.2655" gradientTransform="matrix(1 0 0 -1 102.5 51.208)" gradientUnits="userSpaceOnUse"> + <stop offset="0" style="stop-color:#FFFFFF"/> + <stop offset="1" style="stop-color:#616161"/> +</radialGradient> +<path fill="url(#SVGID_2_)" d="M80.88,92.603c-7.167,0-12.999-5.832-12.999-13c-0.001-7.166,5.832-12.999,12.999-12.999 + s13,5.832,13,12.999C93.879,86.771,88.047,92.603,80.88,92.603L80.88,92.603z"/> +<path opacity="0.5" fill="#FFFFFF" enable-background="new " d="M10.697,75.919c27.161-27.154,64.439-42.608,102.867-42.608 + c11.422,0,22.744,1.386,33.739,4.018C133.183,14.903,108.235,0,79.768,0C35.712,0,0,35.714,0,79.768c0,2.589,0.14,5.14,0.387,7.648 + C3.609,83.419,7.044,79.58,10.697,75.919z"/> +</svg> diff --git a/examples/declarative/dial/dial.qml b/examples/declarative/dial/dial.qml new file mode 100644 index 0000000..ce43b01 --- /dev/null +++ b/examples/declarative/dial/dial.qml @@ -0,0 +1,14 @@ +<?qtfx namespacepath:=DialLibrary ?> +<Rect color="white" width="210" height="240"> + <!-- Dial with a slider to adjust it --> + <Dial id="Dial" value="{Slider.x-2}"/> + <Rect anchors.top="{Dial.bottom}" x="20" width="160" height="16" color="steelblue" gradientColor="lightsteelblue" radius="8" opacity="0.7"> + <Rect id="Slider" anchors.top="{Dial.bottom}" x="2" y="2" width="30" height="12" color="lightgray" gradientColor="gray" radius="6"> + <MouseRegion anchors.fill="{parent}" + drag.target="{parent}" + drag.axis="x" + drag.xmin="2" + drag.xmax="128"/> + </Rect> + </Rect> +</Rect> diff --git a/examples/declarative/easing/easing.qml b/examples/declarative/easing/easing.qml new file mode 100644 index 0000000..f95d8c6 --- /dev/null +++ b/examples/declarative/easing/easing.qml @@ -0,0 +1,67 @@ +<Rect id="Window" width="640" height="{Layout.height}" color="white"> + + <resources> + <ListModel id="EasingTypes"> + <ListItem><type>easeLinear</type></ListItem> + <ListItem><type>easeInQuad</type></ListItem> + <ListItem><type>easeOutQuad</type></ListItem> + <ListItem><type>easeInOutQuad</type></ListItem> + <ListItem><type>easeOutInQuad</type></ListItem> + <ListItem><type>easeInCubic</type></ListItem> + <ListItem><type>easeOutCubic</type></ListItem> + <ListItem><type>easeInOutCubic</type></ListItem> + <ListItem><type>easeOutInCubic</type></ListItem> + <ListItem><type>easeInQuart</type></ListItem> + <ListItem><type>easeOutQuart</type></ListItem> + <ListItem><type>easeInOutQuart</type></ListItem> + <ListItem><type>easeOutInQuart</type></ListItem> + <ListItem><type>easeInQuint</type></ListItem> + <ListItem><type>easeOutQuint</type></ListItem> + <ListItem><type>easeInOutQuint</type></ListItem> + <ListItem><type>easeOutInQuint</type></ListItem> + <ListItem><type>easeInSine</type></ListItem> + <ListItem><type>easeOutSine</type></ListItem> + <ListItem><type>easeInOutSine</type></ListItem> + <ListItem><type>easeOutInSine</type></ListItem> + <ListItem><type>easeInExpo</type></ListItem> + <ListItem><type>easeOutExpo</type></ListItem> + <ListItem><type>easeInOutExpo</type></ListItem> + <ListItem><type>easeOutInExpo</type></ListItem> + <ListItem><type>easeInCirc</type></ListItem> + <ListItem><type>easeOutCirc</type></ListItem> + <ListItem><type>easeInOutCirc</type></ListItem> + <ListItem><type>easeOutInCirc</type></ListItem> + <ListItem><type>easeInElastic</type></ListItem> + <ListItem><type>easeOutElastic</type></ListItem> + <ListItem><type>easeInOutElastic</type></ListItem> + <ListItem><type>easeOutInElastic</type></ListItem> + <ListItem><type>easeInBack</type></ListItem> + <ListItem><type>easeOutBack</type></ListItem> + <ListItem><type>easeInOutBack</type></ListItem> + <ListItem><type>easeOutInBack</type></ListItem> + <ListItem><type>easeOutBounce</type></ListItem> + <ListItem><type>easeInBounce</type></ListItem> + <ListItem><type>easeInOutBounce</type></ListItem> + <ListItem><type>easeOutInBounce</type></ListItem> + </ListModel> + </resources> + + <VerticalLayout id="Layout" anchors.left="{Window.left}" anchors.right="{Window.right}"> + <Repeater dataSource="{EasingTypes}"> + <Component> + <Text id="Text" text="{type}" height="18" font.italic="true"> + <x> + <SequentialAnimation id="Anim"> + <NumericAnimation from="0" to="{Window.width / 2}" easing="{type}" duration="1000"/> + <PauseAnimation duration="300"/> + <NumericAnimation to="0" from="{Window.width / 2}" easing="{type}" duration="1000"/> + </SequentialAnimation> + </x> + <children> + <MouseRegion onClicked="Anim.running=true" anchors.fill="{parent}"/> + </children> + </Text> + </Component> + </Repeater> + </VerticalLayout> +</Rect> diff --git a/examples/declarative/follow/follow.qml b/examples/declarative/follow/follow.qml new file mode 100644 index 0000000..0f3e772 --- /dev/null +++ b/examples/declarative/follow/follow.qml @@ -0,0 +1,35 @@ +<Rect width="320" height="240" color="#ffffff"> + <Rect id="Rect" y="{200}" color="#00ff00" width="60" height="20"> + <y> + <SequentialAnimation running="true" repeat="true"> + <NumericAnimation to="{200}" easing="easeOutBounce(amplitude:180)" duration="2000" /> + <PauseAnimation duration="1000" /> + </SequentialAnimation> + </y> + </Rect> + <!-- Velocity --> + <Rect x="{Rect.width}" color="#ff0000" width="{Rect.width}" height="20"> + <y> + <Follow source="{Rect.y}" velocity="200"/> + </y> + </Rect> + <Text x="{Rect.width}" y="220" text="Velocity"/> + <!-- Spring --> + <Rect x="{Rect.width * 2}" color="#ff0000" width="{Rect.width}" height="20"> + <y> + <Follow source="{Rect.y}" spring="1.2" damping="0.1"/> + </y> + </Rect> + <Text x="{Rect.width * 2}" y="220" text="Spring"/> + <!-- Follow mouse --> + <MouseRegion id="Mouse" anchors.fill="{parent}"> + <Rect width="20" height="20" radius="10" color="#0000ff"> + <x> + <Follow source="{Mouse.mouseX-10}" spring="1.0" damping="0.05"/> + </x> + <y> + <Follow source="{Mouse.mouseY-10}" spring="1.0" damping="0.05"/> + </y> + </Rect> + </MouseRegion> +</Rect> diff --git a/examples/declarative/follow/pong.qml b/examples/declarative/follow/pong.qml new file mode 100644 index 0000000..4fbf323 --- /dev/null +++ b/examples/declarative/follow/pong.qml @@ -0,0 +1,55 @@ +<Rect id="Page" width="640" height="480" color="#000000"> + <!-- Make a ball to bounce --> + <Rect id="Ball" x="20" width="20" height="20" color="#00ee00" z="1"> + <properties> + <!-- Add a property for the target y coordinate --> + <Property name="targetY" value="{Page.height-10}"/> + <Property name="direction" value="right"/> + </properties> + <x> + <!-- Move the ball to the right and back to the left repeatedly --> + <SequentialAnimation running="true" repeat="true"> + <NumericAnimation to="{Page.width-40}" duration="2000"/> + <SetPropertyAction target="{Ball}" property="direction" value="left"/> + <NumericAnimation to="20" duration="2000"/> + <SetPropertyAction target="{Ball}" property="direction" value="right"/> + </SequentialAnimation> + </x> + <y> + <!-- Make y follow the target y coordinate, with a velocity of 200 --> + <Follow source="{Ball.targetY}" velocity="200"/> + </y> + <onTopChanged> + <!-- Detect the ball hitting the top or bottom of the view and bounce it --> + if (y <= 0) + targetY = Page.height-20; + else if (y >= Page.height-20) + targetY = 0; + </onTopChanged> + </Rect> + <!-- + Place bats to the left and right of the view, following the y + coordinates of the ball. + --> + <Rect id="LeftBat" color="#00ee00" x="2" width="20" height="90"> + <y> + <Follow source="{Ball.y-45}" velocity="300" enabled="{Ball.direction == 'left'}"/> + </y> + </Rect> + <Rect id="RightBat" x="{Page.width-22}" color="#00ee00" width="20" height="90"> + <y> + <Follow source="{Ball.y-45}" velocity="300" enabled="{Ball.direction == 'right'}"/> + </y> + </Rect> + + <!-- + The rest, to make it look realistic, if neither ever scores... + --> + <Rect color="#00ee00" width="40" height="60" x="{320-80}"/> + <Rect color="#000000" width="20" height="40" x="{320-70}" y="10"/> + <Rect color="#00ee00" width="40" height="60" x="{320+40}"/> + <Rect color="#000000" width="20" height="40" x="{320+50}" y="10"/> + <Repeater dataSource="{24}"> + <Rect color="#00ee00" width="10" height="10" x="{320-5}" y="{index*20}"/> + </Repeater> +</Rect> diff --git a/examples/declarative/listview/content/MediaButton.qml b/examples/declarative/listview/content/MediaButton.qml new file mode 100644 index 0000000..c92305a --- /dev/null +++ b/examples/declarative/listview/content/MediaButton.qml @@ -0,0 +1,21 @@ +<Item id="Container"> + <signals> + <Signal name="clicked"/> + </signals> + + <properties> + <Property name="text"/> + </properties> + + <Image id="Image" src="pics/button.png"/> + <Image id="Pressed" src="pics/button-pressed.png" opacity="0"/> + <MouseRegion id="MouseRegion" anchors.fill="{Image}" onClicked="Container.clicked.emit();"/> + <Text font.bold="true" color="white" anchors.centeredIn="{Image}" text="{Container.text}"/> + <width>{Image.width}</width> + + <states> + <State name="Pressed" when="{MouseRegion.pressed == true}"> + <SetProperties target="{Pressed}" opacity="1"/> + </State> + </states> +</Item> diff --git a/examples/declarative/listview/content/pics/button-pressed.png b/examples/declarative/listview/content/pics/button-pressed.png Binary files differnew file mode 100644 index 0000000..e434d32 --- /dev/null +++ b/examples/declarative/listview/content/pics/button-pressed.png diff --git a/examples/declarative/listview/content/pics/button.png b/examples/declarative/listview/content/pics/button.png Binary files differnew file mode 100644 index 0000000..56a63ce --- /dev/null +++ b/examples/declarative/listview/content/pics/button.png diff --git a/examples/declarative/listview/content/pics/fruit-salad.jpg b/examples/declarative/listview/content/pics/fruit-salad.jpg Binary files differnew file mode 100644 index 0000000..da5a6b1 --- /dev/null +++ b/examples/declarative/listview/content/pics/fruit-salad.jpg diff --git a/examples/declarative/listview/content/pics/hamburger.jpg b/examples/declarative/listview/content/pics/hamburger.jpg Binary files differnew file mode 100644 index 0000000..d0a15be --- /dev/null +++ b/examples/declarative/listview/content/pics/hamburger.jpg diff --git a/examples/declarative/listview/content/pics/lemonade.jpg b/examples/declarative/listview/content/pics/lemonade.jpg Binary files differnew file mode 100644 index 0000000..db445c9 --- /dev/null +++ b/examples/declarative/listview/content/pics/lemonade.jpg diff --git a/examples/declarative/listview/content/pics/pancakes.jpg b/examples/declarative/listview/content/pics/pancakes.jpg Binary files differnew file mode 100644 index 0000000..60c4396 --- /dev/null +++ b/examples/declarative/listview/content/pics/pancakes.jpg diff --git a/examples/declarative/listview/content/pics/vegetable-soup.jpg b/examples/declarative/listview/content/pics/vegetable-soup.jpg Binary files differnew file mode 100644 index 0000000..9dce332 --- /dev/null +++ b/examples/declarative/listview/content/pics/vegetable-soup.jpg diff --git a/examples/declarative/listview/dummydata/MyPetsModel.qml b/examples/declarative/listview/dummydata/MyPetsModel.qml new file mode 100644 index 0000000..5af7fbf --- /dev/null +++ b/examples/declarative/listview/dummydata/MyPetsModel.qml @@ -0,0 +1,51 @@ +<!-- +ListModel allows free form list models to be defined and populated. +Be sure to name the file the same as the id. +--> +<ListModel id="MyPetsModel"> + <Pet> + <name>Rover</name> + <type>Dog</type> + <age>5</age> + </Pet> + <Pet> + <name>Whiskers</name> + <type>Cat</type> + <age>2</age> + </Pet> + <Pet> + <name>Warren</name> + <type>Rabbit</type> + <age>2</age> + </Pet> + <Pet> + <name>Polly</name> + <type>Parrot</type> + <age>12</age> + </Pet> + <Pet> + <name>Spot</name> + <type>Dog</type> + <age>9</age> + </Pet> + <Pet> + <name>Tiny</name> + <type>Elephant</type> + <age>15</age> + </Pet> + <Pet> + <name>Penny</name> + <type>Turtle</type> + <age>4</age> + </Pet> + <Pet> + <name>Joey</name> + <type>Kangaroo</type> + <age>1</age> + </Pet> + <Pet> + <name>Kimba</name> + <type>Bunny</type> + <age>65</age> + </Pet> +</ListModel> diff --git a/examples/declarative/listview/dummydata/Recipies.qml b/examples/declarative/listview/dummydata/Recipies.qml new file mode 100644 index 0000000..49bc610 --- /dev/null +++ b/examples/declarative/listview/dummydata/Recipies.qml @@ -0,0 +1,112 @@ +<ListModel id="Recipies"> + <Recipe title="Pancakes" picture="content/pics/pancakes.jpg"> + <ingredients> + <![CDATA[ + <html> + <ul> + <li> 1 cup (150g) self-raising flour + <li> 1 tbs caster sugar + <li> 3/4 cup (185ml) milk + <li> 1 egg + </ul> + </html> + ]]> + </ingredients> + <method> + <![CDATA[ + <html> + <ol> + <li> Sift flour and sugar together into a bowl. Add a pinch of salt. + <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth. + <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface. + <li> Turn over and cook other side until golden. + </ol> + ]]> + </method> + </Recipe> + <Recipe title="Fruit Salad" picture="content/pics/fruit-salad.jpg"> + <ingredients> + * Seasonal Fruit + </ingredients> + <method> + * Chop fruit and place in a bowl. + </method> + </Recipe> + <Recipe title="Vegetable Soup" picture="content/pics/vegetable-soup.jpg"> + <ingredients> + <![CDATA[ + <html> + <ul> + <li> 1 onion + <li> 1 turnip + <li> 1 potato + <li> 1 carrot + <li> 1 head of celery + <li> 1 1/2 litres of water + </ul> + </html> + ]]> + </ingredients> + <method> + <![CDATA[ + <html> + <ol> + <li> Chop vegetables. + <li> Boil in water until vegetables soften. + <li> Season with salt and pepper to taste. + </ol> + </html> + ]]> + </method> + </Recipe> + <Recipe title="Hamburger" picture="content/pics/hamburger.jpg"> + <ingredients> + <![CDATA[ + <html> + <ul> + <li> 500g minced beef + <li> Seasoning + <li> lettuce, tomato, onion, cheese + <li> 1 hamburger bun for each burger + </ul> + </html> + ]]> + </ingredients> + <method> + <![CDATA[ + <html> + <ol> + <li> Mix the beef, together with seasoning, in a food processor. + <li> Shape the beef into burgers. + <li> Grill the burgers for about 5 mins on each side (until cooked through) + <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion. + </ol> + </html> + ]]> + </method> + </Recipe> + <Recipe title="Lemonade" picture="content/pics/lemonade.jpg"> + <ingredients> + <![CDATA[ + <html> + <ul> + <li> 1 cup Lemon Juice + <li> 1 cup Sugar + <li> 6 Cups of Water (2 cups warm water, 4 cups cold water) + </ul> + </html> + ]]> + </ingredients> + <method> + <![CDATA[ + <html> + <ol> + <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves. + <li> Pour in lemon juice, stir again, and add 4 cups of cold water. + <li> Chill or serve over ice cubes. + </ol> + </html> + ]]> + </method> + </Recipe> +</ListModel> diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml new file mode 100644 index 0000000..5ce7acb --- /dev/null +++ b/examples/declarative/listview/highlight.qml @@ -0,0 +1,56 @@ +<Rect width="400" height="300" color="white"> + + <!-- + MyPets model is defined in dummydata/MyPetsModel.qml + The viewer automatically loads files in dummydata/* to assist + development without a real data source. + This one contains my pets. + --> + + <!-- + Define a delegate component. A component will be + instantiated for each visible item in the list. + --> + <Component id="PetDelegate"> + <Item id="Wrapper" width="200" height="50"> + <VerticalLayout> + <Text text="{'Name: ' + name}"/> + <Text text="{'Type: ' + type}"/> + <Text text="{'Age: ' + age}"/> + </VerticalLayout> + + <!-- + Use the ListView.isCurrentItem attached property to + indent the item if it is the current item. + --> + <states> + <State name="Current" when="{Wrapper.ListView.isCurrentItem}"> + <SetProperty target="{Wrapper}" property="x" value="10"/> + </State> + </states> + <transitions> + <Transition> + <NumericAnimation properties="x" duration="200" /> + </Transition> + </transitions> + </Item> + </Component> + + <!-- + Specify a highlight with custom movement. Note that autoHighlight + is set to false in the ListView so that we can control how the + highlight moves to the current item. + --> + <Component id="PetHighlight"> + <Rect width="200" height="50" color="#FFFF88"> + <y> + <Follow source="{List1.current.y}" spring="3" damping="0.1"/> + </y> + </Rect> + </Component> + + <ListView id="List1" width="200" height="{parent.height}" model="{MyPetsModel}" + delegate="{PetDelegate}" highlight="{PetHighlight}" autoHighlight="false" + focus="true"/> + +</Rect> diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml new file mode 100644 index 0000000..08c8f18 --- /dev/null +++ b/examples/declarative/listview/listview.qml @@ -0,0 +1,81 @@ +<Rect width="600" height="300" color="white"> + + <!-- + MyPets model is defined in dummydata/MyPetsModel.qml + The viewer automatically loads files in dummydata/* to assist + development without a real data source. + This one contains my pets. + --> + + <!-- + Define a delegate component. A component will be + instantiated for each visible item in the list. + --> + <Component id="PetDelegate"> + <Item id="Wrapper" width="200" height="50"> + <VerticalLayout> + <Text text="{'Name: ' + name}"/> + <Text text="{'Type: ' + type}"/> + <Text text="{'Age: ' + age}"/> + </VerticalLayout> + </Item> + </Component> + + <!-- + Define a highlight component. Just one of these will be instantiated + by each ListView and placed behind the current item. + --> + <Component id="PetHighlight"> + <Rect color="#FFFF88"/> + </Component> + + <!-- + Show the model in three lists, with different currentItemPositioning. + currentItemPositioning determines how the list behaves when the + current item changes. Note that the second and third ListView + set their currentIndex to be the same as the first, and that + the first ListView is given keyboard focus. + + The default mode, Free, allows the currentItem to move freely + within the visible area. If it would move outside the visible + area, the view is scrolled to keep it visible. + + Snap currentItemPositioning attempts to keep the current item + aligned with the snapPosition by scrolling the view, however the + items will not scroll beyond the beginning or end of the view. + + SnapAuto currentItemPositioning always keeps the current item on + the snapPosition by scrolling the view. It also automatically + sets the current item as is scrolled with the mouse. Note + that the first ListView sets its currentIndex to be equal to + the third ListView's currentIndex. By flicking List3 with + the mouse, the current index of List1 will be changed. + --> + + <ListView id="List1" width="200" height="{parent.height}" model="{MyPetsModel}" + delegate="{PetDelegate}" highlight="{PetHighlight}" + currentIndex="{List3.currentIndex}" focus="true"/> + + <ListView id="List2" x="200" width="200" height="{parent.height}" model="{MyPetsModel}" + delegate="{PetDelegate}" highlight="{PetHighlight}" + currentItemPositioning="Snap" snapPosition="125" + currentIndex="{List1.currentIndex}"/> + + <ListView id="List3" x="400" width="200" height="{parent.height}" model="{MyPetsModel}" + delegate="{PetDelegate}" + currentItemPositioning="SnapAuto" snapPosition="125" + currentIndex="{List1.currentIndex}"> + <children> + <!-- + Position a static highlight rather than a normal highlight so that + when the view is flicked, the highlight does not move. + By positioning the highlight at the same position as the snapPosition + the item under the highlight will always be the current item. + Note that we specify the 'children' property. This is because + the default property of a ListView is 'delegate'. + --> + <Rect y="{List3.yPosition+125}" width="200" height="50" color="#FFFF88" z="0"/> + </children> + </ListView> + +</Rect> diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml new file mode 100644 index 0000000..7d32532 --- /dev/null +++ b/examples/declarative/listview/recipes.qml @@ -0,0 +1,83 @@ +<!-- This example illustrates expanding a list item to show a more detailed view --> +<?qtfx namespacepath:=content ?> +<Rect id="page" width="400" height="280" color="black"> + <resources> + <!-- + Delegate for the recipes. This delegate has two modes: + 1. the list mode (default), which just shows the picture and title of the recipe. + 2. the details mode, which also shows the ingredients and method. + --> + <Component id="recipeDelegate"> + <Item id="wrapper" x="10" width="{List.width-20}"> + <!-- + Create a property to contain the visibility of the details. + We can bind multiple element's opacity to this one property, + rather than having a "SetProperty" line for each element we + want to fade. + --> + <properties><Property name="detailsOpacity" value="0" type="real"/></properties> + <!-- A simple rounded rectangle for the background --> + <Rect id="background" x="1" y="2" width="{parent.width-2}" height="{parent.height-4}" color="#FEFFEE" pen.color="#FFBE4F" radius="5"/> + <!-- + This mouse region covers the entire delegate. + When clicked it changes mode to 'Details'. If we are already + in Details mode, then no change will happen. + --> + <MouseRegion id="pageMouse" anchors.fill="{parent}" onClicked="wrapper.state = 'Details'"/> + <!-- + Layout the page. Picture, title and ingredients at the top, method at the + bottom. Note that elements that should not be visible in the list + mode have their opacity set to wrapper.detailsOpacity. + --> + <VerticalLayout id="topLayout" width="{parent.width-20}" margin="10" spacing="10"> + <HorizontalLayout spacing="10" height="{recipePic.height}"> + <Image id="recipePic" src="{picture}" width="48" height="48"/> + <VerticalLayout height="{recipePic.height}" spacing="5" width="{background.width-recipePic.width-20}"> + <Text id="name" text="{title}" font.bold="true" font.size="16"/> + <Text opacity="{wrapper.detailsOpacity}" text="Ingredients" font.size="12" font.bold="true"/> + <Text opacity="{wrapper.detailsOpacity}" text="{ingredients}" wrap="true" width="{parent.width}"/> + </VerticalLayout> + </HorizontalLayout> + <VerticalLayout id="details" opacity="{wrapper.detailsOpacity}"> + <Text text="Method" font.size="12" font.bold="true"/> + <Text text="{method}" wrap="true" width="{topLayout.width}"/> + </VerticalLayout> + </VerticalLayout> + <!-- A button to close the detailed view, i.e. set the state back to default (''). --> + <MediaButton anchors.right="{background.right}" anchors.rightMargin="5" y="10" opacity="{wrapper.detailsOpacity}" text="Close" onClicked="wrapper.state = ''"/> + <!-- Make the default height equal the hight of the picture, plus margin. --> + <height>68</height> + + <states> + <State name="Details"> + <SetProperty target="{background}" property="color" value="white" /> + <!-- Make the picture bigger --> + <SetProperties target="{recipePic}" width="128" height="128" /> + <!-- Make details visible --> + <SetProperties target="{wrapper}" detailsOpacity="1" x="0"/> + <!-- Make the detailed view fill the entire list area --> + <SetProperty target="{wrapper}" property="height" value="{List.height}"/> + <SetProperty target="{wrapper}" property="width" value="{List.width}"/> + <!-- Move the list so that this item is at the top. --> + <SetProperty target="{wrapper.ListView.view}" property="yPosition" value="{wrapper.y}"/> + <!-- Disallow flicking while we're in detailed view --> + <SetProperty target="{wrapper.ListView.view}" property="locked" value="1"/> + </State> + </states> + + <transitions> + <Transition> + <!-- Make the state changes smooth --> + <ParallelAnimation> + <ColorAnimation duration="500" /> + <NumericAnimation duration="300" properties="detailsOpacity,x,yPosition,height,width"/> + </ParallelAnimation> + </Transition> + </transitions> + </Item> + </Component> + </resources> + + <!-- The actual list --> + <ListView id="List" model="{Recipies}" anchors.fill="{parent}" clip="true" delegate="{recipeDelegate}"/> +</Rect> diff --git a/examples/declarative/minehunt/Description.qml b/examples/declarative/minehunt/Description.qml new file mode 100644 index 0000000..5bda5f8 --- /dev/null +++ b/examples/declarative/minehunt/Description.qml @@ -0,0 +1,10 @@ +<Item id="Page" height="{MyText.height + 20}" > + <properties><Property name="text" /></properties> + <MouseRegion anchors.fill="{parent}" drag.target="{Page}" drag.axis="xy" drag.xmin="0" drag.xmax="1000" drag.ymin="0" drag.ymax="1000"/> + <Rect radius="10" anchors.fill="{parent}" color="lightsteelblue" /> + <Item x="10" y="10" width="{parent.width - 20}" height="{parent.height - 20}"> + <Text id="MyText" text="{Page.text}" width="{parent.width}" clip="true" wrap="true"/> + </Item> + + <filter><Shadow xOffset="5" yOffset="5" /></filter> +</Item> diff --git a/examples/declarative/minehunt/Explosion.qml b/examples/declarative/minehunt/Explosion.qml new file mode 100644 index 0000000..aec685b --- /dev/null +++ b/examples/declarative/minehunt/Explosion.qml @@ -0,0 +1,6 @@ +<Item> + <properties> + <Property name="explode" type="Bool" value="false"/> + </properties> + <Particles width="38" height="21" lifeSpan="3600000" lifeSpanDeviation="0" src="pics/star.png" count="200" angle="270" angleDeviation="360" velocity="100" velocityDeviation="20" z="100" emitting="{explode}"/> +</Item> diff --git a/examples/declarative/minehunt/main.cpp b/examples/declarative/minehunt/main.cpp new file mode 100644 index 0000000..9db717b --- /dev/null +++ b/examples/declarative/minehunt/main.cpp @@ -0,0 +1,312 @@ +#include "qmlbindablevalue.h" +#include "qmlengine.h" +#include "qmlcontext.h" +#include "qml.h" +#include <qfxitem.h> +#include <qfxview.h> + +#include <QWidget> +#include <QApplication> +#include <QFile> +#include <QTime> +#include <QTimer> +#include <QVBoxLayout> +#include <QFileInfo> + +QString fileName = "minehunt.qml"; + +class Tile : public QObject +{ + Q_OBJECT +public: + Tile() : _hasFlag(false), _hasMine(false), _hint(-1), _flipped(false) {} + + Q_PROPERTY(bool hasFlag READ hasFlag WRITE setHasFlag NOTIFY hasFlagChanged); + bool hasFlag() const { return _hasFlag; } + + Q_PROPERTY(bool hasMine READ hasMine NOTIFY hasMineChanged); + bool hasMine() const { return _hasMine; } + + Q_PROPERTY(int hint READ hint NOTIFY hintChanged); + int hint() const { return _hint; } + + Q_PROPERTY(bool flipped READ flipped NOTIFY flippedChanged()); + bool flipped() const { return _flipped; } + + void setHasFlag(bool flag) {if(flag==_hasFlag) return; _hasFlag = flag; emit hasFlagChanged();} + void setHasMine(bool mine) {if(mine==_hasMine) return; _hasMine = mine; emit hasMineChanged();} + void setHint(int hint) { if(hint == _hint) return; _hint = hint; emit hintChanged(); } + void flip() { if (_flipped) return; _flipped = true; emit flippedChanged(); } + void unflip() { if(!_flipped) return; _flipped = false; emit flippedChanged(); } + +signals: + void flippedChanged(); + void hasFlagChanged(); + void hintChanged(); + void hasMineChanged(); + +private: + bool _hasFlag; + bool _hasMine; + int _hint; + bool _flipped; +}; + +QML_DECLARE_TYPE(Tile); +QML_DEFINE_TYPE(Tile,Tile); + +class MyWidget : public QWidget +{ +Q_OBJECT +public: + MyWidget(int = 370, int = 480, QWidget *parent=0, Qt::WindowFlags flags=0); + ~MyWidget(); + + Q_PROPERTY(QList<Tile *> *tiles READ tiles); + QList<Tile *> *tiles() { return &_tiles; } + + Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged); + bool isPlaying() {return playing;} + + Q_PROPERTY(bool hasWon READ hasWon NOTIFY hasWonChanged); + bool hasWon() {return won;} + + Q_PROPERTY(int numMines READ numMines NOTIFY numMinesChanged); + int numMines() const{return nMines;} + + Q_PROPERTY(int numFlags READ numFlags NOTIFY numFlagsChanged); + int numFlags() const{return nFlags;} + +public slots: + Q_INVOKABLE void flip(int row, int col); + Q_INVOKABLE void flag(int row, int col); + void setBoard(); + void reset(); + +signals: + void isPlayingChanged(); + void hasWonChanged(); + void numMinesChanged(); + void numFlagsChanged(); + +private: + bool onBoard( int r, int c ) const { return r >= 0 && r < numRows && c >= 0 && c < numCols; } + Tile *tile( int row, int col ) { return onBoard(row, col) ? _tiles[col+numRows*row] : 0; } + int getHint(int row, int col); + void setPlaying(bool b){if(b==playing) return; playing=b; emit isPlayingChanged();} + + QFxView *canvas; + + QList<Tile *> _tiles; + int numCols; + int numRows; + bool playing; + bool won; + int remaining; + int nMines; + int nFlags; +}; + +MyWidget::MyWidget(int width, int height, QWidget *parent, Qt::WindowFlags flags) +: QWidget(parent, flags), canvas(0), numCols(9), numRows(9), playing(true), won(false) +{ + setObjectName("mainWidget"); + srand(QTime(0,0,0).secsTo(QTime::currentTime())); + + //initialize array + for(int ii = 0; ii < numRows * numCols; ++ii) { + _tiles << new Tile; + } + + reset(); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setMargin(0); + setLayout(vbox); + + canvas = new QFxView(this); + canvas->setFixedSize(width, height); + vbox->addWidget(canvas); + + QFile file(fileName); + file.open(QFile::ReadOnly); + QString xml = file.readAll(); + canvas->setXml(xml, fileName); + + QmlContext *ctxt = canvas->rootContext(); + ctxt->activate(); + ctxt->addDefaultObject(this); + ctxt->deactivate(); + + canvas->execute(); +} + +MyWidget::~MyWidget() +{ +} + +void MyWidget::setBoard() +{ + foreach(Tile* t, _tiles){ + t->setHasMine(false); + t->setHint(-1); + } + //place mines + int mines = nMines; + remaining = numRows*numCols-mines; + while ( mines ) { + int col = int((double(rand()) / double(RAND_MAX)) * numCols); + int row = int((double(rand()) / double(RAND_MAX)) * numRows); + + Tile* t = tile( row, col ); + + if (t && !t->hasMine()) { + t->setHasMine( true ); + mines--; + } + } + + //set hints + for (int r = 0; r < numRows; r++) + for (int c = 0; c < numCols; c++) { + Tile* t = tile(r, c); + if (t && !t->hasMine()) { + int hint = getHint(r,c); + t->setHint(hint); + } + } + + setPlaying(true); +} + +void MyWidget::reset() +{ + foreach(Tile* t, _tiles){ + t->unflip(); + t->setHasFlag(false); + } + nMines = 12; + nFlags = 0; + setPlaying(false); + QTimer::singleShot(900,this, SLOT(setBoard())); +} + +int MyWidget::getHint(int row, int col) +{ + int hint = 0; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + Tile* t = tile(r, c); + if (t && t->hasMine()) + hint++; + } + return hint; +} + +void MyWidget::flip(int row, int col) +{ + if(!playing) + return; + + Tile *t = tile(row, col); + if (!t || t->hasFlag()) + return; + + if(t->flipped()){ + int flags = 0; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + Tile *nearT = tile(r, c); + if(!nearT || nearT == t) + continue; + if(nearT->hasFlag()) + flags++; + } + if(!t->hint() || t->hint() != flags) + return; + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + Tile *nearT = tile(r, c); + if (nearT && !nearT->flipped() && !nearT->hasFlag()) { + flip( r, c ); + } + } + return; + } + + t->flip(); + + if (t->hint() == 0) { + for (int c = col-1; c <= col+1; c++) + for (int r = row-1; r <= row+1; r++) { + Tile* t = tile(r, c); + if (t && !t->flipped()) { + flip( r, c ); + } + } + } + + if(t->hasMine()){ + for (int r = 0; r < numRows; r++)//Flip all other mines + for (int c = 0; c < numCols; c++) { + Tile* t = tile(r, c); + if (t && t->hasMine()) { + flip(r, c); + } + } + won = false; + hasWonChanged(); + setPlaying(false); + } + + remaining--; + if(!remaining){ + won = true; + hasWonChanged(); + setPlaying(false); + } +} + +void MyWidget::flag(int row, int col) +{ + Tile *t = tile(row, col); + if(!t) + return; + + t->setHasFlag(!t->hasFlag()); + nFlags += (t->hasFlag()?1:-1); + emit numFlagsChanged(); +} +///////////////////////////////////////////////////////// + +int main(int argc, char ** argv) +{ + QApplication app(argc, argv); + + bool frameless = false; + + int width = 370; + int height = 480; + + for (int i = 1; i < argc; ++i) { + QString arg = argv[i]; + if (arg == "-frameless") { + frameless = true; + } else if(arg == "-width" && i < (argc - 1)) { + ++i; + width = ::atoi(argv[i]); + } else if(arg == "-height" && i < (argc - 1)) { + ++i; + height = ::atoi(argv[i]); + } else if (arg[0] != '-') { + fileName = arg; + } + } + + MyWidget wid(width, height, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget); + wid.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/declarative/minehunt/minehunt.pro b/examples/declarative/minehunt/minehunt.pro new file mode 100644 index 0000000..08b6254 --- /dev/null +++ b/examples/declarative/minehunt/minehunt.pro @@ -0,0 +1,8 @@ +SOURCES = main.cpp + +QT += script declarative + +target.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minehunt.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt +INSTALLS += target sources diff --git a/examples/declarative/minehunt/minehunt.qml b/examples/declarative/minehunt/minehunt.qml new file mode 100644 index 0000000..9cde164 --- /dev/null +++ b/examples/declarative/minehunt/minehunt.qml @@ -0,0 +1,73 @@ +<Item id="field" width="370" height="480"> + <properties> + <Property name="clickx" type="Int" value="0"/> + <Property name="clicky" type="Int" value="0"/> + </properties> + <resources> + <Component id="tile"> + <Flipable id="flipable" width="40" height="40"> + <transform> + <Axis id="axis" xStart="20" xEnd="20" yStart="20" yEnd="0" /> + </transform> + <front> + <Image src="pics/cachepix-boxless.sci" width="40" height="40"> + <Image anchors.horizontalCenter="{parent.horizontalCenter}" + anchors.verticalCenter="{parent.verticalCenter}" + src="pics/flag.png" opacity="{modelData.hasFlag}"> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> + </Image> + </Image> + </front> + <back> + <Image src="pics/cachepix-black.sci" width="40" height="40"> + <Text anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" + text="{modelData.hint}" color="white" font.bold="true" + opacity="{modelData.hasMine == false && modelData.hint > 0}"/> + <Image anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" + src="pics/bomb.png" opacity="{modelData.hasMine}"/> + <Explosion anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" explode="{modelData.hasMine==true && modelData.flipped==true}"/> + </Image> + </back> + <states> + <State name="back" when="{modelData.flipped == true}"> + <SetProperty target="{axis}" property="rotation" value="180" /> + </State> + </states> + <transitions> + <Transition> + <SequentialAnimation> + <PauseAnimation duration="{var ret = Math.abs(flipable.parent.x-field.clickx) + Math.abs(flipable.parent.y-field.clicky); if (ret > 0) {if(modelData.hasMine==true && modelData.flipped==true){ret*3;}else{ret;}} else {0}}"/> + <NumericAnimation easing="easeInOutQuad" properties="rotation"/> + </SequentialAnimation> + </Transition> + </transitions> + <MouseRegion anchors.fill="{parent}" + onClicked="field.clickx = flipable.parent.x; field.clicky = flipable.parent.y; row = Math.floor(index/9); col = index - (Math.floor(index/9) * 9); if(mouseButton==undefined || mouseButton=='Right'){flag(row,col);}else{flip(row,col);}" /> + </Flipable> + </Component> + </resources> + <Image src="pics/No-Ones-Laughing-3.jpg" tile="true"/> + <Description text="Use the 'minehunt' executable to run this demo!" width="300" opacity="{tiles?0:1}" anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"/> + <Repeater dataSource="{tiles}" x="1" y="1"> + <Component> + <ComponentInstance component="{tile}" + x="{(index - (Math.floor(index/9) * 9)) * 41}" + y="{Math.floor(index/9) * 41}"/> + </Component> + </Repeater> + <Item id="gamedata" width="370" height="100" y="380"> + <Text color="white" font.size="18" x="20" y="20">In play:</Text> + <Image x="100" y="20" src="pics/bomb-color.png"/> + <Text x="100" y="60" color="white" text="{numMines}"/> + <Image x="140" y="20" src="pics/flag-color.png"/> + <Text x="140" y="60" color="white" text="{numFlags}"/> + + <Image x="240" y="0" src="{if(isPlaying==true){'pics/smile.png'}else{if(hasWon==true){'pics/glee.png'}else{'pics/frown.png'}}}"> + <MouseRegion anchors.fill="{parent}" onClicked="reset()"/> + </Image> + </Item> +</Item> diff --git a/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg b/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg Binary files differnew file mode 100644 index 0000000..445567f --- /dev/null +++ b/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg diff --git a/examples/declarative/minehunt/pics/bomb-color.png b/examples/declarative/minehunt/pics/bomb-color.png Binary files differnew file mode 100644 index 0000000..61ad0a9 --- /dev/null +++ b/examples/declarative/minehunt/pics/bomb-color.png diff --git a/examples/declarative/minehunt/pics/bomb.png b/examples/declarative/minehunt/pics/bomb.png Binary files differnew file mode 100644 index 0000000..a992575 --- /dev/null +++ b/examples/declarative/minehunt/pics/bomb.png diff --git a/examples/declarative/minehunt/pics/cachepix-black.png b/examples/declarative/minehunt/pics/cachepix-black.png Binary files differnew file mode 100644 index 0000000..53db3ae --- /dev/null +++ b/examples/declarative/minehunt/pics/cachepix-black.png diff --git a/examples/declarative/minehunt/pics/cachepix-black.sci b/examples/declarative/minehunt/pics/cachepix-black.sci new file mode 100644 index 0000000..21d5436 --- /dev/null +++ b/examples/declarative/minehunt/pics/cachepix-black.sci @@ -0,0 +1,5 @@ +gridLeft: 10 +gridTop: 10 +gridBottom: 10 +gridRight: 10 +imageFile: cachepix-black.png diff --git a/examples/declarative/minehunt/pics/cachepix-boxless.png b/examples/declarative/minehunt/pics/cachepix-boxless.png Binary files differnew file mode 100644 index 0000000..288e0e4 --- /dev/null +++ b/examples/declarative/minehunt/pics/cachepix-boxless.png diff --git a/examples/declarative/minehunt/pics/cachepix-boxless.sci b/examples/declarative/minehunt/pics/cachepix-boxless.sci new file mode 100644 index 0000000..d224fd9 --- /dev/null +++ b/examples/declarative/minehunt/pics/cachepix-boxless.sci @@ -0,0 +1,5 @@ +gridLeft: 10 +gridTop: 10 +gridBottom: 10 +gridRight: 10 +imageFile: cachepix-boxless.png diff --git a/examples/declarative/minehunt/pics/flag-color.png b/examples/declarative/minehunt/pics/flag-color.png Binary files differnew file mode 100644 index 0000000..aadad0f --- /dev/null +++ b/examples/declarative/minehunt/pics/flag-color.png diff --git a/examples/declarative/minehunt/pics/flag.png b/examples/declarative/minehunt/pics/flag.png Binary files differnew file mode 100644 index 0000000..39cde4d --- /dev/null +++ b/examples/declarative/minehunt/pics/flag.png diff --git a/examples/declarative/minehunt/pics/frown.png b/examples/declarative/minehunt/pics/frown.png Binary files differnew file mode 100644 index 0000000..52684b3 --- /dev/null +++ b/examples/declarative/minehunt/pics/frown.png diff --git a/examples/declarative/minehunt/pics/glee.png b/examples/declarative/minehunt/pics/glee.png Binary files differnew file mode 100644 index 0000000..59ea583 --- /dev/null +++ b/examples/declarative/minehunt/pics/glee.png diff --git a/examples/declarative/minehunt/pics/smile.png b/examples/declarative/minehunt/pics/smile.png Binary files differnew file mode 100644 index 0000000..ccd52cd --- /dev/null +++ b/examples/declarative/minehunt/pics/smile.png diff --git a/examples/declarative/minehunt/pics/star.png b/examples/declarative/minehunt/pics/star.png Binary files differnew file mode 100644 index 0000000..3772359 --- /dev/null +++ b/examples/declarative/minehunt/pics/star.png diff --git a/examples/declarative/mouseregion/mouse.qml b/examples/declarative/mouseregion/mouse.qml new file mode 100644 index 0000000..f0f22ac --- /dev/null +++ b/examples/declarative/mouseregion/mouse.qml @@ -0,0 +1,24 @@ +<Rect color="white" width="200" height="200"> + <Rect width="50" height="50" color="red"> + <Text text="Click" anchors.centeredIn="{parent}"/> + <MouseRegion onPressed="print('press (x: ' + x + ' y: ' + y + ')')" + onReleased="print('release (x: ' + x + ' y: ' + y + ' isClick: ' + isClick + ' followsPressAndHold: ' + followsPressAndHold + ')')" + onClicked="print('click (x: ' + x + ' y: ' + y + ' followsPressAndHold: ' + followsPressAndHold + ')')" + onDoubleClicked="print('double click (x: ' + x + ' y: ' + y + ')')" + onPressAndHold="print('press and hold')" + onExitedWhilePressed="print('exiting while pressed')" + onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/> + </Rect> + <Rect y="100" width="50" height="50" color="blue"> + <Text text="Drag" anchors.centeredIn="{parent}"/> + <MouseRegion drag.target="{parent}" + drag.axis="x" drag.xmin="0" drag.xmax="150" + onPressed="print('press')" + onReleased="print('release (isClick: ' + isClick + ') (followsPressAndHold: ' + followsPressAndHold + ')')" + onClicked="print('click' + '(followsPressAndHold: ' + followsPressAndHold + ')')" + onDoubleClicked="print('double click')" + onPressAndHold="print('press and hold')" + onExitedWhilePressed="print('exiting while pressed')" + onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/> + </Rect> +</Rect> diff --git a/examples/declarative/namespaces/BlueStuff/Rect.qml b/examples/declarative/namespaces/BlueStuff/Rect.qml new file mode 100644 index 0000000..94e066c --- /dev/null +++ b/examples/declarative/namespaces/BlueStuff/Rect.qml @@ -0,0 +1 @@ +<Rect color="blue"/> diff --git a/examples/declarative/namespaces/Local.qml b/examples/declarative/namespaces/Local.qml new file mode 100644 index 0000000..5fb2aef --- /dev/null +++ b/examples/declarative/namespaces/Local.qml @@ -0,0 +1 @@ +<Text>This is a local component</Text> diff --git a/examples/declarative/namespaces/components.qml b/examples/declarative/namespaces/components.qml new file mode 100644 index 0000000..ea5e2d9 --- /dev/null +++ b/examples/declarative/namespaces/components.qml @@ -0,0 +1,17 @@ +<Item id="Root"> + <properties> + <Property name="period" value="1000"/> + <Property name="color" value="green"/> + </properties> + + <Component id="SpinSquare"> + <Item> + <Rect color="{Root.color}" width="{Root.width}" height="{width}" x="{-width/2}" y="{-height/2}"/> + <rotation> + <NumericAnimation from="0" to="360" repeat="true" running="true" duration="{Root.period}"/> + </rotation> + </Item> + </Component> + + <ComponentInstance component="{SpinSquare}" x="{Root.width/2}" y="{Root.height/2}"/> +</Item> diff --git a/examples/declarative/namespaces/lib/Chronos/Clock.qml b/examples/declarative/namespaces/lib/Chronos/Clock.qml new file mode 100644 index 0000000..088a45c --- /dev/null +++ b/examples/declarative/namespaces/lib/Chronos/Clock.qml @@ -0,0 +1,15 @@ +<?qtfx namespacepath:http://nokia.com/qml/Chronos=. ?> + +<Image id="clock" src="pics/clockface.png" xmlns:This="http://nokia.com/qml/Chronos"> + <properties> + <Property name="hours" value="0"/> + <Property name="minutes" value="0"/> + <Property name="seconds" value="0"/> + </properties> + <DateTimeFormatter id="format" time="{clock.time}"/> + <Item x="{clock.width/2}" y="{clock.height/2}"> + <This:Hand id="hour" length="{clock.height/4}" rotation="{clock.hours*30+clock.minutes/2+clock.seconds/120}"/> + <This:Hand id="minute" length="{clock.height/3}" thickness="3" rotation="{clock.minutes*6+clock.seconds/10}"/> + <This:Hand id="second" length="{clock.height/2.5}" thickness="1" rotation="{clock.seconds*6}"/> + </Item> +</Image> diff --git a/examples/declarative/namespaces/lib/Chronos/Hand.qml b/examples/declarative/namespaces/lib/Chronos/Hand.qml new file mode 100644 index 0000000..3662e74 --- /dev/null +++ b/examples/declarative/namespaces/lib/Chronos/Hand.qml @@ -0,0 +1,9 @@ +<Item id="Hand"> + <properties> + <Property name="length" value="100"/> + <Property name="thickness" value="0"/> + </properties> + <Item rotation="-90"> + <Rect width="{length}" height="{thickness==0 ? length/8 : thickness}" y="{-height/2}"/> + </Item> +</Item> diff --git a/examples/declarative/namespaces/lib/Chronos/pics/clockface.png b/examples/declarative/namespaces/lib/Chronos/pics/clockface.png Binary files differnew file mode 100644 index 0000000..a885950 --- /dev/null +++ b/examples/declarative/namespaces/lib/Chronos/pics/clockface.png diff --git a/examples/declarative/namespaces/lib/Path/PathLabel.qml b/examples/declarative/namespaces/lib/Path/PathLabel.qml new file mode 100644 index 0000000..c4b08b0 --- /dev/null +++ b/examples/declarative/namespaces/lib/Path/PathLabel.qml @@ -0,0 +1 @@ +<Text color="green"/> diff --git a/examples/declarative/namespaces/lib/RedStuff/Rect.qml b/examples/declarative/namespaces/lib/RedStuff/Rect.qml new file mode 100644 index 0000000..3429b09 --- /dev/null +++ b/examples/declarative/namespaces/lib/RedStuff/Rect.qml @@ -0,0 +1 @@ +<Rect color="red"/> diff --git a/examples/declarative/namespaces/lib/Wrong/Wrong.qml b/examples/declarative/namespaces/lib/Wrong/Wrong.qml new file mode 100644 index 0000000..3af55f6 --- /dev/null +++ b/examples/declarative/namespaces/lib/Wrong/Wrong.qml @@ -0,0 +1,3 @@ +<Rect> + <Local/> <!-- not allowed - not in this component! --> +</Rect> diff --git a/examples/declarative/namespaces/library.qml b/examples/declarative/namespaces/library.qml new file mode 100644 index 0000000..ae10ed8 --- /dev/null +++ b/examples/declarative/namespaces/library.qml @@ -0,0 +1,12 @@ +<?qtfx namespacepath:http://nokia.com/qml=lib ?> + +<Rect id="obj" width="200" height="200" xmlns:Chronos="http://nokia.com/qml/Chronos"> + <properties> + <Property name="time_sec"/> + </properties> + <time_sec> <!-- simple animation, not bound to the real time --> + <NumericAnimation from="0" to="43200" duration="43200000" running="true" repeat="true"/> + </time_sec> + <Chronos:Clock x="10" y="10" width="{parent.width-20}" height="{parent.height-20}" + hours="{Math.floor(time_sec/3600)}" minutes="{Math.floor(time_sec/60)%60}" seconds="{time_sec%60}"/> +</Rect> diff --git a/examples/declarative/namespaces/path.qml b/examples/declarative/namespaces/path.qml new file mode 100644 index 0000000..795447b --- /dev/null +++ b/examples/declarative/namespaces/path.qml @@ -0,0 +1,18 @@ +<!-- Empty Namespaces paths allow unqualified Types to be found + in other locations. For file URLs, multiple paths can be + given, forming a file search path. --> + +<?qtfx namespacepath:=lib/Chronos ?> <!-- Clock will be found here --> +<?qtfx namespacepath:=lib/Path ?> <!-- PathLabel will be found here --> + +<Rect id="obj" width="200" height="200"> + <properties> + <Property name="time_sec"/> + </properties> + <time_sec> <!-- simple animation, not bound to the real time --> + <NumericAnimation from="0" to="43200" duration="43200000" running="true" repeat="true"/> + </time_sec> + <Clock x="10" y="10" width="{parent.width-20}" height="{parent.height-20}" + hours="{Math.floor(time_sec/3600)}" minutes="{Math.floor(time_sec/60)%60}" seconds="{time_sec%60}"/> + <PathLabel text="This is a clock"/> +</Rect> diff --git a/examples/declarative/namespaces/simple.qml b/examples/declarative/namespaces/simple.qml new file mode 100644 index 0000000..16d9815 --- /dev/null +++ b/examples/declarative/namespaces/simple.qml @@ -0,0 +1,5 @@ +<?qtfx namespacepath:http://nokia.com/qml=lib ?> +<Rect id="obj" width="100" height="100" xmlns:bs="BlueStuff" xmlns:rs="http://nokia.com/qml/RedStuff"> + <bs:Rect x="20" y="20" width="50" height="50"/> + <rs:Rect x="30" y="30" width="50" height="50"/> +</Rect> diff --git a/examples/declarative/namespaces/wrong1.qml b/examples/declarative/namespaces/wrong1.qml new file mode 100644 index 0000000..721c45a --- /dev/null +++ b/examples/declarative/namespaces/wrong1.qml @@ -0,0 +1,4 @@ +<?qtfx namespacepath:http://nokia.com/qml=lib ?> +<Rect id="obj" width="100" height="100" xmlns:w="http://nokia.com/qml/Wrong" color="white"> + <w:Wrong/> +</Rect> diff --git a/examples/declarative/scrollbar/ScrollBar.qml b/examples/declarative/scrollbar/ScrollBar.qml new file mode 100644 index 0000000..470a170 --- /dev/null +++ b/examples/declarative/scrollbar/ScrollBar.qml @@ -0,0 +1,26 @@ +<Item id="ScrollBar"> + <!-- + The properties that define the scrollbar's state. + position and pageSize are in the range 0.0 - 1.0. They are relative to the + height of the page, i.e. a pageSize of 0.5 means that you can see 50% + of the height of the view. + orientation can be either 'Vertical' or 'Horizontal' + --> + <properties> + <Property name="position"/> + <Property name="pageSize"/> + <Property name="orientation" value="Vertical"/> + </properties> + + <!-- A light, semi-transparent background --> + <Rect id="Background" radius="{orientation == 'Vertical' ? (width/2) : (height/2)}" color="white" opacity="0.3" anchors.fill="{parent}"/> + + <!-- Size the bar to the required size, depending upon the orientation. --> + <Rect opacity="0.6" color="black" + radius="{orientation == 'Vertical' ? (width/2) : (height/2)}" + x="{orientation == 'Vertical' ? 2 : (ScrollBar.position * (ScrollBar.width-4) + 2)}" + y="{orientation == 'Vertical' ? (ScrollBar.position * (ScrollBar.height-4) + 2) : 2}" + width="{orientation == 'Vertical' ? (parent.width-4) : (ScrollBar.pageSize * (ScrollBar.width-4))}" + height="{orientation == 'Vertical' ? (ScrollBar.pageSize * (ScrollBar.height-4)) : (parent.height-4)}" + /> +</Item> diff --git a/examples/declarative/scrollbar/display.qml b/examples/declarative/scrollbar/display.qml new file mode 100644 index 0000000..697b68a --- /dev/null +++ b/examples/declarative/scrollbar/display.qml @@ -0,0 +1,28 @@ +<Rect width="640" height="480"> + + <!-- Create a flickable to view a large image. --> + <Flickable id="View" anchors.fill="{parent}"> + <Image id="Picture" src="pics/niagara_falls.jpg"/> + <viewportWidth>{Picture.width}</viewportWidth> + <viewportHeight>{Picture.height}</viewportHeight> + + <!-- Only show the scrollbars when the view is moving. --> + <states> + <State name="ShowBars" when="{View.moving}"> + <SetProperty target="{SBV}" property="opacity" value="1" /> + <SetProperty target="{SBH}" property="opacity" value="1" /> + </State> + </states> + <transitions> + <Transition fromState="*" toState="*"> + <NumericAnimation properties="opacity" duration="400"/> + </Transition> + </transitions> + + </Flickable> + + <!-- Attach scrollbars to the right and bottom edges of the view. --> + <ScrollBar id="SBV" opacity="0" orientation="Vertical" position="{View.pageYPosition}" pageSize="{View.pageHeight}" width="12" height="{View.height-12}" anchors.right="{View.right}"/> + <ScrollBar id="SBH" opacity="0" orientation="Horizontal" position="{View.pageXPosition}" pageSize="{View.pageWidth}" height="12" width="{View.width-12}" anchors.bottom="{View.bottom}"/> + +</Rect> diff --git a/examples/declarative/scrollbar/pics/niagara_falls.jpg b/examples/declarative/scrollbar/pics/niagara_falls.jpg Binary files differnew file mode 100644 index 0000000..618d808 --- /dev/null +++ b/examples/declarative/scrollbar/pics/niagara_falls.jpg diff --git a/examples/declarative/slideswitch/Switch.qml b/examples/declarative/slideswitch/Switch.qml new file mode 100644 index 0000000..90e6e64 --- /dev/null +++ b/examples/declarative/slideswitch/Switch.qml @@ -0,0 +1,52 @@ +<Item id="Switch" width="{Groove.width}" height="{Groove.height}"> + <properties><Property name="on"/></properties> + <Script> + function toggle() { + if(Switch.state == "On") + Switch.state = "Off"; + else + Switch.state = "On"; + } + function dorelease() { + print(Knob.x); + if(Knob.x == 1) { + if(Switch.state == "Off") + return; + } + + if(Knob.x == 78) { + if(Switch.state == "On") + return; + } + + toggle(); + } + </Script> + <Image id="Groove" src="background.svg"/> + <MouseRegion anchors.fill="{Groove}" onClicked="toggle()"/> + <Image id="Knob" src="knob.svg" x="1" y="2"/> + <MouseRegion anchors.fill="{Knob}" + onClicked="toggle()" + onReleased="if (!isClick) dorelease()" + drag.target="{Knob}" + drag.axis="x" + drag.xmin="1" + drag.xmax="78"/> + + <states> + <State name="On"> + <SetProperty target="{Knob}" property="x" value="78" /> + <SetProperty target="{Switch}" property="on" value="true" /> + </State> + <State name="Off"> + <SetProperty target="{Knob}" property="x" value="1" /> + <SetProperty target="{Switch}" property="on" value="false" /> + </State> + </states> + + <transitions> + <Transition> + <NumericAnimation properties="x" easing="easeInOutQuad" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/slideswitch/background.svg b/examples/declarative/slideswitch/background.svg new file mode 100644 index 0000000..f920d3e --- /dev/null +++ b/examples/declarative/slideswitch/background.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> +]> +<svg version="1.1" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + x="0px" y="0px" width="130px" height="56px" viewBox="0 0 130 56" enable-background="new 0 0 130 56" xml:space="preserve"> +<defs> +</defs> +<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-37.5005" y1="-66" x2="-37.5005" y2="-121.9985" gradientTransform="matrix(1 0 0 -1 102.5 -66)"> + <stop offset="0.0056" style="stop-color:#000000"/> + <stop offset="1" style="stop-color:#EAECEF"/> +</linearGradient> +<path fill="url(#SVGID_1_)" d="M101.998,55.998H28c-15.439,0-28-12.562-28-28C0,12.56,12.561,0,28,0h73.998 + c15.439,0,28,12.559,28,27.998C129.998,43.438,117.438,55.998,101.998,55.998L101.998,55.998z"/> +<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-5.5" y1="-132.1338" x2="-69.5002" y2="-55.8613" gradientTransform="matrix(1 0 0 -1 102.5 -66)"> + <stop offset="0.0056" style="stop-color:#000000"/> + <stop offset="1" style="stop-color:#828385"/> +</linearGradient> +<path fill="url(#SVGID_2_)" d="M127.999,27.998c0,14.359-11.642,26-26,26h-74c-14.359,0-26-11.641-26-26l0,0 + c0-14.359,11.641-26,26-26h74C116.357,1.998,127.999,13.639,127.999,27.998L127.999,27.998z"/> +</svg> diff --git a/examples/declarative/slideswitch/display.qml b/examples/declarative/slideswitch/display.qml new file mode 100644 index 0000000..b62422c --- /dev/null +++ b/examples/declarative/slideswitch/display.qml @@ -0,0 +1,3 @@ +<Rect color="white" width="150" height="150"> + <Switch anchors.centeredIn="{parent}"/> +</Rect> diff --git a/examples/declarative/slideswitch/knob.svg b/examples/declarative/slideswitch/knob.svg new file mode 100644 index 0000000..fb69337 --- /dev/null +++ b/examples/declarative/slideswitch/knob.svg @@ -0,0 +1,867 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + 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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + x="0px" + y="0px" + width="52px" + height="52px" + viewBox="0 0 52 52" + enable-background="new 0 0 52 52" + xml:space="preserve" + id="svg3883" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docname="knob_on.svg" + sodipodi:docbase="/local/axel/embeddedwidgets/embeddedstories/skins/svgslideswitch/MetallicBrush"><metadata + id="metadata4200"><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="640" + inkscape:window-width="937" + 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" + inkscape:zoom="8.3653846" + inkscape:cx="26.000002" + inkscape:cy="26" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:current-layer="svg3883" /> +<defs + id="defs3885"> +</defs> +<linearGradient + id="SVGID_1_" + gradientUnits="userSpaceOnUse" + x1="-59.7866" + y1="-115.917" + x2="-93.2123" + y2="-76.0818" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#000000" + id="stop3888" /> + <stop + offset="1" + style="stop-color:#EAECEF" + id="stop3890" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="26" + id="circle3892" + style="fill:url(#SVGID_1_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="26" + sodipodi:ry="26" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_2_" + gradientUnits="userSpaceOnUse" + x1="-100.5" + y1="-96" + x2="-52.5" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop3895" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop3897" /> + <stop + offset="0.6043" + style="stop-color:#E7EAED" + id="stop3899" /> + <stop + offset="0.6751" + style="stop-color:#DEE4E7" + id="stop3901" /> + <stop + offset="0.7358" + style="stop-color:#CFD9DD" + id="stop3903" /> + <stop + offset="0.791" + style="stop-color:#B9CACF" + id="stop3905" /> + <stop + offset="0.8425" + style="stop-color:#9EB6BD" + id="stop3907" /> + <stop + offset="0.891" + style="stop-color:#7B9EA7" + id="stop3909" /> + <stop + offset="0.9374" + style="stop-color:#53828C" + id="stop3911" /> + <stop + offset="0.9809" + style="stop-color:#25626E" + id="stop3913" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop3915" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="24" + id="circle3917" + style="fill:url(#SVGID_2_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="24" + sodipodi:ry="24" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_3_" + gradientUnits="userSpaceOnUse" + x1="-98.6328" + y1="-96" + x2="-54.3672" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop3920" /> + <stop + offset="0.073" + style="stop-color:#8FAECB" + id="stop3922" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop3924" /> + <stop + offset="0.5902" + style="stop-color:#E7E9ED" + id="stop3926" /> + <stop + offset="0.618" + style="stop-color:#E4E7EB" + id="stop3928" /> + <stop + offset="0.6697" + style="stop-color:#E0E4E9" + id="stop3930" /> + <stop + offset="0.7211" + style="stop-color:#D4DCE1" + id="stop3932" /> + <stop + offset="0.7722" + style="stop-color:#C0CFD5" + id="stop3934" /> + <stop + offset="0.809" + style="stop-color:#ADC2C9" + id="stop3936" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop3938" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="22.132999" + id="circle3940" + style="fill:url(#SVGID_3_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="22.132999" + sodipodi:ry="22.132999" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_4_" + gradientUnits="userSpaceOnUse" + x1="-96.7671" + y1="-96" + x2="-56.2324" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop3943" /> + <stop + offset="0.073" + style="stop-color:#86A7C4" + id="stop3945" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop3947" /> + <stop + offset="0.577" + style="stop-color:#E7EAED" + id="stop3949" /> + <stop + offset="0.618" + style="stop-color:#E1E6EA" + id="stop3951" /> + <stop + offset="0.6697" + style="stop-color:#DDE3E8" + id="stop3953" /> + <stop + offset="0.7211" + style="stop-color:#D1DBE1" + id="stop3955" /> + <stop + offset="0.7722" + style="stop-color:#BDCDD5" + id="stop3957" /> + <stop + offset="0.809" + style="stop-color:#AAC0CA" + id="stop3959" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop3961" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="20.267" + id="circle3963" + style="fill:url(#SVGID_4_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="20.267" + sodipodi:ry="20.267" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_5_" + gradientUnits="userSpaceOnUse" + x1="-94.8999" + y1="-96" + x2="-58.0996" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop3966" /> + <stop + offset="0.073" + style="stop-color:#7E9FBC" + id="stop3968" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop3970" /> + <stop + offset="0.5709" + style="stop-color:#E6E9ED" + id="stop3972" /> + <stop + offset="0.618" + style="stop-color:#DFE4E9" + id="stop3974" /> + <stop + offset="0.6687" + style="stop-color:#DBE1E7" + id="stop3976" /> + <stop + offset="0.7193" + style="stop-color:#CFD9E0" + id="stop3978" /> + <stop + offset="0.7695" + style="stop-color:#BBCCD6" + id="stop3980" /> + <stop + offset="0.809" + style="stop-color:#A6BECA" + id="stop3982" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop3984" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="18.4" + id="circle3986" + style="fill:url(#SVGID_5_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="18.4" + sodipodi:ry="18.4" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_6_" + gradientUnits="userSpaceOnUse" + x1="-93.0332" + y1="-96" + x2="-59.9668" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop3989" /> + <stop + offset="0.073" + style="stop-color:#7697B4" + id="stop3991" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop3993" /> + <stop + offset="0.5636" + style="stop-color:#E6E9ED" + id="stop3995" /> + <stop + offset="0.618" + style="stop-color:#DCE2E8" + id="stop3997" /> + <stop + offset="0.6687" + style="stop-color:#D8DFE6" + id="stop3999" /> + <stop + offset="0.7193" + style="stop-color:#CCD7E0" + id="stop4001" /> + <stop + offset="0.7695" + style="stop-color:#B8CAD5" + id="stop4003" /> + <stop + offset="0.809" + style="stop-color:#A3BCCA" + id="stop4005" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4007" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="16.533001" + id="circle4009" + style="fill:url(#SVGID_6_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="16.533001" + sodipodi:ry="16.533001" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_7_" + gradientUnits="userSpaceOnUse" + x1="-91.167" + y1="-96" + x2="-61.833" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4012" /> + <stop + offset="0.073" + style="stop-color:#6D8FAD" + id="stop4014" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4016" /> + <stop + offset="0.5605" + style="stop-color:#E5E8EC" + id="stop4018" /> + <stop + offset="0.618" + style="stop-color:#DAE1E7" + id="stop4020" /> + <stop + offset="0.6679" + style="stop-color:#D6DEE5" + id="stop4022" /> + <stop + offset="0.7175" + style="stop-color:#CAD6DF" + id="stop4024" /> + <stop + offset="0.7669" + style="stop-color:#B6C9D6" + id="stop4026" /> + <stop + offset="0.809" + style="stop-color:#9FBACB" + id="stop4028" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4030" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="14.667" + id="circle4032" + style="fill:url(#SVGID_7_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="14.667" + sodipodi:ry="14.667" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_8_" + gradientUnits="userSpaceOnUse" + x1="-89.2998" + y1="-96" + x2="-63.7002" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4035" /> + <stop + offset="0.073" + style="stop-color:#6587A5" + id="stop4037" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4039" /> + <stop + offset="0.5588" + style="stop-color:#E4E8EC" + id="stop4041" /> + <stop + offset="0.618" + style="stop-color:#D8DFE7" + id="stop4043" /> + <stop + offset="0.6675" + style="stop-color:#D4DCE5" + id="stop4045" /> + <stop + offset="0.7167" + style="stop-color:#C8D5E0" + id="stop4047" /> + <stop + offset="0.7657" + style="stop-color:#B4C8D6" + id="stop4049" /> + <stop + offset="0.809" + style="stop-color:#9CB8CB" + id="stop4051" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4053" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="12.8" + id="circle4055" + style="fill:url(#SVGID_8_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="12.8" + sodipodi:ry="12.8" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_9_" + gradientUnits="userSpaceOnUse" + x1="-87.4331" + y1="-96" + x2="-65.5664" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4058" /> + <stop + offset="0.073" + style="stop-color:#5D809D" + id="stop4060" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4062" /> + <stop + offset="0.5567" + style="stop-color:#E3E7EC" + id="stop4064" /> + <stop + offset="0.618" + style="stop-color:#D5DDE6" + id="stop4066" /> + <stop + offset="0.6671" + style="stop-color:#D1DAE4" + id="stop4068" /> + <stop + offset="0.7159" + style="stop-color:#C5D3DF" + id="stop4070" /> + <stop + offset="0.7645" + style="stop-color:#B1C6D6" + id="stop4072" /> + <stop + offset="0.809" + style="stop-color:#98B5CB" + id="stop4074" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4076" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="10.933" + id="circle4078" + style="fill:url(#SVGID_9_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="10.933" + sodipodi:ry="10.933" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_10_" + gradientUnits="userSpaceOnUse" + x1="-85.5659" + y1="-96" + x2="-67.4336" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4081" /> + <stop + offset="0.073" + style="stop-color:#547896" + id="stop4083" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4085" /> + <stop + offset="0.5588" + style="stop-color:#E1E6EB" + id="stop4087" /> + <stop + offset="0.618" + style="stop-color:#D3DCE5" + id="stop4089" /> + <stop + offset="0.6663" + style="stop-color:#CFD9E3" + id="stop4091" /> + <stop + offset="0.7143" + style="stop-color:#C3D2DF" + id="stop4093" /> + <stop + offset="0.7621" + style="stop-color:#AFC5D7" + id="stop4095" /> + <stop + offset="0.809" + style="stop-color:#94B3CC" + id="stop4097" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4099" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="9.066" + id="circle4101" + style="fill:url(#SVGID_10_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="9.066" + sodipodi:ry="9.066" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_11_" + gradientUnits="userSpaceOnUse" + x1="-83.7002" + y1="-96" + x2="-69.2998" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4104" /> + <stop + offset="0.073" + style="stop-color:#4C708E" + id="stop4106" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4108" /> + <stop + offset="0.5625" + style="stop-color:#DEE4EA" + id="stop4110" /> + <stop + offset="0.618" + style="stop-color:#D0DAE4" + id="stop4112" /> + <stop + offset="0.6663" + style="stop-color:#CCD7E2" + id="stop4114" /> + <stop + offset="0.7143" + style="stop-color:#C0D0DE" + id="stop4116" /> + <stop + offset="0.7621" + style="stop-color:#ACC3D6" + id="stop4118" /> + <stop + offset="0.809" + style="stop-color:#91B1CC" + id="stop4120" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4122" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="7.1999998" + id="circle4124" + style="fill:url(#SVGID_11_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="7.1999998" + sodipodi:ry="7.1999998" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_12_" + gradientUnits="userSpaceOnUse" + x1="-81.833" + y1="-96" + x2="-71.167" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4127" /> + <stop + offset="0.073" + style="stop-color:#446986" + id="stop4129" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4131" /> + <stop + offset="0.5757" + style="stop-color:#D9E0E8" + id="stop4133" /> + <stop + offset="0.618" + style="stop-color:#CED8E3" + id="stop4135" /> + <stop + offset="0.6655" + style="stop-color:#CAD5E2" + id="stop4137" /> + <stop + offset="0.7129" + style="stop-color:#BECEDD" + id="stop4139" /> + <stop + offset="0.7601" + style="stop-color:#AAC1D6" + id="stop4141" /> + <stop + offset="0.807" + style="stop-color:#8EB0CC" + id="stop4143" /> + <stop + offset="0.809" + style="stop-color:#8DAFCC" + id="stop4145" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4147" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="5.3330002" + id="circle4149" + style="fill:url(#SVGID_12_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="5.3330002" + sodipodi:ry="5.3330002" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_13_" + gradientUnits="userSpaceOnUse" + x1="-79.9658" + y1="-96" + x2="-73.0342" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4152" /> + <stop + offset="0.073" + style="stop-color:#3B617F" + id="stop4154" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4156" /> + <stop + offset="0.6087" + style="stop-color:#CED9E3" + id="stop4158" /> + <stop + offset="0.618" + style="stop-color:#CBD7E2" + id="stop4160" /> + <stop + offset="0.6655" + style="stop-color:#C7D4E1" + id="stop4162" /> + <stop + offset="0.7129" + style="stop-color:#BBCDDD" + id="stop4164" /> + <stop + offset="0.7601" + style="stop-color:#A7C0D6" + id="stop4166" /> + <stop + offset="0.807" + style="stop-color:#8BAECD" + id="stop4168" /> + <stop + offset="0.809" + style="stop-color:#8AADCD" + id="stop4170" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4172" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="3.4660001" + id="circle4174" + style="fill:url(#SVGID_13_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="3.4660001" + sodipodi:ry="3.4660001" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +<linearGradient + id="SVGID_14_" + gradientUnits="userSpaceOnUse" + x1="-78.1001" + y1="-96" + x2="-74.9004" + y2="-96" + gradientTransform="matrix(1,0,0,-1,102.5,-70)"> + <stop + offset="0.0056" + style="stop-color:#8AADCE" + id="stop4177" /> + <stop + offset="0.073" + style="stop-color:#335977" + id="stop4179" /> + <stop + offset="0.5" + style="stop-color:#EAECEF" + id="stop4181" /> + <stop + offset="0.618" + style="stop-color:#C9D5E1" + id="stop4183" /> + <stop + offset="0.6648" + style="stop-color:#C5D3E0" + id="stop4185" /> + <stop + offset="0.7114" + style="stop-color:#B9CBDC" + id="stop4187" /> + <stop + offset="0.758" + style="stop-color:#A5BFD6" + id="stop4189" /> + <stop + offset="0.8042" + style="stop-color:#89ADCE" + id="stop4191" /> + <stop + offset="0.809" + style="stop-color:#86ABCD" + id="stop4193" /> + <stop + offset="1" + style="stop-color:#0E525F" + id="stop4195" /> +</linearGradient> +<circle + cx="26" + cy="26" + r="1.6" + id="circle4197" + style="fill:url(#SVGID_14_)" + sodipodi:cx="26" + sodipodi:cy="26" + sodipodi:rx="1.6" + sodipodi:ry="1.6" + transform="matrix(0.923077,0,0,0.923077,2,1.999996)" /> +</svg>
\ No newline at end of file diff --git a/examples/declarative/states/states.qml b/examples/declarative/states/states.qml new file mode 100644 index 0000000..e540d25 --- /dev/null +++ b/examples/declarative/states/states.qml @@ -0,0 +1,40 @@ +<Rect id="Page" width="300" height="300" color="white"> + + <!-- A target region. Clicking in here sets the state to '' - the default state --> + <Rect width="50" height="50" x="0" y="0" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state=''"/> + </Rect> + + <!-- Another target region. Clicking in here sets the state to 'Position1' --> + <Rect width="50" height="50" x="150" y="50" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position1'"/> + </Rect> + + <!-- Another target region. Clicking in here sets the state to 'Position2' --> + <Rect width="50" height="50" x="0" y="200" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position2'"/> + </Rect> + + <!-- Rect which will be moved when my state changes --> + <Rect id="myrect" width="50" height="50" color="red"/> + + <states> + + <!-- In state 'Position1', change the 'myrect' item x, y to 150, 50. --> + <State name="Position1"> + <SetProperty target="{myrect}" property="x" value="150"/> + <SetProperty target="{myrect}" property="y" value="50"/> + </State> + + <!-- + In state 'Position2', change y to 100. We do not specify 'x' here - + it will therefore be restored to its default value of 0, if it + had been changed. + --> + <State name="Position2"> + <SetProperty target="{myrect}" property="y" value="200"/> + </State> + + </states> + +</Rect> diff --git a/examples/declarative/states/transitions.qml b/examples/declarative/states/transitions.qml new file mode 100644 index 0000000..c3f3515 --- /dev/null +++ b/examples/declarative/states/transitions.qml @@ -0,0 +1,68 @@ +<Rect id="Page" width="300" height="300" color="white"> + + <!-- A target region. Clicking in here sets the state to '' - the default state --> + <Rect width="50" height="50" x="0" y="0" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state=''"/> + </Rect> + + <!-- Another target region. Clicking in here sets the state to 'Position1' --> + <Rect width="50" height="50" x="150" y="50" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position1'"/> + </Rect> + + <!-- Another target region. Clicking in here sets the state to 'Position2' --> + <Rect width="50" height="50" x="0" y="200" color="transparent" pen.color="black"> + <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position2'"/> + </Rect> + + <!-- Rect which will be moved when my state changes --> + <Rect id="myrect" width="50" height="50" color="red"/> + + <states> + + <!-- In state 'Position1', change the 'myrect' item x, y to 150, 50. --> + <State name="Position1"> + <SetProperty target="{myrect}" property="x" value="150"/> + <SetProperty target="{myrect}" property="y" value="50"/> + </State> + + <!-- + In state 'Position2', change y to 100. We do not specify 'x' here - + it will therefore be restored to its default value of 0, if it + had been changed. + --> + <State name="Position2"> + <SetProperty target="{myrect}" property="y" value="200"/> + </State> + + </states> + + <!-- transitions define how the properties change. --> + <transitions> + + <!-- + When transitioning to 'Position1' move x,y over a duration of 1 second, + with easeOutBounce easing function. + --> + <Transition fromState="*" toState="Position1"> + <NumericAnimation properties="x,y" easing="easeOutBounce" duration="1000" /> + </Transition> + + <!-- + When transitioning to 'Position2' move x,y over a duration of 2 seconds, + with easeInOutQuad easing function. + --> + <Transition fromState="*" toState="Position2"> + <NumericAnimation properties="x,y" easing="easeInOutQuad" duration="2000" /> + </Transition> + + <!-- + For any other state changes move x,y linearly over duration of 200ms. + --> + <Transition> + <NumericAnimation properties="x,y" duration="200" /> + </Transition> + + </transitions> + +</Rect> diff --git a/examples/declarative/support/contact.cpp b/examples/declarative/support/contact.cpp new file mode 100644 index 0000000..7d90fc4 --- /dev/null +++ b/examples/declarative/support/contact.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "contact.h" +#include "qmltypes.h" + +QML_DEFINE_TYPE(Contact,Contact); +Contact::Contact() : QObject(0) +{ + m_firstName = "John"; + m_lastName = "Smith"; + m_portraitFile = "contact.png"; + m_company = "Trollkia"; + m_emails << "smith@trollkia.com" << "john45@gmail.com"; + + m_numbers << new PhoneNumber; + m_numbers << new PhoneNumber; + m_numbers << new PhoneNumber; + + m_numbers.at(0)->setType(PhoneNumber::HomePhone); + m_numbers.at(0)->setNumber("35412451"); + + m_numbers.at(1)->setType(PhoneNumber::BusinessPhone); + m_numbers.at(1)->setNumber("33424994"); + + m_numbers.at(2)->setType(PhoneNumber::MobilePhone); + m_numbers.at(2)->setNumber("0424655137"); + + m_addresses << new Address; + m_addresses << new Address; + m_addresses << new Address; + m_addresses.at(0)->setNumber(13); + m_addresses.at(0)->setStreet("Blackhill Cr"); + m_addresses.at(0)->setCountry("Australia"); + m_addresses.at(1)->setNumber(116); + m_addresses.at(1)->setStreet("Sandankerveien"); + m_addresses.at(1)->setCountry("Norway"); + m_addresses.at(2)->setNumber(92); + m_addresses.at(2)->setStreet("Elizibeth St"); + m_addresses.at(2)->setCountry("Australia"); +} + +void Contact::addNumber(PhoneNumber *newNumber) +{ + + m_numbers << newNumber; + emit numbersChanged(); +} + +void Contact::addAddress(Address *newAddress) +{ + m_addresses << newAddress; + emit addressesChanged(); +} + +void Contact::addEmail(QString &newEmail) +{ + + m_emails << newEmail; + emit emailsChanged(); +} + +QML_DEFINE_TYPE(Address,Address); +Address::Address() +: _number(0) +{ +} + +QML_DEFINE_TYPE(PhoneNumber, PhoneNumber); +PhoneNumber::PhoneNumber() +: _type(HomePhone) +{ +} diff --git a/examples/declarative/support/contact.h b/examples/declarative/support/contact.h new file mode 100644 index 0000000..c403f8b --- /dev/null +++ b/examples/declarative/support/contact.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef CONTACT_H +#define CONTACT_H + +#include <qml.h> +#include <QtGui> + + +class Address : public QObject +{ + Q_OBJECT +public: + Address(); + + Q_PROPERTY(int number READ number WRITE setNumber NOTIFY changed); + Q_PROPERTY(QString street READ street WRITE setStreet NOTIFY changed); + Q_PROPERTY(QString country READ country WRITE setCountry NOTIFY changed); + + int number() const { return _number; } + void setNumber(int n) { _number = n; emit changed(); } + + QString street() const { return _street; } + void setStreet(const QString &s) { _street = s; emit changed(); } + + QString country() const { return _country; } + void setCountry(const QString &c) { _country = c; emit changed(); } + +signals: + void changed(); + +private: + int _number; + QString _street; + QString _country; +}; +QML_DECLARE_TYPE(Address); + +class PhoneNumber : public QObject +{ + Q_OBJECT + Q_ENUMS(PhoneType) +public: + PhoneNumber(); + + enum PhoneType { + HomePhone, + BusinessPhone, + MobilePhone + }; + + Q_PROPERTY(QString number READ number WRITE setNumber NOTIFY changed); + Q_PROPERTY(PhoneType type READ type WRITE setType NOTIFY changed); + + QString number() const { return _number; } + void setNumber(QString n) { _number = n; emit changed(); } + + PhoneType type() const { return _type; } + void setType(PhoneType type) { _type = type; emit changed(); } + +signals: + void changed(); + +private: + QString _number; + PhoneType _type; +}; +QML_DECLARE_TYPE(PhoneNumber); + +class Contact : public QObject +{ + Q_OBJECT +public: + Contact(); + + Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY nameChanged); + QString firstName() const { return m_firstName; } + + Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY nameChanged); + QString lastName() const { return m_lastName; } + + Q_PROPERTY(QString portraitFile READ portraitFile WRITE setPortraitFile NOTIFY portraitChanged); + QString portraitFile() const { return m_portraitFile; } + + Q_PROPERTY(QString company READ company WRITE setCompany NOTIFY companyChanged); + QString company() const { return m_company; } + + Q_PROPERTY(QStringList emails READ emails WRITE setEmails NOTIFY emailsChanged); + QStringList emails() const { return m_emails; } + + Q_PROPERTY(QList<Address *>* addresses READ addresses); + QList<Address *>* addresses() { return &m_addresses; } + + Q_PROPERTY(QList<PhoneNumber *>* numbers READ numbers); + QList<PhoneNumber *>* numbers() { return &m_numbers; } + + + void addEmail(QString&); + void addAddress(Address*); + void addNumber(PhoneNumber*); + +public slots: + void setFirstName(const QString &name) { m_firstName = name; emit nameChanged(); } + void setLastName(const QString &name) { m_lastName = name; emit nameChanged(); } + void setPortraitFile(const QString &portraitFile) { m_portraitFile = portraitFile; emit portraitChanged(); } + void setCompany(const QString &company) { m_company = company; emit companyChanged(); } + void setEmails(const QStringList &emails) { m_emails = emails; emit emailsChanged(); } + +signals: + void nameChanged(); + void portraitChanged(); + void companyChanged(); + void emailsChanged(); + void numbersChanged(); + void addressesChanged(); + +private: + QString m_firstName; + QString m_lastName; + QString m_portraitFile; + + QString m_company; + + QList<Address *> m_addresses; + QList<PhoneNumber *>m_numbers; + QStringList m_emails; +}; +QML_DECLARE_TYPE(Contact); + +#endif diff --git a/examples/declarative/support/contactmodel.cpp b/examples/declarative/support/contactmodel.cpp new file mode 100644 index 0000000..efe108fb --- /dev/null +++ b/examples/declarative/support/contactmodel.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "contactmodel.h" +#include "qmltypes.h" + +ContactModel::ContactModel(QObject *parent) : QListModelInterface(parent) +{ + QFile f("../contacts/contacts.txt"); + f.open(QIODevice::ReadOnly); + QTextStream ts(&f); + QString text = ts.readLine(); + while(!text.isEmpty()) { + Contact *c = new Contact; + QStringList list = text.split(" "); + c->setFirstName(list[0]); + c->setLastName(list[1]); + for (int i = 2; i < list.count(); ++i) + c->addEmail(list[i]); + //contactList.append(c); + insertContact(c); + + text = ts.readLine(); + } + f.close(); +} + +ContactModel::~ContactModel() +{ + while (!contactList.isEmpty()) { + Contact *c = contactList.takeFirst(); + delete c; + } +} + +int ContactModel::count() const +{ + return contactList.count(); +} + +QHash<int,QVariant> ContactModel::data(int index, const QList<int> &roles) const +{ + QHash<int,QVariant> returnHash; + + for (int i = 0; i < roles.size(); ++i) { + int role = roles.at(i); + QVariant info; + switch(role) { + case PortraitRole: + info = "contact.png"; + break; + case FirstNameRole: + info = contactList.at(index)->firstName(); + break; + case LastNameRole: + info = contactList.at(index)->lastName(); + break; + case CompanyRole: + info = contactList.at(index)->company(); + break; + case EmailsRole: + info = contactList.at(index)->emails(); + break; + case AddressesRole: + //returns QVariant BOOL + info = QVariant::fromValue(contactList.at(index)->addresses()); + break; + case NumbersRole: + info = QVariant::fromValue(contactList.at(index)->numbers()); + break; + default: + break; + } + returnHash.insert(role, info); + } + + return returnHash; +} + +QString ContactModel::toString(int role) const +{ + switch(role) { + case PortraitRole: + return "portrait"; + case FirstNameRole: + return "firstName"; + case LastNameRole: + return "lastName"; + case CompanyRole: + return "company"; + case EmailsRole: + return "emails"; + case AddressesRole: + return "addresses"; + case NumbersRole: + return "numbers"; + default: + return ""; + } +} + +QList<int> ContactModel::roles() const +{ + return QList<int>() << PortraitRole << FirstNameRole << LastNameRole << CompanyRole << EmailsRole << AddressesRole << NumbersRole; +} + +void ContactModel::deleteContact(int index) +{ + delete contactList.takeAt(index); + emit itemsRemoved(index, 1); +} + +int ContactModel::insertContact(Contact *contact) +{ + int index = 0; + QString fullName = contact->lastName(); + index = findIndex(fullName); + contactList.insert(index, contact); + emit itemsInserted(index, 1); + return index; +} + + +//search - binary search algorithm lastname only + +int ContactModel::findIndex(QString &searchName) const +{ + int start = 0; + int end = contactList.size()-1; + int middle = 0; + QString middleString; + + while (start <= end) + { + middle = (start+end)/2; + middleString = contactList.at(middle)->lastName(); + if (isAfter(searchName, middleString) < 0) start = middle+1; + else if( isAfter(middleString, searchName) < 0) end = middle-1; + else return middle; + } + return start; +} + +int ContactModel::isAfter(QString &name1, QString &name2) const +{ + //if c1 is after c2 alphabetically, return positive + int compString = QString::compare(name1, name2, Qt::CaseInsensitive); + return -compString; +} diff --git a/examples/declarative/support/contactmodel.h b/examples/declarative/support/contactmodel.h new file mode 100644 index 0000000..e262358 --- /dev/null +++ b/examples/declarative/support/contactmodel.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef _CONTACTMODEL_H_ +#define _CONTACTMODEL_H_ + +#include <qlistmodelinterface.h> +#include "contact.h" + +class ContactModel : public QListModelInterface +{ + Q_OBJECT +public: + ContactModel(QObject *parent = 0); + ~ContactModel(); + + enum Roles { + PortraitRole, + FirstNameRole, + LastNameRole, + CompanyRole, + EmailsRole, + AddressesRole, + NumbersRole + }; + + int count() const; + + QHash<int,QVariant> data(int index, const QList<int> &roles) const; + QList<int> roles() const; + + + QString toString(int role) const; + + void deleteContact(int index); + int insertContact(Contact *contact); + + int isAfter(QString &name1, QString &name2) const; + int findIndex(QString &searchName) const; + +private: + QList<Contact*> contactList; +}; + +#endif diff --git a/examples/declarative/support/support.pro b/examples/declarative/support/support.pro new file mode 100644 index 0000000..1da1a28 --- /dev/null +++ b/examples/declarative/support/support.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +TARGET = QtFxSupport +DEPENDPATH += . +INCLUDEPATH += . +MOC_DIR = .moc +OBJECTS_DIR = .obj +DESTDIR = ../../lib +QT += script declarative + +HEADERS += contact.h contactmodel.h +SOURCES += contact.cpp contactmodel.cpp + diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml new file mode 100644 index 0000000..06c9f5a --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml @@ -0,0 +1,22 @@ +<Rect id="page" width="240" height="180" color='black'> + <RemoveButton1 + y="5" + anchors.right="{page.right}" + anchors.rightMargin="5"/> + <RemoveButton2 + y="40" + anchors.right="{page.right}" + anchors.rightMargin="5"/> + <RemoveButton3 + y="75" + anchors.right="{page.right}" + anchors.rightMargin="5"/> + <RemoveButton4 + y="110" + anchors.right="{page.right}" + anchors.rightMargin="5"/> + <RemoveButton5 + y="145" + anchors.right="{page.right}" + anchors.rightMargin="5"/> +</Rect> diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml new file mode 100644 index 0000000..dc3f505 --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml @@ -0,0 +1,4 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"/> diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml new file mode 100644 index 0000000..2ba488d --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml @@ -0,0 +1,10 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png"/> +</Rect> diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml new file mode 100644 index 0000000..9a364c5 --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml @@ -0,0 +1,23 @@ +<Rect id="removeButton" + width="230" height="30" + color="red" + radius="5"> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png"/> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png"/> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove"/> +</Rect> diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml new file mode 100644 index 0000000..45ca19d --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml @@ -0,0 +1,65 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + } else { + removeButton.state = 'opened'; + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="230"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> +</Rect> diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml new file mode 100644 index 0000000..68c1838 --- /dev/null +++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml @@ -0,0 +1,70 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + } else { + removeButton.state = 'opened'; + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="230"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml new file mode 100644 index 0000000..29fdf51 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml @@ -0,0 +1,34 @@ +<Rect id="page" width="480" height="360" color='black'> + <properties> + <Property name="mouseGrabbed" value="false"/> + </properties> + <Item x="0" y="0" width="240" height="180"> + <ContactField1 + y="5" + anchors.left="{parent.left}" anchors.leftMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5"/> + <ContactField2 + y="40" + anchors.left="{parent.left}" anchors.leftMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5"/> + <ContactField3 + y="75" + anchors.left="{parent.left}" anchors.leftMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5" + label="Phone Number" + icon="../shared/pics/phone.png" + value="123123"/> + </Item> + <Rect pen.color="gray" x="5" y="115" width="230" height="180" radius="5"> + <Contact3 anchors.fill="{parent}" + label="Brian" + phone="123123" + email="brian@bigisp.com" /> + </Rect> + <Rect pen.color="gray" x="245" y="115" width="230" height="180" radius="5"> + <Contact4 anchors.fill="{parent}" + label="Brian" + phone="123123" + email="brian@bigisp.com" /> + </Rect> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml b/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml new file mode 100644 index 0000000..fdd0c6d --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml @@ -0,0 +1,27 @@ +<Item id="contactDetails"> + <properties> + <Property name="contactid" value=""/> + <Property name="label" onValueChanged="labelField.value = label"/> + <Property name="phone" onValueChanged="phoneField.value = phone"/> + <Property name="email" onValueChanged="emailField.value = email"/> + </properties> + <VerticalLayout id="layout" + anchors.fill="{parent}" + spacing="5" + margin="5"> + <ContactField3 id="labelField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + label="Name"/> + <ContactField3 id="phoneField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/phone.png" + label="Phone"/> + <ContactField3 id="emailField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/email.png" + label="Email"/> + </VerticalLayout> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml b/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml new file mode 100644 index 0000000..b1882da --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml @@ -0,0 +1,27 @@ +<Item id="contactDetails"> + <properties> + <Property name="contactid" value=""/> + <Property name="label" onValueChanged="labelField.value = label"/> + <Property name="phone" onValueChanged="phoneField.value = phone"/> + <Property name="email" onValueChanged="emailField.value = email"/> + </properties> + <VerticalLayout id="layout" + anchors.fill="{parent}" + spacing="5" + margin="5"> + <ContactField4 id="labelField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + label="Name"/> + <ContactField4 id="phoneField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/phone.png" + label="Phone"/> + <ContactField4 id="emailField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/email.png" + label="Email"/> + </VerticalLayout> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml new file mode 100644 index 0000000..5547a3b --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml @@ -0,0 +1,17 @@ +<Item id="contactField" + clip="true" + height="30"> + <RemoveButton1 id="removeButton" + anchors.right="{parent.right}" + anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"/> + <Text id="fieldText" + width="{contactField.width-70}" + anchors.right="{removeButton.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + font.bold="true" + color="white" + text="Phone Number"/> + <Image src="../shared/pics/phone.png" + anchors.right="{fieldText.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}"/> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml new file mode 100644 index 0000000..b69e03c --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml @@ -0,0 +1,19 @@ +<Item id="contactField" + clip="true" + height="30"> + <RemoveButton2 id="removeButton" + anchors.right="{parent.right}" + anchors.top="{parent.top}" anchors.bottom="{parent.bottom}" + expandedWidth="{contactField.width}" + onConfirmed="print('Clear field text'); fieldText.text=''"/> + <Text id="fieldText" + width="{contactField.width-70}" + anchors.right="{removeButton.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + font.bold="true" + color="white" + text="Phone Number"/> + <Image src="../shared/pics/phone.png" + anchors.right="{fieldText.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}"/> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml new file mode 100644 index 0000000..f3a11f9 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml @@ -0,0 +1,35 @@ +<Item id="contactField" + clip="true" + height="30"> + <properties> + <Property name="label"/> + <Property name="icon"/> + <Property name="value"/> + </properties> + <RemoveButton3 id="removeButton" + anchors.right="{parent.right}" + anchors.top="{parent.top}" anchors.bottom="{parent.bottom}" + expandedWidth="{contactField.width}" + onConfirmed="print('Clear field text'); fieldText.text=''"/> + <FieldText3 id="fieldText" + width="{contactField.width-70}" + anchors.right="{removeButton.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + label="{contactField.label}" + text="{contactField.value}"/> + <Image + anchors.right="{fieldText.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + src="{contactField.icon}"/> + <states> + <State name="editingText" when="{fieldText.state == 'editing'}"> + <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/> + <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="width,rightMargin" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml new file mode 100644 index 0000000..13ccbc0 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml @@ -0,0 +1,35 @@ +<Item id="contactField" + clip="true" + height="30"> + <properties> + <Property name="label"/> + <Property name="icon"/> + <Property name="value"/> + </properties> + <RemoveButton4 id="removeButton" + anchors.right="{parent.right}" + anchors.top="{parent.top}" anchors.bottom="{parent.bottom}" + expandedWidth="{contactField.width}" + onConfirmed="print('Clear field text'); fieldText.text=''"/> + <FieldText4 id="fieldText" + width="{contactField.width-70}" + anchors.right="{removeButton.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + label="{contactField.label}" + text="{contactField.value}"/> + <Image + anchors.right="{fieldText.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + src="{contactField.icon}"/> + <states> + <State name="editingText" when="{fieldText.state == 'editing'}"> + <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/> + <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="width,rightMargin" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml b/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml new file mode 100644 index 0000000..c807aed --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml @@ -0,0 +1,93 @@ +<Rect id="fieldText" + height="30" + radius="5" + color="black"> + <properties> + <Property + name="text" + value="" + onValueChanged="reset()"/> + <Property + name="label" + value=""/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function edit() { + fieldText.state='editing'; + } + function confirm() { + fieldText.text = textEdit.text; + fieldText.state=''; + fieldText.confirmed.emit(); + } + function reset() { + textEdit.text = fieldText.text; + fieldText.state=''; + } + </Script> + </resources> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"/> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"/> + <TextEdit id="textEdit" + anchors.left="{parent.left}" anchors.leftMargin="0" + anchors.right="{parent.right}" anchors.rightMargin="0" + anchors.verticalCenter="{parent.verticalCenter}" + color="white" + font.bold="true" + readOnly="true" + wrap="false" + /> + <Text id="textLabel" + x="5" width="{parent.width-10}" + anchors.verticalCenter="{parent.verticalCenter}" + hAlign="AlignHCenter" + color="#505050" + font.italic="true" + text="{fieldText.label}" + opacity="{textEdit.text != '' ? 0 : 1}"> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> + </Text> + <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/> + <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/> + <MouseRegion + id="editRegion" + anchors.fill="{textEdit}" + onClicked="edit()"/> + <states> + <State name="editing"> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{fieldText}" property="color" value="white"/> + <SetProperty target="{textEdit}" property="color" value="black"/> + <SetProperty target="{textEdit}" property="readOnly" value="false"/> + <SetProperty target="{textEdit}" property="focus" value="true"/> + <SetProperty target="{editRegion}" property="opacity" value="0"/> + <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/> + <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/> + <ColorAnimation duration="150"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml b/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml new file mode 100644 index 0000000..a4df42b --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml @@ -0,0 +1,98 @@ +<Rect id="fieldText" + height="30" + radius="5" + color="black"> + <properties> + <Property + name="text" + value="" + onValueChanged="reset()"/> + <Property + name="label" + value=""/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function edit() { + if (!page.mouseGrabbed) { + fieldText.state='editing'; + page.mouseGrabbed=true; + } + } + function confirm() { + fieldText.text = textEdit.text; + fieldText.state=''; + page.mouseGrabbed=false; + fieldText.confirmed.emit(); + } + function reset() { + textEdit.text = fieldText.text; + fieldText.state=''; + page.mouseGrabbed=false; + } + </Script> + </resources> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"/> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"/> + <TextEdit id="textEdit" + anchors.left="{parent.left}" anchors.leftMargin="0" + anchors.right="{parent.right}" anchors.rightMargin="0" + anchors.verticalCenter="{parent.verticalCenter}" + color="white" + font.bold="true" + readOnly="true" + wrap="false" + /> + <Text id="textLabel" + x="5" width="{parent.width-10}" + anchors.verticalCenter="{parent.verticalCenter}" + hAlign="AlignHCenter" + color="#505050" + font.italic="true" + text="{fieldText.label}" + opacity="{textEdit.text != '' ? 0 : 1}"> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> + </Text> + <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/> + <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/> + <MouseRegion + id="editRegion" + anchors.fill="{textEdit}" + onClicked="edit()"/> + <states> + <State name="editing"> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{fieldText}" property="color" value="white"/> + <SetProperty target="{textEdit}" property="color" value="black"/> + <SetProperty target="{textEdit}" property="readOnly" value="false"/> + <SetProperty target="{textEdit}" property="focus" value="true"/> + <SetProperty target="{editRegion}" property="opacity" value="0"/> + <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/> + <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/> + <ColorAnimation duration="150"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml new file mode 100644 index 0000000..68c1838 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml @@ -0,0 +1,70 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + } else { + removeButton.state = 'opened'; + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="230"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml new file mode 100644 index 0000000..d9ff4c5 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml @@ -0,0 +1,76 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <properties> + <Property name="expandedWidth" value="230"/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + } else { + removeButton.state = 'opened'; + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle(); removeButton.confirmed.emit()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml new file mode 100644 index 0000000..d9ff4c5 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml @@ -0,0 +1,76 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <properties> + <Property name="expandedWidth" value="230"/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + } else { + removeButton.state = 'opened'; + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle(); removeButton.confirmed.emit()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml new file mode 100644 index 0000000..a489e95 --- /dev/null +++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml @@ -0,0 +1,80 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <properties> + <Property name="expandedWidth" value="230"/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + page.mouseGrabbed=false; + } else { + if (!page.mouseGrabbed) { + removeButton.state = 'opened'; + page.mouseGrabbed=true; + } + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle(); removeButton.confirmed.emit()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml new file mode 100644 index 0000000..ed2a3dc --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml @@ -0,0 +1,8 @@ +<Rect id="page" width="480" height="640" color='black'> + <properties> + <Property name="mouseGrabbed" value="false"/> + </properties> + <ContactView1 x="0" y="0" width="240" height="320"/> + <ContactView2 x="240" y="0" width="240" height="320"/> + <ContactView3 x="0" y="320" width="240" height="320"/> +</Rect> diff --git a/examples/declarative/tutorials/contacts/3_Collections/Button.qml b/examples/declarative/tutorials/contacts/3_Collections/Button.qml new file mode 100644 index 0000000..8290d35 --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/Button.qml @@ -0,0 +1,38 @@ +<Item id="button" width="30" height="30"> + <properties> + <Property name="icon"/> + </properties> + <signals> + <Signal name="clicked"/> + </signals> + <Rect id="buttonRect" + anchors.fill="{parent}" + color="lightgreen" + radius="5"> + <Image id="iconImage" + src="{button.icon}" + anchors.horizontalCenter="{buttonRect.horizontalCenter}" + anchors.verticalCenter="{buttonRect.verticalCenter}"/> + <MouseRegion id="buttonMouseRegion" + anchors.fill="{buttonRect}" + onClicked="button.clicked.emit()"/> + <states> + <State name="pressed" when="{buttonMouseRegion.pressed == true}"> + <SetProperty target="{buttonRect}" property="color" value="green"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="pressed"> + <ColorAnimation duration="200"/> + </Transition> + <Transition fromState="pressed" toState="*"> + <ColorAnimation duration="1000"/> + </Transition> + </transitions> + </Rect> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/Contact.qml b/examples/declarative/tutorials/contacts/3_Collections/Contact.qml new file mode 100644 index 0000000..f620c25 --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/Contact.qml @@ -0,0 +1,28 @@ +<Item id="contactDetails" + anchors.fill="{parent}"> + <properties> + <Property name="contactid" value=""/> + <Property name="label" onValueChanged="labelField.value = label"/> + <Property name="phone" onValueChanged="phoneField.value = phone"/> + <Property name="email" onValueChanged="emailField.value = email"/> + </properties> + <VerticalLayout id="layout" + anchors.fill="{parent}" + spacing="5" + margin="5"> + <ContactField id="labelField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + label="Name"/> + <ContactField id="phoneField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/phone.png" + label="Phone"/> + <ContactField id="emailField" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5" + icon="../shared/pics/email.png" + label="Email"/> + </VerticalLayout> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml new file mode 100644 index 0000000..819914c --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml @@ -0,0 +1,35 @@ +<Item id="contactField" + clip="true" + height="30"> + <properties> + <Property name="label"/> + <Property name="icon"/> + <Property name="value"/> + </properties> + <RemoveButton id="removeButton" + anchors.right="{parent.right}" + anchors.top="{parent.top}" anchors.bottom="{parent.bottom}" + expandedWidth="{contactField.width}" + onConfirmed="print('Clear field text'); fieldText.text=''"/> + <FieldText id="fieldText" + width="{contactField.width-70}" + anchors.right="{removeButton.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + label="{contactField.label}" + text="{contactField.value}"/> + <Image + anchors.right="{fieldText.left}" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + src="{contactField.icon}"/> + <states> + <State name="editingText" when="{fieldText.state == 'editing'}"> + <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/> + <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="width,rightMargin" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml new file mode 100644 index 0000000..d6f7bad --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml @@ -0,0 +1,22 @@ +<Item id="contacts"> + <resources> + <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/> + <SqlQuery id="contactList" connection="{contactDatabase}"> + <query>SELECT recid, label, email, phone FROM contacts ORDER BY label, recid</query> + </SqlQuery> + <Component id="contactDelegate"> + <Text + x="40" y="12" + width="{contactListView.width-30}" + height="30" + color="white" + font.bold="true" + text="{model.label}"/> + </Component> + </resources> + <ListView id="contactListView" + anchors.fill="{parent}" + clip="true" + model="{contactList}" + delegate="{contactDelegate}"/> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml new file mode 100644 index 0000000..da1e5db --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml @@ -0,0 +1,62 @@ +<Item id="contacts"> + <resources> + <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/> + <SqlQuery id="contactList" connection="{contactDatabase}"> + <query>SELECT recid AS contactid, label, email, phone FROM contacts ORDER BY label, recid</query> + </SqlQuery> + <Component id="contactDelegate"> + <Item id="wrapper" + x="0" + width="{ListView.view.width}" height="34"> + <Text id="label" + x="40" y="12" + width="{parent.width-30}" + text="{model.label}" + color="white" + font.bold="true"> + </Text> + <MouseRegion + anchors.fill="{label}" + onClicked="wrapper.state='opened'"/> + <Contact id="details" + anchors.fill="{parent}" + contactid="{model.contactid}" + label="{model.label}" + email="{model.email}" + phone="{model.phone}" + opacity="0"/> + <states> + <State name='opened'> + <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/> + <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/> + <SetProperty target="{contactListView}" property="locked" value="1"/> + <SetProperty target="{label}" property="opacity" value="0"/> + <SetProperty target="{details}" property="opacity" value="1"/> + </State> + </states> + <transitions> + <Transition> + <NumericAnimation duration="500" properties="yPosition,height,opacity"/> + </Transition> + </transitions> + <Connection sender="{cancelEditButton}" signal="clicked()"> + if (wrapper.state == 'opened') { + wrapper.state = ''; + } + </Connection> + </Item> + </Component> + </resources> + <Button id="cancelEditButton" + anchors.top="{parent.top}" anchors.topMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5" + icon="../shared/pics/cancel.png"/> + <ListView id="contactListView" + anchors.left="{parent.left}" + anchors.right="{parent.right}" + anchors.top="{cancelEditButton.bottom}" + anchors.bottom="{parent.bottom}" + clip="true" + model="{contactList}" + delegate="{contactDelegate}"/> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml new file mode 100644 index 0000000..a5d88a1 --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml @@ -0,0 +1,67 @@ +<Item id="contacts"> + <resources> + <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/> + <SqlQuery id="contactList" connection="{contactDatabase}"> + <query>SELECT recid AS contactid, label, email, phone FROM contacts ORDER BY label, recid</query> + </SqlQuery> + <Component id="contactDelegate"> + <Item id="wrapper" + x="0" + width="{ListView.view.width}" height="34"> + <Text id="label" + x="40" y="12" + width="{parent.width-30}" + text="{model.label}" + color="white" + font.bold="true"> + </Text> + <MouseRegion + anchors.fill="{label}"> + <onClicked> + Details.qml = 'Contact.qml'; + wrapper.state='opened'; + </onClicked> + </MouseRegion> + <Item id="Details" + anchors.fill="{wrapper}" + opacity="0"> + <Bind target="{Details.qmlItem}" property="contactid" value="{model.contactid}"/> + <Bind target="{Details.qmlItem}" property="label" value="{model.label}"/> + <Bind target="{Details.qmlItem}" property="phone" value="{model.phone}"/> + <Bind target="{Details.qmlItem}" property="email" value="{model.email}"/> + </Item> + <states> + <State name='opened'> + <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/> + <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/> + <SetProperty target="{contactListView}" property="locked" value="1"/> + <SetProperty target="{label}" property="opacity" value="0"/> + <SetProperty target="{Details}" property="opacity" value="1"/> + </State> + </states> + <transitions> + <Transition> + <NumericAnimation duration="500" properties="yPosition,height,opacity"/> + </Transition> + </transitions> + <Connection sender="{cancelEditButton}" signal="clicked()"> + if (wrapper.state == 'opened') { + wrapper.state = ''; + } + </Connection> + </Item> + </Component> + </resources> + <Button id="cancelEditButton" + anchors.top="{parent.top}" anchors.topMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5" + icon="../shared/pics/cancel.png"/> + <ListView id="contactListView" + anchors.left="{parent.left}" + anchors.right="{parent.right}" + anchors.top="{cancelEditButton.bottom}" + anchors.bottom="{parent.bottom}" + clip="true" + model="{contactList}" + delegate="{contactDelegate}"/> +</Item> diff --git a/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml b/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml new file mode 100644 index 0000000..a4df42b --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml @@ -0,0 +1,98 @@ +<Rect id="fieldText" + height="30" + radius="5" + color="black"> + <properties> + <Property + name="text" + value="" + onValueChanged="reset()"/> + <Property + name="label" + value=""/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function edit() { + if (!page.mouseGrabbed) { + fieldText.state='editing'; + page.mouseGrabbed=true; + } + } + function confirm() { + fieldText.text = textEdit.text; + fieldText.state=''; + page.mouseGrabbed=false; + fieldText.confirmed.emit(); + } + function reset() { + textEdit.text = fieldText.text; + fieldText.state=''; + page.mouseGrabbed=false; + } + </Script> + </resources> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"/> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"/> + <TextEdit id="textEdit" + anchors.left="{parent.left}" anchors.leftMargin="0" + anchors.right="{parent.right}" anchors.rightMargin="0" + anchors.verticalCenter="{parent.verticalCenter}" + color="white" + font.bold="true" + readOnly="true" + wrap="false" + /> + <Text id="textLabel" + x="5" width="{parent.width-10}" + anchors.verticalCenter="{parent.verticalCenter}" + hAlign="AlignHCenter" + color="#505050" + font.italic="true" + text="{fieldText.label}" + opacity="{textEdit.text != '' ? 0 : 1}"> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> + </Text> + <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/> + <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/> + <MouseRegion + id="editRegion" + anchors.fill="{textEdit}" + onClicked="edit()"/> + <states> + <State name="editing"> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{fieldText}" property="color" value="white"/> + <SetProperty target="{textEdit}" property="color" value="black"/> + <SetProperty target="{textEdit}" property="readOnly" value="false"/> + <SetProperty target="{textEdit}" property="focus" value="true"/> + <SetProperty target="{editRegion}" property="opacity" value="0"/> + <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/> + <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/> + <ColorAnimation duration="150"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml b/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml new file mode 100644 index 0000000..a489e95 --- /dev/null +++ b/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml @@ -0,0 +1,80 @@ +<Rect id="removeButton" + width="30" height="30" + color="red" + radius="5"> + <properties> + <Property name="expandedWidth" value="230"/> + </properties> + <signals> + <Signal name="confirmed"/> + </signals> + <resources> + <Script> + function toggle() { + print('removeButton.toggle()'); + if (removeButton.state == 'opened') { + removeButton.state = ''; + page.mouseGrabbed=false; + } else { + if (!page.mouseGrabbed) { + removeButton.state = 'opened'; + page.mouseGrabbed=true; + } + } + } + </Script> + </resources> + <Image id="trashIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/trash.png" + opacity="1"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="cancelIcon" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/cancel.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle()"/> + </Image> + <Image id="confirmIcon" + width="22" height="22" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}" + src="../shared/pics/ok.png" + opacity="0"> + <MouseRegion + anchors.fill="{parent}" + onClicked="toggle(); removeButton.confirmed.emit()"/> + </Image> + <Text id="text" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4" + font.bold="true" + color="white" + hAlign="AlignHCenter" + text="Remove" + opacity="0"/> + <states> + <State name="opened"> + <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/contacts/shared/contacts.sqlite b/examples/declarative/tutorials/contacts/shared/contacts.sqlite Binary files differnew file mode 100644 index 0000000..7347adc --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/contacts.sqlite diff --git a/examples/declarative/tutorials/contacts/shared/pics/cancel.png b/examples/declarative/tutorials/contacts/shared/pics/cancel.png Binary files differnew file mode 100644 index 0000000..ecc9533 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/cancel.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/email.png b/examples/declarative/tutorials/contacts/shared/pics/email.png Binary files differnew file mode 100644 index 0000000..04b3865 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/email.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/new.png b/examples/declarative/tutorials/contacts/shared/pics/new.png Binary files differnew file mode 100644 index 0000000..c7ebac3 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/new.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/ok.png b/examples/declarative/tutorials/contacts/shared/pics/ok.png Binary files differnew file mode 100644 index 0000000..5795f04 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/ok.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/phone.png b/examples/declarative/tutorials/contacts/shared/pics/phone.png Binary files differnew file mode 100644 index 0000000..fc9c222 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/phone.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/search.png b/examples/declarative/tutorials/contacts/shared/pics/search.png Binary files differnew file mode 100644 index 0000000..cc74e69 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/search.png diff --git a/examples/declarative/tutorials/contacts/shared/pics/trash.png b/examples/declarative/tutorials/contacts/shared/pics/trash.png Binary files differnew file mode 100644 index 0000000..2042595 --- /dev/null +++ b/examples/declarative/tutorials/contacts/shared/pics/trash.png diff --git a/examples/declarative/tutorials/contacts/t8/Button.qml b/examples/declarative/tutorials/contacts/t8/Button.qml new file mode 100644 index 0000000..63c4636 --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/Button.qml @@ -0,0 +1,33 @@ +<Item width="30" height="30" id="button"> + <properties> + <Property name="icon"/> + </properties> + <signals> + <Signal name="clicked"/> + </signals> + <Rect id="buttonRect" color="lightgreen" anchors.fill="{parent}" radius="5"> + <Image id="iconImage" + src="{button.icon}" + anchors.horizontalCenter="{buttonRect.horizontalCenter}" + anchors.verticalCenter="{buttonRect.verticalCenter}"/> + <MouseRegion id="buttonMouseRegion" anchors.fill="{buttonRect}" onClicked="button.clicked.emit()"/> + <states> + <State name="pressed" when="{buttonMouseRegion.pressed == true}"> + <SetProperty target="{buttonRect}" property="color" value="green"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="pressed"> + <ColorAnimation duration="200"/> + </Transition> + <Transition fromState="pressed" toState="*"> + <ColorAnimation duration="1000"/> + </Transition> + </transitions> + </Rect> + <opacity> + <Behaviour> + <NumericAnimation property="opacity" duration="250"/> + </Behaviour> + </opacity> +</Item> diff --git a/examples/declarative/tutorials/contacts/t8/Contact.qml b/examples/declarative/tutorials/contacts/t8/Contact.qml new file mode 100644 index 0000000..5852b43 --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/Contact.qml @@ -0,0 +1,80 @@ +<Item id="contactDetails" anchors.fill="{parent}"> + <properties> + <Property name="label" onValueChanged="c_label.value = label"/> + <Property name="contactid" value=""/> + <Property name="phone" onValueChanged="c_phone.value = phone"/> + <Property name="email" onValueChanged="c_email.value = email"/> + <Property name="mode" value="closed"/> + </properties> + <signals> + <Signal name="open"/> + <Signal name="close"/> + <Signal name="confirm"/> + <Signal name="cancel"/> + </signals> + <resources> + <SqlQuery id="updateContactQuery" connection="{contactDatabase}"> + <query>UPDATE contacts SET label = :l, email = :e, phone = :p WHERE recid = :r</query> + <bindings> + <SqlBind name=":r" value="{contactid}"/> + <SqlBind name=":l" value="{c_label.value}"/> + <SqlBind name=":e" value="{c_email.value}"/> + <SqlBind name=":p" value="{c_phone.value}"/> + </bindings> + </SqlQuery> + <SqlQuery id="insertContactQuery" connection="{contactDatabase}"> + <query>INSERT INTO contacts (label, email, phone) VALUES(:l, :e, :p)</query> + <bindings> + <SqlBind name=":l" value="{c_label.value}"/> + <SqlBind name=":e" value="{c_email.value}"/> + <SqlBind name=":p" value="{c_phone.value}"/> + </bindings> + </SqlQuery> + </resources> + <Connection sender="{contactDetails}" signal="cancel()"> + c_label.value = label; + c_phone.value = phone; + c_email.value = email; + contactDetails.close.emit(); + </Connection> + <Connection sender="{contactDetails}" signal="confirm()"> + if (c_label.value != '') { + if (contactid == '') { + insertContactQuery.exec(); + c_label.value = label; + c_phone.value = phone; + c_email.value = email; + } else { + updateContactQuery.exec(); + } + contactList.exec(); + } + contactDetails.close.emit(); + </Connection> + <VerticalLayout id="layout" anchors.fill="{parent}" spacing="5" margin="5"> + <Field id="c_label" label="Name" + editable="{mode == 'opened' ? 1 : 0}" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5"/> + <Field id="c_phone" icon="../shared/pics/phone.png" label="Phone" + opacity="0" editable="{mode == 'opened' ? 1 : 0}" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5"/> + <Field id="c_email" icon="../shared/pics/email.png" label="Email" + opacity="0" editable="{mode == 'opened' ? 1 : 0}" + anchors.left="{layout.left}" anchors.leftMargin="5" + anchors.right="{layout.right}" anchors.rightMargin="5"/> + </VerticalLayout> + <MouseRegion anchors.fill="{contactDetails}" onClicked="contactDetails.open.emit()" z="{mode=='opened' ? -1 : 1}"/> + <states> + <State name="opened" when="{mode == 'opened'}"> + <SetProperty target="{c_phone}" property="opacity" value="1"/> + <SetProperty target="{c_email}" property="opacity" value="1"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation target="{contactFields}" properties="opacity" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/t8/Field.qml b/examples/declarative/tutorials/contacts/t8/Field.qml new file mode 100644 index 0000000..0191ef8 --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/Field.qml @@ -0,0 +1,54 @@ +<Item height="30" width="200" id="field"> + <properties> + <Property name="value" onValueChanged="fieldText.text=field.value"/> + <Property name="icon"/> + <Property name="editable" value="0"/> + <Property name="label"/> + </properties> + <Item id="fieldSelector" width="30" height="30" + x="0" + anchors.top="{parent.top}" + anchors.bottom="{parent.bottom}"> + <Image src="{field.icon}" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.horizontalCenter="{parent.horizontalCenter}"/> + </Item> + <FieldText id="fieldText" + label="{field.label}" + width="{field.width-70}" + anchors.left="{fieldSelector.right}" + anchors.leftMargin="5" + anchors.top="{parent.top}" + anchors.bottom="{parent.bottom}" + onTextEdited="field.value = fieldText.text"/> + <FieldRemover id="fieldRemover" + anchors.left="{fieldText.right}" + anchors.leftMargin="5" + anchors.top="{parent.top}" + anchors.bottom="{parent.bottom}" + onConfirm="fieldText.text = ''" + opacity="{field.editable}"/> + <states> + <State name="textFill" when="{fieldText.open == 'true'}"> + <SetProperty target="{fieldText}" property="width" value="{field.width}"/> + <SetProperty target="{fieldText}" property="x" value="0"/> + <SetProperty target="{fieldRemover}" property="opacity" value="0"/> + <SetProperty target="{fieldSelector}" property="opacity" value="0"/> + <SetProperty target="{fieldSelector}" property="x" value="{-5-fieldSelector.width}"/> + </State> + <State name="removerFill" when="{fieldRemover.open == 'true'}"> + <SetProperty target="{fieldRemover}" property="width" value="{field.width}"/> + <SetProperty target="{fieldRemover}" property="x" value="0"/> + <SetProperty target="{fieldText}" property="opacity" value="0"/> + <SetProperty target="{fieldSelector}" property="opacity" value="0"/> + <SetProperty target="{fieldSelector}" property="x" value="{-10-fieldText.width-fieldSelector.width}"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="*"> + <NumericAnimation target="{fieldSelector}" properties="width,x,opacity" duration="200"/> + <NumericAnimation target="{fieldText}" properties="width,x,opacity" duration="200"/> + <NumericAnimation target="{fieldRemover}" properties="width,x,opacity" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/t8/FieldRemover.qml b/examples/declarative/tutorials/contacts/t8/FieldRemover.qml new file mode 100644 index 0000000..a7dad64 --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/FieldRemover.qml @@ -0,0 +1,57 @@ +<Item height="30" width="30" id="fieldRemover" clip="true"> + <properties> + <Property name="open" value="false"/> + </properties> + <signals> + <Signal name="confirm"/> + </signals> + <resources> + <Script> + function toggle() { + if (fieldRemover.state=='opened') { + fieldRemover.state=''; + open='false'; + Page.mouseGrabbed='false'; + } else { + if (Page.mouseGrabbed != 'true') { + fieldRemover.state='opened'; + open='true'; + Page.mouseGrabbed='true'; + } + } + } + </Script> + </resources> + <Rect id="border" anchors.fill="{parent}" color="red" radius="5"/> + <Image id="trashIcon" src="../shared/pics/trash.png" + width="22" height="22" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}"/> + <Image id="cancelIcon" src="../shared/pics/cancel.png" + width="22" height="22" opacity="0" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}"/> + <Image id="confirmIcon" src="../shared/pics/ok.png" + width="22" height="22" opacity="0" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}"/> + <Text id="text" opacity="0" text="Remove" font.bold="true" color="white" hAlign="AlignHCenter" + anchors.verticalCenter="{parent.verticalCenter}" + anchors.left="{confirmIcon.right}" anchors.leftMargin="4" + anchors.right="{cancelIcon.left}" anchors.rightMargin="4"/> + <MouseRegion anchors.fill="{confirmIcon}" onClicked="toggle(); fieldRemover.confirm.emit()"/> + <MouseRegion anchors.fill="{trashIcon}" onClicked="toggle()"/> + <states> + <State name="opened"> + <SetProperty target="{text}" property="opacity" value="1"/> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{trashIcon}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="opened" reversible="true"> + <NumericAnimation properties="opacity,x,width" duration="200"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/t8/FieldText.qml b/examples/declarative/tutorials/contacts/t8/FieldText.qml new file mode 100644 index 0000000..d3a158a --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/FieldText.qml @@ -0,0 +1,89 @@ +<Item height="30" id="fieldText"> + <properties> + <Property name="open" value="false"/> + <Property name="text" value="" onValueChanged="setText(fieldText.text)"/> + <Property name="label" value=""/> + </properties> + <signals> + <Signal name="textEdited"/> + </signals> + <resources> + <Script> + function start() { + if (Page.mouseGrabbed != 'true') { + fieldText.state='editing'; + open='true'; + Page.mouseGrabbed='true'; + } + } + function confirm() { + fieldText.text = textEdit.text; + fieldText.state=''; + open='false'; + Page.mouseGrabbed='false'; + fieldText.textEdited.emit(); + } + function cancel() { + textEdit.text = fieldText.text; + fieldText.state=''; + open='false'; + Page.mouseGrabbed='false'; + } + function setText(value) { + if (textEdit.text != value) { + fieldText.state=''; + open='false'; + textEdit.text = value; + } + } + </Script> + </resources> + <Rect id="border" radius="5" anchors.fill="{parent}" color="{field.editable == 1 ? '#202020' : '#000000'}"> + <TextEdit id="textEdit" vAlign="AlignVCenter" text="" + readOnly="true" font.bold="true" wrap="false" color="white" + x="5" width="{parent.width-10}" + anchors.verticalCenter="{parent.verticalCenter}" + /> + <Text id="textLabel" vAlign="AlignVCenter" hAlign="AlignHCenter" + color="#505050" font.italic="true" + anchors.fill="{border}" text="{fieldText.label}" + opacity="{textEdit.text == '' ? 1 : 0}"> + <opacity> + <Behaviour> + <NumericAnimation target="{textLabel}" property="opacity" duration="250"/> + </Behaviour> + </opacity> + </Text> + <Image id="cancelIcon" src="../shared/pics/cancel.png" + width="22" height="22" opacity="0" + anchors.right="{parent.right}" anchors.rightMargin="4" + anchors.verticalCenter="{parent.verticalCenter}"/> + <Image id="confirmIcon" src="../shared/pics/ok.png" + width="22" height="22" opacity="0" + anchors.left="{parent.left}" anchors.leftMargin="4" + anchors.verticalCenter="{parent.verticalCenter}"/> + <MouseRegion anchors.fill="{cancelIcon}" onClicked="cancel()"/> + <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/> + <MouseRegion id="editRegion" anchors.fill="{textEdit}" onClicked="start()"/> + </Rect> + <states> + <State name="editing"> + <SetProperty target="{confirmIcon}" property="opacity" value="1"/> + <SetProperty target="{cancelIcon}" property="opacity" value="1"/> + <SetProperty target="{border}" property="color" value="white"/> + <SetProperty target="{textEdit}" property="color" value="black"/> + <SetProperty target="{textEdit}" property="readOnly" value="false"/> + <SetProperty target="{textEdit}" property="focus" value="true"/> + <SetProperty target="{textEdit}" property="x" value="35"/> + <SetProperty target="{editRegion}" property="opacity" value="0"/> + </State> + </states> + <transitions> + <Transition fromState='' toState="*" reversible="true"> + <NumericAnimation target="{textEdit}" properties="x" duration="200"/> + <NumericAnimation target="{confirmIcon}" properties="opacity" duration="200"/> + <NumericAnimation target="{cancelIcon}" properties="opacity" duration="200"/> + <ColorAnimation duration="150"/> + </Transition> + </transitions> +</Item> diff --git a/examples/declarative/tutorials/contacts/t8/SearchBar.qml b/examples/declarative/tutorials/contacts/t8/SearchBar.qml new file mode 100644 index 0000000..f8e1a6a --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/SearchBar.qml @@ -0,0 +1,16 @@ +<Item height="30" width="{parent.width}"> + <properties> + <Property name="text" value="{searchEdit.text}"/> + </properties> + <Rect color="white" anchors.fill="{parent}"> + <Image id="searchIcon" src="../shared/pics/search.png" + anchors.left="{parent.left}" anchors.leftMargin="5" + anchors.verticalCenter="{parent.verticalCenter}"/> + <TextEdit id="searchEdit" focus="{Page.listShown == 1}" + anchors.left="{searchIcon.right}" anchors.right="{parent.right}" + anchors.leftMargin="5" anchors.rightMargin="5" + anchors.verticalCenter="{parent.verticalCenter}" + readOnly="false" wrap="false"/> + </Rect> +</Item> + diff --git a/examples/declarative/tutorials/contacts/t8/contacts.qml b/examples/declarative/tutorials/contacts/t8/contacts.qml new file mode 100644 index 0000000..f76ccfd --- /dev/null +++ b/examples/declarative/tutorials/contacts/t8/contacts.qml @@ -0,0 +1,133 @@ +<Rect id="Page" color="black" width="240" height="320"> + <properties> + <Property name="listShown" value="1"/> + <Property name="mode" value="list"/> + <Property name="mouseGrabbed" value="false"/> + </properties> + <resources> + <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/> + <SqlQuery id="contactList" connection="{contactDatabase}"> + <query>SELECT recid, label, email, phone FROM contacts WHERE lower(label) LIKE lower(:searchTerm) ORDER BY label, recid</query> + <bindings> + <SqlBind name=":searchTerm" value="{searchBar.text + '%' }"/> + </bindings> + </SqlQuery> + <Component id="contactDelegate"> + <Item id="wrapper" x="0" width="{ListView.view.width}" height="34"> + <Text id="label" x="45" y="12" text="{model.label}" color="white" font.bold="true" width="{parent.width-30}" opacity="{listShown}"/> + <Item id="Details" anchors.fill="{wrapper}"> + <Bind target="{Details.qmlItem}" property="contactid" value="{model.recid}"/> + <Bind target="{Details.qmlItem}" property="mode" value="{wrapper.state}"/> + <Bind target="{Details.qmlItem}" property="label" value="{model.label}"/> + <Bind target="{Details.qmlItem}" property="phone" value="{model.phone}"/> + <Bind target="{Details.qmlItem}" property="email" value="{model.email}"/> + </Item> + <MouseRegion anchors.fill="{label}" opacity="{listShown}"> + <onClicked> + Details.qml = 'Contact.qml'; + wrapper.state='opened'; + </onClicked> + </MouseRegion> + <states> + <State name='opened'> + <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/> + <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/> + <SetProperty target="{contactListView}" property="locked" value="1"/> + <SetProperty target="{Details.qmlItem}" property="mode" value="opened"/> + <SetProperty target="{Page}" property="mode" value="editExisting"/> + </State> + </states> + <transitions> + <Transition> + <NumericAnimation duration="500" properties="yPosition,height,opacity"/> + </Transition> + </transitions> + <Connection sender="{confirmEditButton}" signal="clicked()"> + if (Details.qmlItem.mode == 'opened' && Page.mouseGrabbed != 'true') { + Details.qmlItem.mode = 'closed'; + wrapper.state = ""; + Details.qmlItem.confirm.emit(); + } + </Connection> + <Connection sender="{cancelEditButton}" signal="clicked()"> + if (Details.qmlItem.mode == 'opened' && Page.mouseGrabbed != 'true') { + Details.qmlItem.mode = 'closed'; + wrapper.state = ""; + Details.qmlItem.cancel.emit(); + } + </Connection> + </Item> + </Component> + </resources> + <Button id="newContactButton" icon="../shared/pics/new.png" + anchors.top="{parent.top}" anchors.topMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5" + onClicked="newContactItem.label = ''; newContactItem.phone = ''; newContactItem.email = ''; Page.mode = 'editNew'" + opacity="{Page.mode == 'list' ? 1 : 0}"/> + <Button id="cancelEditButton" icon="../shared/pics/cancel.png" + anchors.top="{parent.top}" anchors.topMargin="5" + anchors.right="{parent.right}" anchors.rightMargin="5" + opacity="{Page.mode == 'list' || Page.mouseGrabbed == 'true' ? 0 : 1}"/> + <Button id="confirmEditButton" icon="../shared/pics/ok.png" + anchors.top="{parent.top}" anchors.topMargin="5" + anchors.left="{parent.left}" anchors.leftMargin="5" + opacity="{Page.mode == 'list' || Page.mouseGrabbed == 'true' ? 0 : 1}"/> + <FocusRealm id="searchBarRealm" + height="30" + anchors.bottom="{parent.bottom}" + anchors.left="{parent.left}" anchors.right="{parent.right}" + focus="{Page.mode == 'list' ? 'true' : 'false'}"> + <SearchBar id="searchBar" anchors.fill="{parent}"> + <states> + <State name="searchHidden" when="{searchBar.text == '' || Page.listShown == 0}"> + <SetProperty target="{searchBarRealm}" property="anchors.bottomMargin" value="-30"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="*"> + <NumericAnimation property="bottomMargin" duration="250"/> + </Transition> + </transitions> + </SearchBar> + </FocusRealm> + <ListView id="contactListView" model="{contactList}" delegate="{contactDelegate}" + anchors.top="{newContactButton.bottom}" anchors.topMargin="10" + anchors.left="{parent.left}" anchors.right="{parent.right}" + anchors.bottom="{searchBarRealm.top}" + clip="true" + focus="{Page.mode == 'list' ? 'false' : 'true'}" + /> + <Contact id="newContactItem" + mode="opened" + anchors.top="{newContactButton.bottom}" anchors.topMargin="10" + anchors.left="{parent.left}" anchors.right="{parent.right}" + anchors.bottom="{searchBarRealm.top}" + onClose="Page.mode='list'" + opacity="0" + /> + <Connection sender="{confirmEditButton}" signal="clicked()"> + if (Page.mode == 'editNew' && Page.mouseGrabbed != 'true') { + newContactItem.confirm.emit() + } + </Connection> + <Connection sender="{cancelEditButton}" signal="clicked()"> + if (Page.mode == 'editNew' && Page.mouseGrabbed != 'true') { + newContactItem.cancel.emit() + } + </Connection> + <states> + <State name="editExistingState" when="{Page.mode == 'editExisting'}"> + <SetProperty target="{Page}" property="listShown" value="0"/> + </State> + <State name="editNewState" when="{Page.mode == 'editNew'}"> + <SetProperty target="{Page}" property="listShown" value="0"/> + <SetProperty target="{contactListView}" property="opacity" value="0"/> + <SetProperty target="{newContactItem}" property="opacity" value="1"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="*"> + <NumericAnimation property="opacity" duration="500"/> + </Transition> + </transitions> +</Rect> diff --git a/examples/declarative/tutorials/t1/tutorial1.qml b/examples/declarative/tutorials/t1/tutorial1.qml new file mode 100644 index 0000000..e4de571 --- /dev/null +++ b/examples/declarative/tutorials/t1/tutorial1.qml @@ -0,0 +1,3 @@ +<Rect id="Page" width="480" height="200" color="white"> + <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}"/> +</Rect> diff --git a/examples/declarative/tutorials/t2/Cell.qml b/examples/declarative/tutorials/t2/Cell.qml new file mode 100644 index 0000000..5d6ff52 --- /dev/null +++ b/examples/declarative/tutorials/t2/Cell.qml @@ -0,0 +1,7 @@ +<Item id="CellContainer" width="40" height="25"> + <properties> + <Property name="color"/> + </properties> + <Rect anchors.fill="{parent}" color="{CellContainer.color}"/> + <MouseRegion anchors.fill="{parent}" onClicked="HelloText.color = CellContainer.color" /> +</Item> diff --git a/examples/declarative/tutorials/t2/tutorial2.qml b/examples/declarative/tutorials/t2/tutorial2.qml new file mode 100644 index 0000000..1e3af16 --- /dev/null +++ b/examples/declarative/tutorials/t2/tutorial2.qml @@ -0,0 +1,11 @@ +<Rect id="Page" width="480" height="200" color="white"> + <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}"/> + <GridLayout id="ColorPicker" x="0" anchors.bottom="{Page.bottom}" width="120" height="50" columns="3" rows="2"> + <Cell color="#ff0000"/> + <Cell color="#00ff00"/> + <Cell color="#0000ff"/> + <Cell color="#ffff00"/> + <Cell color="#00ffff"/> + <Cell color="#ff00ff"/> + </GridLayout> +</Rect> diff --git a/examples/declarative/tutorials/t3/Cell.qml b/examples/declarative/tutorials/t3/Cell.qml new file mode 100644 index 0000000..5d6ff52 --- /dev/null +++ b/examples/declarative/tutorials/t3/Cell.qml @@ -0,0 +1,7 @@ +<Item id="CellContainer" width="40" height="25"> + <properties> + <Property name="color"/> + </properties> + <Rect anchors.fill="{parent}" color="{CellContainer.color}"/> + <MouseRegion anchors.fill="{parent}" onClicked="HelloText.color = CellContainer.color" /> +</Item> diff --git a/examples/declarative/tutorials/t3/tutorial3.qml b/examples/declarative/tutorials/t3/tutorial3.qml new file mode 100644 index 0000000..f9f1415 --- /dev/null +++ b/examples/declarative/tutorials/t3/tutorial3.qml @@ -0,0 +1,27 @@ +<Rect id="Page" width="480" height="200" color="white"> + <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}"> + <states> + <State name="down" when="{MouseRegion.pressed == true}"> + <SetProperty target="{HelloText}" property="y" value="160"/> + <SetProperty target="{HelloText}" property="color" value="red"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="down" reversible="true"> + <ParallelAnimation> + <NumericAnimation properties="y" duration="500" easing="easeOutBounce"/> + <ColorAnimation duration="500"/> + </ParallelAnimation> + </Transition> + </transitions> + </Text> + <MouseRegion id="MouseRegion" anchors.fill="{HelloText}"/> + <GridLayout id="ColorPicker" x="0" anchors.bottom="{Page.bottom}" width="120" height="50" columns="3" rows="2"> + <Cell color="#ff0000"/> + <Cell color="#00ff00"/> + <Cell color="#0000ff"/> + <Cell color="#ffff00"/> + <Cell color="#00ffff"/> + <Cell color="#ff00ff"/> + </GridLayout> +</Rect> diff --git a/examples/declarative/velocity/Day.qml b/examples/declarative/velocity/Day.qml new file mode 100644 index 0000000..3441648 --- /dev/null +++ b/examples/declarative/velocity/Day.qml @@ -0,0 +1,41 @@ +<Rect width="400" height="500" radius="7" pen.color="black" id="Page"> + <properties> + <Property name="day" type="string" /> + <Property name="stickies" /> + </properties> + + <Image x="10" y="10" src="cork.jpg" opaque="true"/> + <Text x="20" y="20" height="40" font.size="14" font.bold="true" width="370" text="{day}" style="Outline" styleColor="#dedede"/> + + <Repeater dataSource="{Page.stickies}"> + <Item x="{Math.random() * 200 + 100}" y="{Math.random() * 300 + 50}" id="StickyPage"> + <rotation> + <Follow source="{-Flick.xVelocity / 100}" spring="2.0" damping="0.1"/> + </rotation> + <Item id="Sticky" scale="0.5"> + <Image id="StickyImage" src="sticky.png" smooth="true" y="-20" x="{8 + -width * 0.6 / 2}" scale="0.6" /> + <TextEdit id="MyText" smooth="true" font.size="28" readOnly="false" x="-104" y="36" wrap="true" rotation="-8" text="{noteText}" width="195" height="172" /> + <Item y="-20" x="{StickyImage.x}" width="{StickyImage.width * StickyImage.scale}" height="{StickyImage.height * StickyImage.scale}" > + <MouseRegion id="Mouse" onClicked="MyText.focus = true" anchors.fill="{parent}" drag.target="{StickyPage}" drag.axis="xy" drag.ymin="0" drag.ymax="500" drag.xmin="0" drag.xmax="400"/> + </Item> + </Item> + <Image src="tack.png" x="{-width / 2}" y="{-height * 0.7 / 2}" scale="0.7" /> + + <states> + <State name="pressed" when="{Mouse.pressed}"> + <SetProperties target="{Sticky}" rotation="8" scale="1"/> + <SetProperties target="{Page}" z="8"/> + </State> + </states> + <transitions> + <Transition> + <NumericAnimation properties="rotation,scale" duration="200"/> + </Transition> + </transitions> + </Item> + </Repeater> + + + + +</Rect> diff --git a/examples/declarative/velocity/cork.jpg b/examples/declarative/velocity/cork.jpg Binary files differnew file mode 100644 index 0000000..d4d706c --- /dev/null +++ b/examples/declarative/velocity/cork.jpg diff --git a/examples/declarative/velocity/sticky.png b/examples/declarative/velocity/sticky.png Binary files differnew file mode 100644 index 0000000..73df3cd --- /dev/null +++ b/examples/declarative/velocity/sticky.png diff --git a/examples/declarative/velocity/tack.png b/examples/declarative/velocity/tack.png Binary files differnew file mode 100644 index 0000000..cef2d1c --- /dev/null +++ b/examples/declarative/velocity/tack.png diff --git a/examples/declarative/velocity/velocity.qml b/examples/declarative/velocity/velocity.qml new file mode 100644 index 0000000..0215d37 --- /dev/null +++ b/examples/declarative/velocity/velocity.qml @@ -0,0 +1,81 @@ +<Rect color="lightSteelBlue" width="800" height="600"> + <ListModel id="List"> + <Day> + <name>Sunday</name> + <dayColor>#808080</dayColor> + <notes> + <Note noteText="Lunch" /> + <Note noteText="Party" /> + </notes> + </Day> + <Day> + <name>Monday</name> + <dayColor>blue</dayColor> + <notes> + <Note noteText="Pickup kids" /> + <Note noteText="Checkout kinetic" /> + <Note noteText="Read email" /> + </notes> + </Day> + <Day> + <name>Tuesday</name> + <dayColor>yellow</dayColor> + <notes> + <Note noteText="Walk dog" /> + <Note noteText="Buy newspaper" /> + </notes> + </Day> + <Day> + <name>Wednesday</name> + <dayColor>purple</dayColor> + <notes> + <Note noteText="Cook dinner" /> + <Note noteText="Eat dinner" /> + </notes> + </Day> + <Day> + <name>Thursday</name> + <dayColor>blue</dayColor> + <notes> + <Note noteText="5:30pm Meeting" /> + <Note noteText="Weed garden" /> + </notes> + </Day> + <Day> + <name>Friday</name> + <dayColor>green</dayColor> + <notes> + <Note noteText="Still work" /> + <Note noteText="Drink" /> + </notes> + </Day> + <Day> + <name>Saturday</name> + <dayColor>orange</dayColor> + <notes> + <Note noteText="Drink" /> + <Note noteText="Drink" /> + </notes> + </Day> + </ListModel> + + <Flickable id="Flick" anchors.fill="{parent}" viewportWidth="{Lay.width}"> + <HorizontalLayout id="Lay"> + <Repeater dataSource="{List}"> + <Component> + <Day day="{name}" color="{dayColor}" stickies="{notes}"/> + </Component> + </Repeater> + <!-- + <Day color="#808080" day="Sunday" /> + <Day color="blue" day="Monday"/> + <Day color="yellow" day="Tuesday"/> + <Day color="purple" day="Wednesday"/> + <Day color="blue" day="Thursday"/> + <Day color="green" day="Friday"/> + <Day color="orange" day="Saturday"/> + --> + </HorizontalLayout> + </Flickable> + +</Rect> diff --git a/examples/declarative/webview/autosize.qml b/examples/declarative/webview/autosize.qml new file mode 100644 index 0000000..fedd497 --- /dev/null +++ b/examples/declarative/webview/autosize.qml @@ -0,0 +1,42 @@ +<!-- The WebView size is determined by the width, height, + idealWidth, and idealHeight properties. --> +<Rect id="Rect" color="white" width="200" height="{Layout.height}"> + <VerticalLayout id="Layout" spacing="2"> + <WebView> + <html><![CDATA[ + No width defined. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + <WebView width="{Rect.width}"> + <html><![CDATA[ + The width is full. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + <WebView width="{Rect.width/2}"> + <html><![CDATA[ + The width is half. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + <WebView idealWidth="{Rect.width/2}"> + <html><![CDATA[ + The idealWidth is half. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + <WebView idealWidth="{Rect.width/2}"> + <html><![CDATA[ + The_idealWidth_is_half. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + <WebView width="{Rect.width/2}"> + <html><![CDATA[ + The_width_is_half. + ]]></html> + <Rect color="#10000000" anchors.fill="{parent}"/> + </WebView> + </VerticalLayout> +</Rect> diff --git a/examples/declarative/webview/content/SpinSquare.qml b/examples/declarative/webview/content/SpinSquare.qml new file mode 100644 index 0000000..ced45d5 --- /dev/null +++ b/examples/declarative/webview/content/SpinSquare.qml @@ -0,0 +1,12 @@ +<Item id="Root"> + <properties> + <Property name="period" value="250"/> + <Property name="color" value="black"/> + </properties> + <Item x="{Root.width/2}" y="{Root.height/2}"> + <Rect color="{Root.color}" width="{Root.width}" height="{width}" x="{-width/2}" y="{-height/2}"/> + <rotation> + <NumericAnimation from="0" to="360" repeat="true" running="true" duration="{Root.period}"/> + </rotation> + </Item> +</Item> diff --git a/examples/declarative/webview/inline-html.qml b/examples/declarative/webview/inline-html.qml new file mode 100644 index 0000000..701db41 --- /dev/null +++ b/examples/declarative/webview/inline-html.qml @@ -0,0 +1,13 @@ +<!-- Inline HTML with loose formatting can be + set on the html property by using CDATA. --> +<WebView> + <html><![CDATA[ + <body bgcolor="white"> + <table border=1> + <tr><th><th>One<th>Two<th>Three + <tr><th>1<td>X<td>1<td>X + <tr><th>2<td>0<td>X<td>0 + <tr><th>3<td>X<td>1<td>X + </table> + ]]></html> +</WebView> diff --git a/examples/declarative/webview/inline-xhtml.qml b/examples/declarative/webview/inline-xhtml.qml new file mode 100644 index 0000000..4acb417 --- /dev/null +++ b/examples/declarative/webview/inline-xhtml.qml @@ -0,0 +1,14 @@ +<!-- Inline xHTML (with strict XML formatting) can be + set on the html property by giving it the appropriate namespace. --> +<WebView> + <html xmlns="http://www.w3.org/1999/xhtml"> + <body bgcolor="white"> + <table border="1"> + <tr><th></th><th>One</th><th>Two</th><th>Three</th></tr> + <tr><th>1</th><td>X</td><td>1</td><td>X</td></tr> + <tr><th>2</th><td>0</td><td>X</td><td>0</td></tr> + <tr><th>3</th><td>X</td><td>1</td><td>X</td></tr> + </table> + </body> + </html> +</WebView> diff --git a/examples/declarative/webview/qml-in-html.qml b/examples/declarative/webview/qml-in-html.qml new file mode 100644 index 0000000..2715788 --- /dev/null +++ b/examples/declarative/webview/qml-in-html.qml @@ -0,0 +1,20 @@ +<!-- The WebView supports QML data through the HTML OBJECT tag --> +<Flickable width="{250*.75}" height="240" + viewportWidth="{Web.width*Web.scale}" viewportHeight="{Web.height*Web.scale}"> +<WebView id="Web" width="250" height="420" scale="0.75"> + <html><![CDATA[ + <html> + <body bgcolor=white> + These are QML plugins, shown in a QML WebView via HTML OBJECT tags, all scaled to 75% + and placed in a Flickable area... + <table border=1> + <tr><th>Duration <th>Color <th>Plugin + <tr><td>500 <td>red <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=500 color=red /> + <tr><td>2000 <td>blue <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=2000 color=blue /> + <tr><td>1000 <td>green <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=1000 color=green /> + </table> + </body> + </html> + ]]></html> +</WebView> +</Flickable> diff --git a/examples/declarative/webview/transparent.qml b/examples/declarative/webview/transparent.qml new file mode 100644 index 0000000..71e1621 --- /dev/null +++ b/examples/declarative/webview/transparent.qml @@ -0,0 +1,6 @@ +<!-- The WebView background is transparent + if the HTML does not specify a background --> + +<Rect color="green" width="{Web.width}" height="{Web.height}"> + <WebView id="Web" html="Hello <b>World!</b>"/> +</Rect> diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml new file mode 100644 index 0000000..cfd0a98 --- /dev/null +++ b/examples/declarative/xmldata/daringfireball.qml @@ -0,0 +1,25 @@ +<Rect color="white" width="600" height="600"> + <resources> + <XmlListModel id="feedModel" src="http://daringfireball.net/index.xml" + query="doc($src)/feed/entry"> + <namespaceDeclarations> + declare default element namespace 'http://www.w3.org/2005/Atom'; + </namespaceDeclarations> + <Role name="title" query="title/string()"/> + <Role name="tagline" query="author/name/string()"/> + <Role name="content" query="content/string()" isCData="true"/> + </XmlListModel> + <Component id="feedDelegate"> + <Item height="{contents.height + 20}"> + <Text x="10" id="TitleText" text="{title}" font.bold="true"/> + <Text text="{'by ' + tagline}" anchors.left="{TitleText.right}" anchors.leftMargin="10" font.italic="true"/> + <Text x="10" text="{content}" anchors.top="{TitleText.bottom}" width="580" wrap="true"> + <onLinkActivated>print('link clicked: ' + link)</onLinkActivated> + </Text> + </Item> + </Component> + </resources> + + <ListView id="list" anchors.fill="{parent}" clip="true" + model="{feedModel}" delegate="{feedDelegate}"/> +</Rect> diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml new file mode 100644 index 0000000..80ace18 --- /dev/null +++ b/examples/declarative/xmldata/yahoonews.qml @@ -0,0 +1,38 @@ +<Rect color="black" gradientColor="#AAAAAA" width="600" height="600"> + <resources> + <XmlListModel id="feedModel" src="http://rss.news.yahoo.com/rss/oceania" query="doc($src)/rss/channel/item"> + <Role name="title" query="title/string()"/> + <Role name="link" query="link/string()"/> + <Role name="description" query="description/string()" isCData="true"/> + </XmlListModel> + <Component id="feedDelegate"> + <Item id="Delegate" height="{Wrapper.height + 10}"> + <MouseRegion anchors.fill="{Wrapper}" onPressed="Delegate.ListView.list.currentIndex = index;" + onClicked="if (Wrapper.state == 'Details') { Wrapper.state = '';} else {Wrapper.state = 'Details';}"/> + <Rect id="Wrapper" y="5" height="{TitleText.height + 10}" width="580" color="#F0F0F0" radius="5"> + <Text x="10" y="5" id="TitleText" text="{'<a href=\'' + link + '\'>' + title + '</a>'}" font.bold="true" font.family="Helvetica" font.size="14" onLinkActivated="print('link clicked: ' + link)"/> + <Text x="10" id="Description" text="{description}" width="560" wrap="true" font.family="Helvetica" + anchors.top="{TitleText.bottom}" anchors.topMargin="5" opacity="0"/> + + <states> + <State name="Details"> + <SetProperty target="{Wrapper}" property="height" binding="contents.height + 10"/> + <SetProperty target="{Description}" property="opacity" value="1"/> + </State> + </states> + <transitions> + <Transition fromState="*" toState="Details" reversible="true"> + <SequentialAnimation> + <NumericAnimation duration="200" properties="height" easing="easeOutQuad"/> + <NumericAnimation duration="200" properties="opacity"/> + </SequentialAnimation> + </Transition> + </transitions> + </Rect> + </Item> + </Component> + </resources> + + <ListView id="list" x="10" y="10" width="{parent.width - 20}" height="{parent.height - 20}" clip="true" + model="{feedModel}" delegate="{feedDelegate}" currentItemPositioning="Snap"/> +</Rect> diff --git a/examples/examples.pro b/examples/examples.pro index 2c4fc81..874cd37 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -14,16 +14,19 @@ SUBDIRS = \ qtconcurrent \ richtext \ sql \ + statemachine \ threads \ tools \ tutorials \ widgets \ uitools \ + declarative \ xml \ script contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon contains(QT_CONFIG, webkit): SUBDIRS += webkit +contains(QT_CONFIG, animation): SUBDIRS += animation embedded:SUBDIRS += qws !wince*: { !contains(QT_EDITION, Console):contains(QT_BUILD_PARTS, tools):SUBDIRS += designer diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp index 213c5b2..ee50670 100644 --- a/examples/opengl/hellogl_es2/glwidget.cpp +++ b/examples/opengl/hellogl_es2/glwidget.cpp @@ -48,124 +48,10 @@ const int bubbleNum = 8; -inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2) -{ - xOut = y1 * z2 - z1 * y2; - yOut = z1 * x2 - x1 * z2; - zOut = x1 * y2 - y1 * x2; -} - -inline void Normalize(qreal &x, qreal &y, qreal &z) -{ - qreal l = sqrt(x*x + y*y + z*z); - x = x / l; - y = y / l; - z = z / l; -} - -inline void IdentityMatrix(GLfloat *m) -{ - m[0 * 4 + 0] = 1.0f; - m[1 * 4 + 0] = 0.0f; - m[2 * 4 + 0] = 0.0f; - m[3 * 4 + 0] = 0.0f; - m[0 * 4 + 1] = 0.0f; - m[1 * 4 + 1] = 1.0f; - m[2 * 4 + 1] = 0.0f; - m[3 * 4 + 1] = 0.0f; - m[0 * 4 + 2] = 0.0f; - m[1 * 4 + 2] = 0.0f; - m[2 * 4 + 2] = 1.0f; - m[3 * 4 + 2] = 0.0f; - m[0 * 4 + 3] = 0.0f; - m[1 * 4 + 3] = 0.0f; - m[2 * 4 + 3] = 0.0f; - m[3 * 4 + 3] = 1.0f; -} - -// Adjust a 4x4 matrix to apply a scale. -inline void ScaleMatrix(GLfloat *m, GLfloat scalex, GLfloat scaley, GLfloat scalez) -{ - m[0 * 4 + 0] *= scalex; - m[0 * 4 + 1] *= scalex; - m[0 * 4 + 2] *= scalex; - m[0 * 4 + 3] *= scalex; - m[1 * 4 + 0] *= scaley; - m[1 * 4 + 1] *= scaley; - m[1 * 4 + 2] *= scaley; - m[1 * 4 + 3] *= scaley; - m[2 * 4 + 0] *= scalez; - m[2 * 4 + 1] *= scalez; - m[2 * 4 + 2] *= scalez; - m[2 * 4 + 3] *= scalez; -} - -// Adjust a 4x4 matrix to apply a translation. -inline void TranslateMatrix(GLfloat *m, GLfloat translatex, GLfloat translatey, GLfloat translatez) -{ - m[3 * 4 + 0] += m[0 * 4 + 0] * translatex + m[1 * 4 + 0] * translatey + m[2 * 4 + 0] * translatez; - m[3 * 4 + 1] += m[0 * 4 + 1] * translatex + m[1 * 4 + 1] * translatey + m[2 * 4 + 1] * translatez; - m[3 * 4 + 2] += m[0 * 4 + 2] * translatex + m[1 * 4 + 2] * translatey + m[2 * 4 + 2] * translatez; - m[3 * 4 + 3] += m[0 * 4 + 3] * translatex + m[1 * 4 + 3] * translatey + m[2 * 4 + 3] * translatez; -} - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -// Adjust a 4x4 matrix to apply a rotation. -inline void RotateMatrix(GLfloat *m, GLfloat angle, GLfloat vx, GLfloat vy, GLfloat vz) -{ - GLfloat len = sqrt(vx * vx + vy * vy + vz * vz); - if (len != 0) { - vx /= len; - vy /= len; - vz /= len; - } - - GLfloat c, s, ic; - c = cos(angle * M_PI / 180.0); - s = sin(angle * M_PI / 180.0); - ic = 1.0f - c; - - GLfloat rot[16]; - rot[0 * 4 + 0] = vx * vx * ic + c; - rot[1 * 4 + 0] = vx * vy * ic - vz * s; - rot[2 * 4 + 0] = vx * vz * ic + vy * s; - rot[3 * 4 + 0] = 0.0f; - rot[0 * 4 + 1] = vy * vx * ic + vz * s; - rot[1 * 4 + 1] = vy * vy * ic + c; - rot[2 * 4 + 1] = vy * vz * ic - vx * s; - rot[3 * 4 + 1] = 0.0f; - rot[0 * 4 + 2] = vx * vz * ic - vy * s; - rot[1 * 4 + 2] = vy * vz * ic + vx * s; - rot[2 * 4 + 2] = vz * vz * ic + c; - rot[3 * 4 + 2] = 0.0f; - rot[0 * 4 + 3] = 0.0f; - rot[1 * 4 + 3] = 0.0f; - rot[2 * 4 + 3] = 0.0f; - rot[3 * 4 + 3] = 1.0f; - - GLfloat temp[16]; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - temp[j * 4 + i] = 0.0f; - for (int k = 0; k < 4; ++k) { - temp[j * 4 + i] += m[k * 4 + i] * rot[j * 4 + k]; - } - } - } - - qMemCopy(m, temp, sizeof(temp)); -} - GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) { qtLogo = true; - createdVertices = 0; - createdNormals = 0; - m_vertexNumber = 0; frames = 0; setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_NoSystemBackground); @@ -178,10 +64,6 @@ GLWidget::GLWidget(QWidget *parent) GLWidget::~GLWidget() { - if (createdVertices) - delete[] createdVertices; - if (createdNormals) - delete[] createdNormals; } void GLWidget::setScaling(int scale) { @@ -210,13 +92,11 @@ void GLWidget::showBubbles(bool bubbles) void GLWidget::paintQtLogo() { glDisable(GL_TEXTURE_2D); - glVertexAttribPointer(vertexAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdVertices); - glEnableVertexAttribArray(vertexAttr1); - glVertexAttribPointer(normalAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdNormals); - glEnableVertexAttribArray(normalAttr1); - glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3); - glDisableVertexAttribArray(normalAttr1); - glDisableVertexAttribArray(vertexAttr1); + program1.setAttributeArray(vertexAttr1, vertices.constData()); + program1.setAttributeArray(normalAttr1, normals.constData()); + glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + program1.disableAttributeArray(normalAttr1); + program1.disableAttributeArray(vertexAttr1); } void GLWidget::paintTexturedCube() @@ -239,8 +119,7 @@ void GLWidget::paintTexturedCube() -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5 }; - glVertexAttribPointer(vertexAttr2, 3, GL_FLOAT, GL_FALSE, 0, afVertices); - glEnableVertexAttribArray(vertexAttr2); + program2.setAttributeArray(vertexAttr2, afVertices, 3); GLfloat afTexCoord[] = { 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f, @@ -258,8 +137,7 @@ void GLWidget::paintTexturedCube() 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f }; - glVertexAttribPointer(texCoordAttr2, 2, GL_FLOAT, GL_FALSE, 0, afTexCoord); - glEnableVertexAttribArray(texCoordAttr2); + program2.setAttributeArray(texCoordAttr2, afTexCoord, 2); GLfloat afNormals[] = { @@ -278,50 +156,15 @@ void GLWidget::paintTexturedCube() 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0 }; - glVertexAttribPointer(normalAttr2, 3, GL_FLOAT, GL_FALSE, 0, afNormals); - glEnableVertexAttribArray(normalAttr2); + program2.setAttributeArray(normalAttr2, afNormals, 3); - glUniform1i(textureUniform2, 0); // use texture unit 0 + program2.setUniformValue(textureUniform2, 0); // use texture unit 0 glDrawArrays(GL_TRIANGLES, 0, 36); - glDisableVertexAttribArray(vertexAttr2); - glDisableVertexAttribArray(normalAttr2); - glDisableVertexAttribArray(texCoordAttr2); -} - -static void reportCompileErrors(GLuint shader, const char *src) -{ - GLint value = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &value); - bool compiled = (value != 0); - value = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value); - if (!compiled && value > 1) { - char *log = new char [value]; - GLint len; - glGetShaderInfoLog(shader, value, &len, log); - qWarning("%s\n", log); - qWarning("when compiling:\n%s\n", src); - delete [] log; - } -} - -static void reportLinkErrors(GLuint program, const char *vsrc, const char *fsrc) -{ - GLint value = 0; - glGetProgramiv(program, GL_LINK_STATUS, &value); - bool linked = (value != 0); - value = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value); - if (!linked && value > 1) { - char *log = new char [value]; - GLint len; - glGetProgramInfoLog(program, value, &len, log); - qWarning("%s\n", log); - qWarning("when linking:\n%s\nwith:\n%s\n", vsrc, fsrc); - delete [] log; - } + program2.disableAttributeArray(vertexAttr2); + program2.disableAttributeArray(normalAttr2); + program2.disableAttributeArray(texCoordAttr2); } void GLWidget::initializeGL () @@ -332,8 +175,8 @@ void GLWidget::initializeGL () glGenTextures(1, &m_uiTexture); m_uiTexture = bindTexture(QImage(":/qt.png")); - GLuint vshader1 = glCreateShader(GL_VERTEX_SHADER); - const char *vsrc1[1] = { + QGLShader *vshader1 = new QGLShader(QGLShader::VertexShader, this); + const char *vsrc1 = "attribute highp vec4 vertex;\n" "attribute mediump vec3 normal;\n" "uniform mediump mat4 matrix;\n" @@ -346,36 +189,28 @@ void GLWidget::initializeGL () " color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n" " color = clamp(color, 0.0, 1.0);\n" " gl_Position = matrix * vertex;\n" - "}\n" - }; - glShaderSource(vshader1, 1, vsrc1, 0); - glCompileShader(vshader1); - reportCompileErrors(vshader1, vsrc1[0]); + "}\n"; + vshader1->setSourceCode(vsrc1); - GLuint fshader1 = glCreateShader(GL_FRAGMENT_SHADER); - const char *fsrc1[1] = { + QGLShader *fshader1 = new QGLShader(QGLShader::FragmentShader, this); + const char *fsrc1 = "varying mediump vec4 color;\n" "void main(void)\n" "{\n" " gl_FragColor = color;\n" - "}\n" - }; - glShaderSource(fshader1, 1, fsrc1, 0); - glCompileShader(fshader1); - reportCompileErrors(fshader1, fsrc1[0]); - - program1 = glCreateProgram(); - glAttachShader(program1, vshader1); - glAttachShader(program1, fshader1); - glLinkProgram(program1); - reportLinkErrors(program1, vsrc1[0], fsrc1[0]); - - vertexAttr1 = glGetAttribLocation(program1, "vertex"); - normalAttr1 = glGetAttribLocation(program1, "normal"); - matrixUniform1 = glGetUniformLocation(program1, "matrix"); - - GLuint vshader2 = glCreateShader(GL_VERTEX_SHADER); - const char *vsrc2[1] = { + "}\n"; + fshader1->setSourceCode(fsrc1); + + program1.addShader(vshader1); + program1.addShader(fshader1); + program1.link(); + + vertexAttr1 = program1.attributeLocation("vertex"); + normalAttr1 = program1.attributeLocation("normal"); + matrixUniform1 = program1.uniformLocation("matrix"); + + QGLShader *vshader2 = new QGLShader(QGLShader::VertexShader); + const char *vsrc2 = "attribute highp vec4 vertex;\n" "attribute highp vec4 texCoord;\n" "attribute mediump vec3 normal;\n" @@ -388,14 +223,11 @@ void GLWidget::initializeGL () " angle = max(dot(normal, toLight), 0.0);\n" " gl_Position = matrix * vertex;\n" " texc = texCoord;\n" - "}\n" - }; - glShaderSource(vshader2, 1, vsrc2, 0); - glCompileShader(vshader2); - reportCompileErrors(vshader2, vsrc2[0]); + "}\n"; + vshader2->setSourceCode(vsrc2); - GLuint fshader2 = glCreateShader(GL_FRAGMENT_SHADER); - const char *fsrc2[1] = { + QGLShader *fshader2 = new QGLShader(QGLShader::FragmentShader); + const char *fsrc2 = "varying highp vec4 texc;\n" "uniform sampler2D tex;\n" "varying mediump float angle;\n" @@ -404,23 +236,18 @@ void GLWidget::initializeGL () " highp vec3 color = texture2D(tex, texc.st).rgb;\n" " color = color * 0.2 + color * 0.8 * angle;\n" " gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n" - "}\n" - }; - glShaderSource(fshader2, 1, fsrc2, 0); - glCompileShader(fshader2); - reportCompileErrors(fshader2, fsrc2[0]); - - program2 = glCreateProgram(); - glAttachShader(program2, vshader2); - glAttachShader(program2, fshader2); - glLinkProgram(program2); - reportLinkErrors(program2, vsrc2[0], fsrc2[0]); - - vertexAttr2 = glGetAttribLocation(program2, "vertex"); - normalAttr2 = glGetAttribLocation(program2, "normal"); - texCoordAttr2 = glGetAttribLocation(program2, "texCoord"); - matrixUniform2 = glGetUniformLocation(program2, "matrix"); - textureUniform2 = glGetUniformLocation(program2, "tex"); + "}\n"; + fshader2->setSourceCode(fsrc2); + + program2.addShader(vshader2); + program2.addShader(fshader2); + program2.link(); + + vertexAttr2 = program2.attributeLocation("vertex"); + normalAttr2 = program2.attributeLocation("normal"); + texCoordAttr2 = program2.attributeLocation("texCoord"); + matrixUniform2 = program2.uniformLocation("matrix"); + textureUniform2 = program2.uniformLocation("tex"); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -450,24 +277,23 @@ void GLWidget::paintGL() glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - GLfloat modelview[16]; - IdentityMatrix(modelview); - RotateMatrix(modelview, m_fAngle, 0.0, 1.0, 0.0); - RotateMatrix(modelview, m_fAngle, 1.0, 0.0, 0.0); - RotateMatrix(modelview, m_fAngle, 0.0, 0.0, 1.0); - ScaleMatrix(modelview, m_fScale, m_fScale, m_fScale); - TranslateMatrix(modelview, 0, -0.2, 0); + QMatrix4x4 modelview; + modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f); + modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f); + modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f); + modelview.scale(m_fScale); + modelview.translate(0.0f, -0.2f, 0.0f); if (qtLogo) { - glUseProgram(program1); - glUniformMatrix4fv(matrixUniform1, 1, GL_FALSE, modelview); + program1.enable(); + program1.setUniformValue(matrixUniform1, modelview); paintQtLogo(); - glUseProgram(0); + program1.disable(); } else { - glUseProgram(program2); - glUniformMatrix4fv(matrixUniform2, 1, GL_FALSE, modelview); + program2.enable(); + program1.setUniformValue(matrixUniform2, modelview); paintTexturedCube(); - glUseProgram(0); + program2.disable(); } glDisable(GL_DEPTH_TEST); @@ -563,80 +389,69 @@ void GLWidget::createGeometry() extrude(x8, y8, x5, y5); } - m_vertexNumber = vertices.size(); - createdVertices = new GLfloat[m_vertexNumber]; - createdNormals = new GLfloat[m_vertexNumber]; - for (int i = 0;i < m_vertexNumber;i++) { - createdVertices[i] = vertices.at(i) * 2; - createdNormals[i] = normals.at(i); - } - vertices.clear(); - normals.clear(); + for (int i = 0;i < vertices.size();i++) + vertices[i] *= 2.0f; } void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4) { - qreal nx, ny, nz; + vertices << QVector3D(x1, y1, -0.05f); + vertices << QVector3D(x2, y2, -0.05f); + vertices << QVector3D(x4, y4, -0.05f); - vertices << x1 << y1 << -0.05f; - vertices << x2 << y2 << -0.05f; - vertices << x4 << y4 << -0.05f; + vertices << QVector3D(x3, y3, -0.05f); + vertices << QVector3D(x4, y4, -0.05f); + vertices << QVector3D(x2, y2, -0.05f); - vertices << x3 << y3 << -0.05f; - vertices << x4 << y4 << -0.05f; - vertices << x2 << y2 << -0.05f; + QVector3D n = QVector3D::normal + (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f)); - CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0, x4 - x1, y4 - y1, 0); - Normalize(nx, ny, nz); + normals << n; + normals << n; + normals << n; - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; + normals << n; + normals << n; + normals << n; - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; + vertices << QVector3D(x4, y4, 0.05f); + vertices << QVector3D(x2, y2, 0.05f); + vertices << QVector3D(x1, y1, 0.05f); - vertices << x4 << y4 << 0.05f; - vertices << x2 << y2 << 0.05f; - vertices << x1 << y1 << 0.05f; + vertices << QVector3D(x2, y2, 0.05f); + vertices << QVector3D(x4, y4, 0.05f); + vertices << QVector3D(x3, y3, 0.05f); - vertices << x2 << y2 << 0.05f; - vertices << x4 << y4 << 0.05f; - vertices << x3 << y3 << 0.05f; + n = QVector3D::normal + (QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f)); - CrossProduct(nx, ny, nz, x2 - x4, y2 - y4, 0, x1 - x4, y1 - y4, 0); - Normalize(nx, ny, nz); + normals << n; + normals << n; + normals << n; - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; - - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; + normals << n; + normals << n; + normals << n; } void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2) { - qreal nx, ny, nz; - - vertices << x1 << y1 << +0.05f; - vertices << x2 << y2 << +0.05f; - vertices << x1 << y1 << -0.05f; + vertices << QVector3D(x1, y1, +0.05f); + vertices << QVector3D(x2, y2, +0.05f); + vertices << QVector3D(x1, y1, -0.05f); - vertices << x2 << y2 << -0.05f; - vertices << x1 << y1 << -0.05f; - vertices << x2 << y2 << +0.05f; + vertices << QVector3D(x2, y2, -0.05f); + vertices << QVector3D(x1, y1, -0.05f); + vertices << QVector3D(x2, y2, +0.05f); - CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0.0f, 0.0f, 0.0f, -0.1f); - Normalize(nx, ny, nz); + QVector3D n = QVector3D::normal + (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f)); - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; + normals << n; + normals << n; + normals << n; - normals << nx << ny << nz; - normals << nx << ny << nz; - normals << nx << ny << nz; + normals << n; + normals << n; + normals << n; } diff --git a/examples/opengl/hellogl_es2/glwidget.h b/examples/opengl/hellogl_es2/glwidget.h index 9a7823a..596e1cc 100644 --- a/examples/opengl/hellogl_es2/glwidget.h +++ b/examples/opengl/hellogl_es2/glwidget.h @@ -43,7 +43,11 @@ #define GLWIDGET_H #include <QGLWidget> +#include <QtGui/qvector3d.h> +#include <QtGui/qmatrix4x4.h> +#include <QtOpenGL/qglshaderprogram.h> #include <QTime> +#include <QVector> class Bubble; class GLWidget : public QGLWidget { @@ -71,24 +75,21 @@ private: void createBubbles(int number); void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4); void extrude(qreal x1, qreal y1, qreal x2, qreal y2); - QList<qreal> vertices; - QList<qreal> normals; - GLfloat *createdVertices; - GLfloat *createdNormals; - int m_vertexNumber; + QVector<QVector3D> vertices; + QVector<QVector3D> normals; bool qtLogo; QList<Bubble*> bubbles; int frames; QTime time; - GLuint program1; - GLuint program2; - GLuint vertexAttr1; - GLuint normalAttr1; - GLuint matrixUniform1; - GLuint vertexAttr2; - GLuint normalAttr2; - GLuint texCoordAttr2; - GLuint matrixUniform2; - GLuint textureUniform2; + QGLShaderProgram program1; + QGLShaderProgram program2; + int vertexAttr1; + int normalAttr1; + int matrixUniform1; + int vertexAttr2; + int normalAttr2; + int texCoordAttr2; + int matrixUniform2; + int textureUniform2; }; #endif diff --git a/examples/statemachine/README b/examples/statemachine/README new file mode 100644 index 0000000..2879e67 --- /dev/null +++ b/examples/statemachine/README @@ -0,0 +1,36 @@ +Qt is provided with a powerful hierchical finite state machine through +the Qt State Machine classes. + +The example launcher provided with Qt can be used to explore each of the +examples in this directory. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/statemachine/citizenquartz/citizenquartz.pro b/examples/statemachine/citizenquartz/citizenquartz.pro new file mode 100644 index 0000000..58039a0 --- /dev/null +++ b/examples/statemachine/citizenquartz/citizenquartz.pro @@ -0,0 +1,20 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + clock.cpp \ + clockbutton.cpp \ + clockdisplay.cpp \ + propertyaddstate.cpp \ + +HEADERS += clock.h \ + clockbutton.h \ + clockdisplay.h \ + propertyaddstate.h \ + timeperiod.h \ + +RESOURCES += citizenquartz.qrc +CONFIG += console diff --git a/examples/statemachine/citizenquartz/citizenquartz.qrc b/examples/statemachine/citizenquartz/citizenquartz.qrc new file mode 100644 index 0000000..bcc675a --- /dev/null +++ b/examples/statemachine/citizenquartz/citizenquartz.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>sound/alarm.wav</file> +</qresource> +</RCC>
\ No newline at end of file diff --git a/examples/statemachine/citizenquartz/clock.cpp b/examples/statemachine/citizenquartz/clock.cpp new file mode 100644 index 0000000..51180f5 --- /dev/null +++ b/examples/statemachine/citizenquartz/clock.cpp @@ -0,0 +1,382 @@ +#include "clock.h" +#include "clockbutton.h" +#include "clockdisplay.h" +#include "propertyaddstate.h" +#include "timeperiod.h" + +#include <QStateMachine> +#include <QState> +#include <QHistoryState> + +#include <QPainter> +#include <QTimer> +#include <QSound> + +Clock::Clock(QGraphicsItem *parent) + : QGraphicsItem(parent), + m_stateMachine(0), + m_clockDisplay(0), + m_buttonA(0), + m_buttonB(0), + m_buttonC(0), + m_buttonD(0), + m_alarmState(0), + m_timeState(0), + m_updateState(0), + m_regularState(0), + m_alarmSound(new QSound(":/sound/alarm.wav", this)) +{ +} + +void Clock::initializeUi() +{ + QPainterPath path = shape(); + QPointF pap; + qreal aap; + + m_buttonA = new ClockButton("Button A", this); + pap = path.pointAtPercent(0.05); + aap = path.angleAtPercent(0.05); + m_buttonA->translate(pap.x(), pap.y()); + m_buttonA->rotate(-aap); + connect(m_buttonA, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed())); + + m_buttonB = new ClockButton("Button B", this); + pap = path.pointAtPercent(0.77); + aap = path.angleAtPercent(0.77); + m_buttonB->translate(pap.x(), pap.y()); + m_buttonB->rotate(-aap); + connect(m_buttonB, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed())); + + m_buttonC = new ClockButton("Button C", this); + pap = path.pointAtPercent(0.67); + aap = path.angleAtPercent(0.67); + m_buttonC->translate(pap.x(), pap.y()); + m_buttonC->rotate(-aap); + connect(m_buttonC, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed())); + + m_buttonD = new ClockButton("Button D", this); + pap = path.pointAtPercent(0.57); + aap = path.angleAtPercent(0.57); + m_buttonD->translate(pap.x(), pap.y()); + m_buttonD->rotate(-aap); + connect(m_buttonD, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed())); + + QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(this); + label->setText("CITIZEN"); + label->setPos(0.0 - label->boundingRect().width() / 2.0, -100.0); + + m_clockDisplay = new ClockDisplay(this); + m_clockDisplay->setCurrentTime(QDateTime::currentDateTime()); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(updateTime())); + timer->setInterval(1); + timer->start(); + m_time.start(); +} + +void Clock::initializeStateMachine() +{ + m_stateMachine = new QStateMachine; + + QState *displays = new QState(m_stateMachine->rootState()); + displays->setObjectName("displays"); + initializeDisplaysState(displays); + + /*QState *alarmsBeep = new QState(m_stateMachine->rootState()); + alarmsBeep->setObjectName("alarmsBeep"); + initializeAlarmsBeepState(alarmsBeep);*/ + + m_stateMachine->setInitialState(displays); + m_stateMachine->start(); +} + +void Clock::initializeUpdateState(QState *updateState) +{ + QState *sec = new QState(updateState); + sec->setObjectName("sec"); + sec->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditSecondMode); + updateState->setInitialState(sec); + + PropertyAddState *secIncrease = new PropertyAddState(updateState); + secIncrease->setObjectName("sec ++"); + secIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setSeconds(1)); + sec->addTransition(m_buttonD, SIGNAL(pressed()), secIncrease); + secIncrease->addTransition(sec); + + QState *oneMin = new QState(updateState); + oneMin->setObjectName("1 min"); + oneMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMinuteMode); + sec->addTransition(m_buttonC, SIGNAL(pressed()), oneMin); + + PropertyAddState *oneMinIncrease = new PropertyAddState(updateState); + oneMinIncrease->setObjectName("1 min ++"); + oneMinIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setMinutes(1)); + oneMin->addTransition(m_buttonD, SIGNAL(pressed()), oneMinIncrease); + oneMinIncrease->addTransition(oneMin); + + QState *tenMin = new QState(updateState); + tenMin->setObjectName("10 min"); + tenMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMinuteMode); + oneMin->addTransition(m_buttonC, SIGNAL(pressed()), tenMin); + + PropertyAddState *tenMinIncrease = new PropertyAddState(updateState); + tenMinIncrease->setObjectName("10 min ++"); + tenMinIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setMinutes(10)); + tenMin->addTransition(m_buttonD, SIGNAL(pressed()), tenMinIncrease); + tenMinIncrease->addTransition(tenMin); + + QState *hr = new QState(updateState); + hr->setObjectName("hr"); + hr->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditHourMode); + tenMin->addTransition(m_buttonC, SIGNAL(pressed()), hr); + + PropertyAddState *hrIncrease = new PropertyAddState(updateState); + hrIncrease->setObjectName("hr ++"); + hrIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setHours(1)); + hr->addTransition(m_buttonD, SIGNAL(pressed()), hrIncrease); + hrIncrease->addTransition(hr); + + QState *mon = new QState(updateState); + mon->setObjectName("mon"); + mon->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMonthMode); + hr->addTransition(m_buttonC, SIGNAL(pressed()), mon); + + PropertyAddState *monIncrease = new PropertyAddState(updateState); + monIncrease->setObjectName("mon ++"); + monIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setMonths(1)); + mon->addTransition(m_buttonD, SIGNAL(pressed()), monIncrease); + monIncrease->addTransition(mon); + + QState *day = new QState(updateState); + day->setObjectName("day"); + day->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditDayMode); + mon->addTransition(m_buttonC, SIGNAL(pressed()), day); + + PropertyAddState *dayIncrease = new PropertyAddState(updateState); + dayIncrease->setObjectName("day ++"); + dayIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setDays(1)); + day->addTransition(m_buttonD, SIGNAL(pressed()), dayIncrease); + dayIncrease->addTransition(day); + + QState *year = new QState(updateState); + year->setObjectName("year"); + year->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditYearMode); + day->addTransition(m_buttonC, SIGNAL(pressed()), year); + + PropertyAddState *yearIncrease = new PropertyAddState(updateState); + yearIncrease->setObjectName("year ++"); + yearIncrease->addToProperty(m_clockDisplay, "currentTime", + TimePeriod().setYears(1)); + year->addTransition(m_buttonD, SIGNAL(pressed()), yearIncrease); + yearIncrease->addTransition(year); + year->addTransition(m_buttonC, SIGNAL(pressed()), m_timeState); +} + +void Clock::initializeRegularState(QState *regular) +{ + m_timeState = new QState(regular); + m_timeState->setObjectName("time"); + m_timeState->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::CurrentTimeMode); + + QState *date = new QState(regular); + date->setObjectName("date"); + date->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::CurrentDateMode); + + QState *dateTimerState = new QState(date); + dateTimerState->setObjectName("dateTimerState"); + + // Date state exits after 2 m + QTimer *dateTimer = new QTimer(dateTimerState); + dateTimer->setSingleShot(true); + dateTimer->setInterval(2*60000); + dateTimerState->invokeMethodOnEntry(dateTimer, "start"); + dateTimerState->invokeMethodOnExit(dateTimer, "stop"); + + date->setInitialState(dateTimerState); + + m_updateState = new QState(regular); + m_updateState->setObjectName("update"); + + // Update state exits after 2 m + QTimer *updateTimer = new QTimer(m_updateState); + updateTimer->setSingleShot(true); + updateTimer->setInterval(2 * 60000); + m_updateState->invokeMethodOnEntry(updateTimer, "start"); + m_updateState->invokeMethodOnExit(updateTimer, "stop"); + + initializeUpdateState(m_updateState); + + m_timeState->addTransition(m_buttonD, SIGNAL(pressed()), date); + date->addTransition(m_buttonD, SIGNAL(pressed()), m_timeState); + date->addTransition(dateTimer, SIGNAL(timeout()), m_timeState); + + m_updateState->addTransition(updateTimer, SIGNAL(timeout()), m_timeState); + m_updateState->addTransition(m_buttonB, SIGNAL(pressed()), m_timeState); + + regular->setInitialState(m_timeState); +} + +void Clock::initializeAlarmUpdateState(QState *update) +{ + QState *hr = new QState(update); + hr->setObjectName("hr"); + hr->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmHourMode); + + PropertyAddState *hrInc = new PropertyAddState(update); + hrInc->setObjectName("hr ++"); + hrInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setHours(1)); + hr->addTransition(m_buttonD, SIGNAL(pressed()), hrInc); + hrInc->addTransition(hr); + + QState *tenMin = new QState(update); + tenMin->setObjectName("10 min"); + tenMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmTenMinuteMode); + hr->addTransition(m_buttonC, SIGNAL(pressed()), tenMin); + + PropertyAddState *tenMinInc = new PropertyAddState(update); + tenMinInc->setObjectName("10 min ++"); + tenMinInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setMinutes(10)); + tenMin->addTransition(m_buttonD, SIGNAL(pressed()), tenMinInc); + tenMinInc->addTransition(tenMin); + + QState *oneMin = new QState(update); + oneMin->setObjectName("1 min"); + oneMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmMinuteMode); + tenMin->addTransition(m_buttonC, SIGNAL(pressed()), oneMin); + + PropertyAddState *oneMinInc = new PropertyAddState(update); + oneMinInc->setObjectName("1 min ++"); + oneMinInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setMinutes(1)); + oneMin->addTransition(m_buttonD, SIGNAL(pressed()), oneMinInc); + oneMinInc->addTransition(oneMin); + + oneMin->addTransition(m_buttonC, SIGNAL(pressed()), m_alarmState); + m_alarmState->addTransition(m_buttonC, SIGNAL(pressed()), hr); +} + +void Clock::initializeOutState(QState *out) +{ + m_alarmState = new QState(out); + m_alarmState->setObjectName("alarmState"); + m_alarmState->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::AlarmMode); + initializeAlarmState(m_alarmState); + out->setInitialState(m_alarmState); + + QState *alarmUpdate = new QState(out); + alarmUpdate->setObjectName("alarmUpdate"); + initializeAlarmUpdateState(alarmUpdate); + + alarmUpdate->addTransition(m_buttonB, SIGNAL(pressed()), m_alarmState); + m_alarmState->addTransition(m_buttonA, SIGNAL(pressed()), m_regularState); +} + +void Clock::initializeDisplaysState(QState *displays) +{ + m_regularState = new QState(displays); + m_regularState->setObjectName("regular"); + initializeRegularState(m_regularState); + displays->setInitialState(m_regularState); + + QState *out = new QState(displays); + out->setObjectName("out"); + + QTimer *outTimer = new QTimer(out); + outTimer->setSingleShot(true); + outTimer->setInterval(2 * 60000); + out->invokeMethodOnEntry(outTimer, "start"); + out->invokeMethodOnExit(outTimer, "stop"); + + initializeOutState(out); + + QState *wait = new QState(displays); + wait->setObjectName("wait"); + + QTimer *waitTimer = new QTimer(wait); + waitTimer->setSingleShot(true); + waitTimer->setInterval(2000); + wait->invokeMethodOnEntry(waitTimer, "start"); + wait->invokeMethodOnExit(waitTimer, "stop"); + + m_timeState->addTransition(m_buttonC, SIGNAL(pressed()), wait); + wait->addTransition(waitTimer, SIGNAL(timeout()), m_updateState); + wait->addTransition(m_buttonC, SIGNAL(released()), m_timeState); + m_timeState->addTransition(m_buttonA, SIGNAL(pressed()), m_alarmState); + out->addTransition(outTimer, SIGNAL(timeout()), m_regularState); +} + +void Clock::initializeAlarmState(QState *alarmState) +{ + QState *offState = new QState(alarmState); + offState->setObjectName("alarmOff"); + offState->setPropertyOnEntry(m_clockDisplay, "alarmEnabled", false); + + QState *onState = new QState(alarmState); + onState->setObjectName("alarmOn"); + onState->setPropertyOnEntry(m_clockDisplay, "alarmEnabled", true); + + QHistoryState *history = alarmState->addHistoryState(); + history->setObjectName("alarmHistory"); + history->setDefaultState(onState); + + offState->addTransition(m_buttonD, SIGNAL(pressed()), onState); + onState->addTransition(m_buttonD, SIGNAL(pressed()), offState); + + QState *intermediate = new QState(alarmState); + intermediate->addTransition(history); + + alarmState->setInitialState(intermediate); +} + +QRectF Clock::boundingRect() const +{ + return shape().boundingRect(); +} + +QPainterPath Clock::shape() const +{ + QPainterPath path; + path.addRoundedRect(QRectF(-140.0, -100.0, 280.0, 200.0), 50.0, 50.0, Qt::RelativeSize); + + return path; +} + +void Clock::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setPen(Qt::black); + painter->setBrush(Qt::NoBrush); + + // Clock face + painter->drawPath(shape()); +} + +void Clock::updateTime() +{ + int elapsed = m_time.elapsed(); + if (elapsed > 0) { + m_time.restart(); + QDateTime currentTime = m_clockDisplay->currentTime(); + m_clockDisplay->setCurrentTime(currentTime.addMSecs(elapsed)); + + update(); + } +} + +void Clock::playSound() +{ + m_alarmSound->stop(); + m_alarmSound->play(); +} + +void Clock::stopSound() +{ + m_alarmSound->stop(); +} + diff --git a/examples/statemachine/citizenquartz/clock.h b/examples/statemachine/citizenquartz/clock.h new file mode 100644 index 0000000..aee1b55 --- /dev/null +++ b/examples/statemachine/citizenquartz/clock.h @@ -0,0 +1,60 @@ +#ifndef CLOCK_H +#define CLOCK_H + +#include <QGraphicsItem> +#include <QTime> + +class ClockButton ; +class ClockDisplay ; +class QStateMachine ; +class QState ; +class QTimerState ; +class QSound ; + +class Clock: public QObject, public QGraphicsItem +{ + Q_OBJECT +public: + Clock(QGraphicsItem *parent = 0); + + void initializeUi(); + void initializeStateMachine(); + + virtual QRectF boundingRect() const; + virtual QPainterPath shape() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + +signals: + void alarm(); + void anyButtonPressed(); + +public slots: + void updateTime(); + void playSound(); + void stopSound(); + +private: + void initializeDisplaysState(QState *displays); + void initializeAlarmState(QState *alarmState); + void initializeRegularState(QState *regular); + void initializeUpdateState(QState *update); + void initializeOutState(QState *out); + void initializeAlarmUpdateState(QState *update); + + QStateMachine *m_stateMachine; + ClockDisplay *m_clockDisplay; + ClockButton *m_buttonA; + ClockButton *m_buttonB; + ClockButton *m_buttonC; + ClockButton *m_buttonD; + + QState *m_alarmState; + QState *m_timeState; + QState *m_updateState; + QState *m_regularState; + + QSound *m_alarmSound; + QTime m_time; +}; + +#endif // CLOCK_H diff --git a/examples/statemachine/citizenquartz/clockbutton.cpp b/examples/statemachine/citizenquartz/clockbutton.cpp new file mode 100644 index 0000000..7b86891 --- /dev/null +++ b/examples/statemachine/citizenquartz/clockbutton.cpp @@ -0,0 +1,39 @@ +#include "clockbutton.h" + +#include <QPainter> + +ClockButton::ClockButton(const QString &name, QGraphicsItem *parent) : QGraphicsItem(parent) +{ + setObjectName(name); + setToolTip(name); + setAcceptedMouseButtons(Qt::LeftButton); +} + +QRectF ClockButton::boundingRect() const +{ + return QRectF(-10.0, -10.0, 20.0, 20.0); +} + +QPainterPath ClockButton::shape() const +{ + QPainterPath path; + path.addRoundedRect(boundingRect(), 15.0, 15.0, Qt::RelativeSize); + + return path; +} + +void ClockButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setBrush(Qt::black); + painter->drawPath(shape()); +} + +void ClockButton::mousePressEvent(QGraphicsSceneMouseEvent *) +{ + emit pressed(); +} + +void ClockButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + emit released(); +}
\ No newline at end of file diff --git a/examples/statemachine/citizenquartz/clockbutton.h b/examples/statemachine/citizenquartz/clockbutton.h new file mode 100644 index 0000000..02a7ccd --- /dev/null +++ b/examples/statemachine/citizenquartz/clockbutton.h @@ -0,0 +1,25 @@ +#ifndef CLOCKBUTTON_H +#define CLOCKBUTTON_H + +#include <QGraphicsItem> + +class ClockButton: public QObject, public QGraphicsItem +{ + Q_OBJECT +public: + ClockButton(const QString &name, QGraphicsItem *parent = 0); + + virtual QRectF boundingRect() const; + virtual QPainterPath shape() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent *); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +signals: + void pressed(); + void released(); +}; + +#endif //CLOCKBUTTON_H diff --git a/examples/statemachine/citizenquartz/clockdisplay.cpp b/examples/statemachine/citizenquartz/clockdisplay.cpp new file mode 100644 index 0000000..717b881 --- /dev/null +++ b/examples/statemachine/citizenquartz/clockdisplay.cpp @@ -0,0 +1,140 @@ +#include "clockdisplay.h" + +#include <QPainter> +#include <QTimer> + +ClockDisplay::ClockDisplay(QGraphicsItem *parent) + : QGraphicsItem(parent), + m_displayMode(CurrentTimeMode), + m_currentTime(QDate(1970, 1, 1), QTime(0, 0)), + m_alarm(0, 0), + m_alarmEnabled(false), + m_blink(false) + +{ + m_text = new QGraphicsTextItem(this); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(toggleBlinkFlag())); + timer->start(500); + + QFont font = m_text->font(); + font.setPointSizeF(20.0); + m_text->setFont(font); + + m_text->translate(-100.0, -20.0); + + QPixmap pm(":/images/alarm.png"); + m_alarmSymbol = new QGraphicsPixmapItem(pm, this); + m_alarmSymbol->translate(-100.0, -60.0); + m_alarmSymbol->setOffset(5.0, 5.0); + m_alarmSymbol->scale(0.5, 0.5); +} + +ClockDisplay::~ClockDisplay() +{ +} + +void ClockDisplay::toggleBlinkFlag() +{ + m_blink = !m_blink; + update(); +} + +void ClockDisplay::updateText() +{ + switch (m_displayMode) { + case EditSecondMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("hh:mm:'<font color=\"transparent\">'ss'</font>'")); + break; + } + // fall throoough + case EditMinuteMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("hh:'<font color=\"transparent\">'mm'</font>':ss")); + break; + } + + // fall throoough + case EditHourMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("'<font color=\"transparent\">'hh'</font>':mm:ss")); + break; + } + + // fall throoough + case CurrentTimeMode: + m_text->setHtml(m_currentTime.toString("hh:mm:ss")); + break; + + case EditMonthMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("yyyy.'<font color=\"transparent\">'MM'</font>'.dd")); + break; + } + + // fall throoough + case EditDayMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("yyyy.MM.'<font color=\"transparent\">'dd'</font>'")); + break; + } + + // fall throoough + case EditYearMode: + if (m_blink) { + m_text->setHtml(m_currentTime.toString("'<font color=\"transparent\">'yyyy'</font>'.MM.dd")); + break; + } + + // fall throoough + case CurrentDateMode: + m_text->setHtml(m_currentTime.toString("yyyy.MM.dd")); + break; + + case EditAlarmHourMode: + if (m_blink) { + m_text->setHtml(m_alarm.toString("'<font color=\"transparent\">'hh'</font>':mm")); + break; + } + + // fall throooough + case EditAlarmTenMinuteMode: + case EditAlarmMinuteMode: + if (m_blink) { + m_text->setHtml(m_alarm.toString("hh:'<font color=\"transparent\">'mm'</font>'")); + break; + } + + // fall throoough + case AlarmMode: + m_text->setHtml(m_alarm.toString("hh:mm")); + break; + + default: + m_text->setHtml("Not implemented"); + }; +} + +QRectF ClockDisplay::boundingRect() const +{ + return QRectF(-100.0, -60.0, 200.0, 120.0); +} + +void ClockDisplay::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (m_alarmEnabled) + m_alarmSymbol->setVisible(true); + + updateText(); + + // Screen + painter->drawRoundedRect(boundingRect(), 15.0, 15.0, Qt::RelativeSize); + + // Button grid + painter->drawLine(QPointF(-100.0, -20.0), QPointF(100.0, -20.0)); + painter->drawLine(QPointF(-50.0, -60.0), QPointF(-50.0, -20.0)); + painter->drawLine(QPointF(0.0, -60.0), QPointF(0.0, -20.0)); + painter->drawLine(QPointF(50.0, -60.0), QPointF(50.0, -20.0)); +} diff --git a/examples/statemachine/citizenquartz/clockdisplay.h b/examples/statemachine/citizenquartz/clockdisplay.h new file mode 100644 index 0000000..e0ac8bb --- /dev/null +++ b/examples/statemachine/citizenquartz/clockdisplay.h @@ -0,0 +1,75 @@ +#ifndef CLOCKDISPLAY_H +#define CLOCKDISPLAY_H + +#include <QObject> +#include <QGraphicsItem> +#include <QDateTime> + +class ClockDisplay: public QObject, public QGraphicsItem +{ + Q_OBJECT + Q_ENUMS(DisplayMode) + Q_PROPERTY(DisplayMode displayMode READ displayMode WRITE setDisplayMode) + Q_PROPERTY(QDateTime currentTime READ currentTime WRITE setCurrentTime) + Q_PROPERTY(QTime alarm READ alarm WRITE setAlarm) + Q_PROPERTY(bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled) +public: + enum DisplayMode { + CurrentTimeMode, + EditSecondMode, + EditMinuteMode, + EditHourMode, + + CurrentDateMode, + EditMonthMode, + EditDayMode, + EditYearMode, + + AlarmMode, + EditAlarmHourMode, + EditAlarmTenMinuteMode, + EditAlarmMinuteMode, + + ChimeMode, + StopWatchMode, + ModeCount + }; + + ClockDisplay(QGraphicsItem *parent = 0); + virtual ~ClockDisplay(); + + void setDisplayMode(DisplayMode displayMode) { m_displayMode = displayMode; update(); } + DisplayMode displayMode() const { return m_displayMode; } + + QDateTime currentTime() const { return m_currentTime; } + void setCurrentTime(const QDateTime &time) { m_currentTime = time; update(); } + + QTime alarm() const { return m_alarm; } + void setAlarm(const QTime &time) { m_alarm = time; update(); } + + bool alarmEnabled() const { return m_alarmEnabled; } + void setAlarmEnabled(bool enabled) { m_alarmEnabled = enabled; update(); } + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + +private slots: + void toggleBlinkFlag(); + +private: + void updateText(); + + DisplayMode m_displayMode; + + QDateTime m_currentTime; + QTime m_alarm; + + QGraphicsTextItem *m_text; + QGraphicsPixmapItem *m_alarmSymbol; + + uint m_alarmEnabled : 1; + uint m_blink : 1; + uint m_reserved : 30; +}; + +#endif diff --git a/examples/statemachine/citizenquartz/images/alarm.png b/examples/statemachine/citizenquartz/images/alarm.png Binary files differnew file mode 100644 index 0000000..a19778d --- /dev/null +++ b/examples/statemachine/citizenquartz/images/alarm.png diff --git a/examples/statemachine/citizenquartz/main.cpp b/examples/statemachine/citizenquartz/main.cpp new file mode 100644 index 0000000..2c6b14c --- /dev/null +++ b/examples/statemachine/citizenquartz/main.cpp @@ -0,0 +1,23 @@ +#include <QApplication> +#include <QGraphicsScene> +#include <QGraphicsView> + +#include "clock.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QGraphicsScene scene; + + Clock *clock = new Clock; + clock->initializeUi(); + clock->initializeStateMachine(); + scene.addItem(clock); + + QGraphicsView view(&scene); + view.setRenderHint(QPainter::Antialiasing); + view.show(); + + return app.exec(); +} diff --git a/examples/statemachine/citizenquartz/propertyaddstate.cpp b/examples/statemachine/citizenquartz/propertyaddstate.cpp new file mode 100644 index 0000000..f129c8d --- /dev/null +++ b/examples/statemachine/citizenquartz/propertyaddstate.cpp @@ -0,0 +1,46 @@ +#include "PropertyAddState.h" +#include "timeperiod.h" + +#include <QDateTime> +#include <QDebug> + +PropertyAddState::PropertyAddState(QState *parent) + : QState(parent) +{ +} + +void PropertyAddState::addToProperty(QObject *object, const char *propertyName, + const QVariant &valueToAdd) +{ + m_propertyAdditions.append(PropertyAdder(object, propertyName, valueToAdd)); +} + +QVariant PropertyAddState::addProperties(const QVariant ¤t, const QVariant &toAdd) const +{ + QVariant result; + switch (current.type()) { + case QVariant::DateTime: + result = current.toDateTime() + qvariant_cast<TimePeriod>(toAdd); + break; + case QVariant::Time: + result = current.toTime() + qvariant_cast<TimePeriod>(toAdd); + break; + default: + qWarning("PropertyAddState::addProperties: QVariant type '%s' not supported", + current.typeName()); + }; + + return result; +} + +void PropertyAddState::onEntry() +{ + foreach (PropertyAdder propertyAdder, m_propertyAdditions) { + QObject *object = propertyAdder.object; + const char *propertyName = propertyAdder.propertyName; + QVariant toAdd = propertyAdder.valueToAdd; + QVariant current = object->property(propertyName); + + object->setProperty(propertyName, addProperties(current, toAdd)); + } +} diff --git a/examples/statemachine/citizenquartz/propertyaddstate.h b/examples/statemachine/citizenquartz/propertyaddstate.h new file mode 100644 index 0000000..96f45fc --- /dev/null +++ b/examples/statemachine/citizenquartz/propertyaddstate.h @@ -0,0 +1,33 @@ +#ifndef PropertyAddState_H +#define PropertyAddState_H + +#include <qstate.h> + +#include <QVariant> +#include <QList> + +class PropertyAddState: public QState +{ +public: + PropertyAddState(QState *parent = 0); + + void addToProperty(QObject *object, const char *propertyName, const QVariant &valueToAdd); + virtual void onEntry(); + +private: + QVariant addProperties(const QVariant ¤t, const QVariant &toAdd) const; + + struct PropertyAdder { + PropertyAdder(QObject *_object, const char *_propertyName, const QVariant &_valueToAdd) + : object(_object), propertyName(_propertyName), valueToAdd(_valueToAdd) + { + } + + QObject *object; + const char *propertyName; + QVariant valueToAdd; + }; + QList<PropertyAdder> m_propertyAdditions; +}; + +#endif // PropertyAddState_H diff --git a/examples/statemachine/citizenquartz/sound/alarm.wav b/examples/statemachine/citizenquartz/sound/alarm.wav Binary files differnew file mode 100644 index 0000000..1d9486f --- /dev/null +++ b/examples/statemachine/citizenquartz/sound/alarm.wav diff --git a/examples/statemachine/citizenquartz/timeperiod.h b/examples/statemachine/citizenquartz/timeperiod.h new file mode 100644 index 0000000..a64c17c --- /dev/null +++ b/examples/statemachine/citizenquartz/timeperiod.h @@ -0,0 +1,84 @@ +#ifndef TIMEPERIOD_H +#define TIMEPERIOD_H + +#include <QDateTime> +#include <QTime> +#include <QDebug> + +class TimePeriod +{ +public: + TimePeriod() : m_seconds(0), m_minutes(0), m_hours(0), m_days(0), m_months(0), m_years(0) + { + } + + TimePeriod &setSeconds(int seconds) { m_seconds = seconds; return *this; } + int seconds() const { return m_seconds; } + + TimePeriod &setMinutes(int minutes) { m_minutes = minutes; return *this; } + int minutes() const { return m_minutes; } + + TimePeriod &setHours(int hours) { m_hours = hours; return *this; } + int hours() const { return m_hours; } + + TimePeriod &setDays(int days) { m_days = days; return *this; } + int days() const { return m_days; } + + TimePeriod &setMonths(int months) { m_months = months; return *this; } + int months() const { return m_months; } + + TimePeriod &setYears(int years) { m_years = years; return *this; } + int years() const { return m_years; } + + operator QVariant() const + { + QVariant v; + qVariantSetValue<TimePeriod>(v, *this); + return v; + } + +private: + int m_seconds; + int m_minutes; + int m_hours; + int m_days; + int m_months; + int m_years; +}; + +inline void operator+=(QDateTime &dateTime, const TimePeriod &timePeriod) +{ + dateTime = dateTime.addSecs(timePeriod.seconds()); + dateTime = dateTime.addSecs(timePeriod.minutes() * 60); + dateTime = dateTime.addSecs(timePeriod.hours() * 3600); + dateTime = dateTime.addDays(timePeriod.days()); + dateTime = dateTime.addMonths(timePeriod.months()); + dateTime = dateTime.addYears(timePeriod.years()); +} + +inline QDateTime operator+(const QDateTime &dateTime, const TimePeriod &timePeriod) +{ + QDateTime result(dateTime); + result += timePeriod; + + return result; +} + +inline void operator+=(QTime &time, const TimePeriod &timePeriod) +{ + time = time.addSecs(timePeriod.seconds()); + time = time.addSecs(timePeriod.minutes() * 60); + time = time.addSecs(timePeriod.hours() * 3600); +} + +inline QTime operator+(const QTime &time, const TimePeriod &timePeriod) +{ + QTime result(time); + result += timePeriod; + + return time; +} + +Q_DECLARE_METATYPE(TimePeriod) + +#endif \\ TIMEPERIOD_H diff --git a/examples/statemachine/clockticking/clockticking.pro b/examples/statemachine/clockticking/clockticking.pro new file mode 100644 index 0000000..bff9cb8 --- /dev/null +++ b/examples/statemachine/clockticking/clockticking.pro @@ -0,0 +1,10 @@ +QT = core +TEMPLATE = app +TARGET = +win32: CONFIG += console +mac:CONFIG -= app_bundle +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp new file mode 100644 index 0000000..e903988 --- /dev/null +++ b/examples/statemachine/clockticking/main.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <stdio.h> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qtransition.h> +#endif + +class ClockEvent : public QEvent +{ +public: + ClockEvent() : QEvent(QEvent::Type(QEvent::User+2)) + {} +}; + +class ClockState : public QState +{ +public: + ClockState(QStateMachine *machine, QState *parent) + : QState(parent), m_machine(machine) {} + +protected: + virtual void onEntry() + { + fprintf(stdout, "ClockState entered; posting the initial tick\n"); + m_machine->postEvent(new ClockEvent()); + } + +private: + QStateMachine *m_machine; +}; + +class ClockTransition : public QAbstractTransition +{ +public: + ClockTransition(QStateMachine *machine) + : QAbstractTransition(), m_machine(machine) { } + +protected: + virtual bool eventTest(QEvent *e) const { + return (e->type() == QEvent::User+2); + } + virtual void onTransition() + { + fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n"); + m_machine->postEvent(new ClockEvent(), 1000); + } + +private: + QStateMachine *m_machine; +}; + +class ClockListener : public QAbstractTransition +{ +public: + ClockListener() + : QAbstractTransition() {} + +protected: + virtual bool eventTest(QEvent *e) const { + return (e->type() == QEvent::User+2); + } + virtual void onTransition() + { + fprintf(stdout, "ClockListener heard a tick!\n"); + } +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QStateMachine machine; + QState *group = new QState(QState::ParallelGroup); + group->setObjectName("group"); + + ClockState *clock = new ClockState(&machine, group); + clock->setObjectName("clock"); + clock->addTransition(new ClockTransition(&machine)); + + QState *listener = new QState(group); + listener->setObjectName("listener"); + listener->addTransition(new ClockListener()); + + machine.addState(group); + machine.setInitialState(group); + machine.start(); + + return app.exec(); +} diff --git a/examples/statemachine/composition/composition.pro b/examples/statemachine/composition/composition.pro new file mode 100644 index 0000000..6a976cb --- /dev/null +++ b/examples/statemachine/composition/composition.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp new file mode 100644 index 0000000..892542d --- /dev/null +++ b/examples/statemachine/composition/main.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qfinalstate.h> +#endif + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + QLabel label; + label.setAlignment(Qt::AlignCenter); + + QStateMachine machine; + + QState *s1 = new QState(); + s1->setObjectName("s1"); + s1->setPropertyOnEntry(&label, "text", "In S1, hang on..."); + s1->setPropertyOnEntry(&label, "geometry", QRect(100, 100, 200, 100)); + + QState *s1_timer = new QState(s1); + s1_timer->setObjectName("s1_timer"); + QTimer t1; + t1.setInterval(2000); + s1_timer->invokeMethodOnEntry(&t1, "start"); + QFinalState *s1_done = new QFinalState(s1); + s1_done->setObjectName("s1_done"); + s1_timer->addTransition(&t1, SIGNAL(timeout()), s1_done); + s1->setInitialState(s1_timer); + + QState *s2 = new QState(); + s2->setObjectName("s2"); + s2->setPropertyOnEntry(&label, "text", "In S2, I'm gonna quit on you..."); + s2->setPropertyOnEntry(&label, "geometry", QRect(300, 300, 300, 100)); +// s2->invokeMethodOnEntry(&label, "setNum", QList<QVariant>() << 123); +// s2->invokeMethodOnEntry(&label, "showMaximized"); + + QState *s2_timer = new QState(s2); + s2_timer->setObjectName("s2_timer"); + QTimer t2; + t2.setInterval(2000); + s2_timer->invokeMethodOnEntry(&t2, "start"); + QFinalState *s2_done = new QFinalState(s2); + s2_done->setObjectName("s2_done"); + s2_timer->addTransition(&t2, SIGNAL(timeout()), s2_done); + s2->setInitialState(s2_timer); + + s1->addFinishedTransition(s2); + + QFinalState *s3 = new QFinalState(); + s3->setObjectName("s3"); + s2->addFinishedTransition(s3); + + machine.addState(s1); + machine.addState(s2); + machine.addState(s3); + machine.setInitialState(s1); + QObject::connect(&machine, SIGNAL(finished()), &app, SLOT(quit())); + machine.start(); + + label.show(); + return app.exec(); +} diff --git a/examples/statemachine/eventtransitions/eventtransitions.pro b/examples/statemachine/eventtransitions/eventtransitions.pro new file mode 100644 index 0000000..6a976cb --- /dev/null +++ b/examples/statemachine/eventtransitions/eventtransitions.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/eventtransitions/main.cpp b/examples/statemachine/eventtransitions/main.cpp new file mode 100644 index 0000000..51b2d82 --- /dev/null +++ b/examples/statemachine/eventtransitions/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qeventtransition.h> +#endif + +class Window : public QWidget +{ +public: + Window(QWidget *parent = 0) + : QWidget(parent) + { + QPushButton *button = new QPushButton(this); + button->setGeometry(QRect(100, 100, 100, 100)); + + QStateMachine *machine = new QStateMachine(this); + + QState *s1 = new QState(); + s1->setPropertyOnEntry(button, "text", "Outside"); + + QState *s2 = new QState(); + s2->setPropertyOnEntry(button, "text", "Inside"); + + QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter); + enterTransition->setTargetState(s2); + s1->addTransition(enterTransition); + + QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave); + leaveTransition->setTargetState(s1); + s2->addTransition(leaveTransition); + + QState *s3 = new QState(); + s3->setPropertyOnEntry(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); + + machine->addState(s1); + machine->addState(s2); + machine->addState(s3); + machine->setInitialState(s1); + QObject::connect(machine, SIGNAL(finished()), qApp, SLOT(quit())); + machine->start(); + } +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Window window; + window.resize(300, 300); + window.show(); + + return app.exec(); +} diff --git a/examples/statemachine/factorial/factorial.pro b/examples/statemachine/factorial/factorial.pro new file mode 100644 index 0000000..ac79117 --- /dev/null +++ b/examples/statemachine/factorial/factorial.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = +QT = core +win32: CONFIG += console +mac:CONFIG -= app_bundle +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/factorial/main.cpp b/examples/statemachine/factorial/main.cpp new file mode 100644 index 0000000..985b09f --- /dev/null +++ b/examples/statemachine/factorial/main.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <stdio.h> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qsignaltransition.h> +#include <qfinalstate.h> +#endif + +class Factorial : public QObject +{ + Q_OBJECT + Q_PROPERTY(int x READ x WRITE setX) + Q_PROPERTY(int fac READ fac WRITE setFac) +public: + Factorial(QObject *parent = 0) + : QObject(parent) + { + m_fac = 1; + m_x = -1; + } + + int x() const + { + return m_x; + } + + void setX(int x) + { + if (x == m_x) + return; + m_x = x; + emit xChanged(); + } + + int fac() const + { + return m_fac; + } + + void setFac(int fac) + { + m_fac = fac; + } + +Q_SIGNALS: + void xChanged(); + +private: + int m_x; + int m_fac; +}; + +class FactorialLoopTransition : public QSignalTransition +{ +public: + FactorialLoopTransition(Factorial *fact) + : QSignalTransition(fact, SIGNAL(xChanged())), m_fact(fact) + {} + + virtual bool eventTest(QEvent *) const + { + return m_fact->property("x").toInt() > 1; + } + + virtual void onTransition() + { + int x = m_fact->property("x").toInt(); + int fac = m_fact->property("fac").toInt(); + m_fact->setProperty("fac", x * fac); + m_fact->setProperty("x", x - 1); + } + +private: + Factorial *m_fact; +}; + +class FactorialDoneTransition : public QSignalTransition +{ +public: + FactorialDoneTransition(Factorial *fact) + : QSignalTransition(fact, SIGNAL(xChanged())), m_fact(fact) + {} + + virtual bool eventTest(QEvent *) const + { + return m_fact->property("x").toInt() <= 1; + } + + virtual void onTransition() + { + fprintf(stdout, "%d\n", m_fact->property("fac").toInt()); + } + +private: + Factorial *m_fact; +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + Factorial factorial; + + QStateMachine machine; + + QState *computing = new QState(machine.rootState()); + computing->addTransition(new FactorialLoopTransition(&factorial)); + + QFinalState *done = new QFinalState(machine.rootState()); + FactorialDoneTransition *doneTransition = new FactorialDoneTransition(&factorial); + doneTransition->setTargetState(done); + computing->addTransition(doneTransition); + + QState *initialize = new QState(machine.rootState()); + initialize->setPropertyOnEntry(&factorial, "x", 6); + FactorialLoopTransition *enterLoopTransition = new FactorialLoopTransition(&factorial); + enterLoopTransition->setTargetState(computing); + initialize->addTransition(enterLoopTransition); + + QObject::connect(&machine, SIGNAL(finished()), &app, SLOT(quit())); + + machine.setInitialState(initialize); + machine.start(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/statemachine/helloworld/helloworld.pro b/examples/statemachine/helloworld/helloworld.pro new file mode 100644 index 0000000..ac79117 --- /dev/null +++ b/examples/statemachine/helloworld/helloworld.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = +QT = core +win32: CONFIG += console +mac:CONFIG -= app_bundle +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/helloworld/main.cpp b/examples/statemachine/helloworld/main.cpp new file mode 100644 index 0000000..a124623 --- /dev/null +++ b/examples/statemachine/helloworld/main.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qfinalstate.h> +#endif + +class S0 : public QState +{ +public: + S0(QState *parent = 0) + : QState(parent) {} + + virtual void onEntry() + { + fprintf(stdout, "Hello world!\n"); + } +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QStateMachine machine; + QState *s0 = new S0(); + QFinalState *s1 = new QFinalState(); + s0->addTransition(s1); + + machine.addState(s0); + machine.addState(s1); + machine.setInitialState(s0); + + QObject::connect(&machine, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit())); + machine.start(); + + return app.exec(); +} diff --git a/examples/statemachine/pauseandresume/main.cpp b/examples/statemachine/pauseandresume/main.cpp new file mode 100644 index 0000000..7aed84b --- /dev/null +++ b/examples/statemachine/pauseandresume/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstatemachine.h> +#include <qstate.h> +#include <qfinalstate.h> +#include <qhistorystate.h> +#endif + +class Window : public QWidget +{ +public: + Window(QWidget *parent = 0) + : QWidget(parent) + { + QPushButton *pb = new QPushButton("Go"); + QPushButton *pauseButton = new QPushButton("Pause"); + QPushButton *quitButton = new QPushButton("Quit"); + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->addWidget(pb); + vbox->addWidget(pauseButton); + vbox->addWidget(quitButton); + + QStateMachine *machine = new QStateMachine(this); + + QState *process = new QState(machine->rootState()); + process->setObjectName("process"); + + QState *s1 = new QState(process); + s1->setObjectName("s1"); + QState *s2 = new QState(process); + s2->setObjectName("s2"); + s1->addTransition(pb, SIGNAL(clicked()), s2); + s2->addTransition(pb, SIGNAL(clicked()), s1); + + QHistoryState *h = process->addHistoryState(); + h->setDefaultState(s1); + + QState *interrupted = new QState(machine->rootState()); + interrupted->setObjectName("interrupted"); + QFinalState *terminated = new QFinalState(machine->rootState()); + terminated->setObjectName("terminated"); + interrupted->addTransition(pauseButton, SIGNAL(clicked()), h); + interrupted->addTransition(quitButton, SIGNAL(clicked()), terminated); + + process->addTransition(pauseButton, SIGNAL(clicked()), interrupted); + process->addTransition(quitButton, SIGNAL(clicked()), terminated); + + process->setInitialState(s1); + machine->setInitialState(process); + QObject::connect(machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit())); + machine->start(); + } +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Window win; + win.show(); + return app.exec(); +} diff --git a/examples/statemachine/pauseandresume/pauseandresume.pro b/examples/statemachine/pauseandresume/pauseandresume.pro new file mode 100644 index 0000000..6a976cb --- /dev/null +++ b/examples/statemachine/pauseandresume/pauseandresume.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp new file mode 100644 index 0000000..d749076 --- /dev/null +++ b/examples/statemachine/pingpong/main.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <stdio.h> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstate.h> +#include <qstatemachine.h> +#include <qtransition.h> +#endif + +class PingEvent : public QEvent +{ +public: + PingEvent() : QEvent(QEvent::Type(QEvent::User+2)) + {} +}; + +class PongEvent : public QEvent +{ +public: + PongEvent() : QEvent(QEvent::Type(QEvent::User+3)) + {} +}; + +class Pinger : public QState +{ +public: + Pinger(QStateMachine *machine, QState *parent) + : QState(parent), m_machine(machine) {} + +protected: + virtual void onEntry() + { + m_machine->postEvent(new PingEvent()); + fprintf(stdout, "ping?\n"); + } + +private: + QStateMachine *m_machine; +}; + +class PongTransition : public QAbstractTransition +{ +public: + PongTransition(QStateMachine *machine) + : QAbstractTransition(), m_machine(machine) {} + +protected: + virtual bool eventTest(QEvent *e) const { + return (e->type() == QEvent::User+3); + } + virtual void onTransition() + { + m_machine->postEvent(new PingEvent(), 500); + fprintf(stdout, "ping?\n"); + } + +private: + QStateMachine *m_machine; +}; + +class PingTransition : public QAbstractTransition +{ +public: + PingTransition(QStateMachine *machine) + : QAbstractTransition(), m_machine(machine) {} + +protected: + virtual bool eventTest(QEvent *e) const { + return (e->type() == QEvent::User+2); + } + virtual void onTransition() + { + m_machine->postEvent(new PongEvent(), 500); + fprintf(stdout, "pong!\n"); + } + +private: + QStateMachine *m_machine; +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QStateMachine machine; + QState *group = new QState(QState::ParallelGroup); + group->setObjectName("group"); + + Pinger *pinger = new Pinger(&machine, group); + pinger->setObjectName("pinger"); + pinger->addTransition(new PongTransition(&machine)); + + QState *ponger = new QState(group); + ponger->setObjectName("ponger"); + ponger->addTransition(new PingTransition(&machine)); + + machine.addState(group); + machine.setInitialState(group); + machine.start(); + + return app.exec(); +} diff --git a/examples/statemachine/pingpong/pingpong.pro b/examples/statemachine/pingpong/pingpong.pro new file mode 100644 index 0000000..bff9cb8 --- /dev/null +++ b/examples/statemachine/pingpong/pingpong.pro @@ -0,0 +1,10 @@ +QT = core +TEMPLATE = app +TARGET = +win32: CONFIG += console +mac:CONFIG -= app_bundle +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/statemachine/statemachine.pro b/examples/statemachine/statemachine.pro new file mode 100644 index 0000000..ba32c12 --- /dev/null +++ b/examples/statemachine/statemachine.pro @@ -0,0 +1,17 @@ +TEMPLATE = subdirs +SUBDIRS = \ + clockticking \ + composition \ + eventtransitions \ + factorial \ + helloworld \ + pauseandresume \ + pingpong \ + trafficlight \ + twowaybutton + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS statemachine.pro README +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine +INSTALLS += target sources diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp new file mode 100644 index 0000000..fbb6b68 --- /dev/null +++ b/examples/statemachine/trafficlight/main.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstate.h> +#include <qstatemachine.h> +#include <qfinalstate.h> +#endif + +//! [0] +class LightWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(bool on READ isOn WRITE setOn) +public: + LightWidget(const QColor &color, QWidget *parent = 0) + : 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(); + } + +protected: + virtual void paintEvent(QPaintEvent *) + { + 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 LightState : public QState +{ +public: + LightState(LightWidget *light, int duration, QState *parent = 0) + : QState(parent) + { + QTimer *timer = new QTimer(this); + timer->setInterval(duration); + timer->setSingleShot(true); + QState *timing = new QState(this); + timing->setPropertyOnEntry(light, "on", true); + timing->invokeMethodOnEntry(timer, "start"); + timing->setPropertyOnExit(light, "on", false); + QFinalState *done = new QFinalState(this); + timing->addTransition(timer, SIGNAL(timeout()), done); + setInitialState(timing); + } +}; +//! [1] + +//! [2] +class TrafficLightWidget : public QWidget +{ +public: + TrafficLightWidget(QWidget *parent = 0) + : 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::Background, 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; +}; +//! [2] + +//! [3] +class TrafficLight : public QWidget +{ +public: + TrafficLight(QWidget *parent = 0) + : QWidget(parent) + { + QVBoxLayout *vbox = new QVBoxLayout(this); + TrafficLightWidget *widget = new TrafficLightWidget(); + vbox->addWidget(widget); + + QStateMachine *machine = new QStateMachine(this); + LightState *redGoingYellow = new LightState(widget->redLight(), 3000); + redGoingYellow->setObjectName("redGoingYellow"); + LightState *yellowGoingGreen = new LightState(widget->yellowLight(), 1000); + yellowGoingGreen->setObjectName("yellowGoingGreen"); + redGoingYellow->addFinishedTransition(yellowGoingGreen); + LightState *greenGoingYellow = new LightState(widget->greenLight(), 3000); + greenGoingYellow->setObjectName("greenGoingYellow"); + yellowGoingGreen->addFinishedTransition(greenGoingYellow); + LightState *yellowGoingRed = new LightState(widget->yellowLight(), 1000); + yellowGoingRed->setObjectName("yellowGoingRed"); + greenGoingYellow->addFinishedTransition(yellowGoingRed); + yellowGoingRed->addFinishedTransition(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(120, 300); + widget.show(); + + return app.exec(); +} +//! [4] + +#include "main.moc" diff --git a/examples/statemachine/trafficlight/trafficlight.pro b/examples/statemachine/trafficlight/trafficlight.pro new file mode 100644 index 0000000..730bd75 --- /dev/null +++ b/examples/statemachine/trafficlight/trafficlight.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +SOURCES += main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/trafficlight +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS trafficlight.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/trafficlight +INSTALLS += target sources diff --git a/examples/statemachine/twowaybutton/main.cpp b/examples/statemachine/twowaybutton/main.cpp new file mode 100644 index 0000000..eab0b3d --- /dev/null +++ b/examples/statemachine/twowaybutton/main.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> +#ifdef QT_STATEMACHINE_SOLUTION +#include <qstate.h> +#include <qstatemachine.h> +#endif + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QPushButton button; + + QStateMachine machine; + QState *first = new QState(); + first->setObjectName("first"); + + QState *off = new QState(); + off->setPropertyOnEntry(&button, "text", "Off"); + off->setObjectName("off"); + first->addTransition(off); + + QState *on = new QState(); + on->setObjectName("on"); + on->setPropertyOnEntry(&button, "text", "On"); + off->addTransition(&button, SIGNAL(clicked()), on); + on->addTransition(&button, SIGNAL(clicked()), off); + + machine.addState(first); + machine.addState(off); + machine.addState(on); + machine.setInitialState(first); + machine.start(); + + button.resize(100, 50); + button.show(); + return app.exec(); +} diff --git a/examples/statemachine/twowaybutton/twowaybutton.pro b/examples/statemachine/twowaybutton/twowaybutton.pro new file mode 100644 index 0000000..6a976cb --- /dev/null +++ b/examples/statemachine/twowaybutton/twowaybutton.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp |