summaryrefslogtreecommitdiffstats
path: root/examples/statemachine
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /examples/statemachine
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'examples/statemachine')
-rw-r--r--examples/statemachine/README36
-rw-r--r--examples/statemachine/citizenquartz/citizenquartz.pro20
-rw-r--r--examples/statemachine/citizenquartz/citizenquartz.qrc5
-rw-r--r--examples/statemachine/citizenquartz/clock.cpp382
-rw-r--r--examples/statemachine/citizenquartz/clock.h60
-rw-r--r--examples/statemachine/citizenquartz/clockbutton.cpp39
-rw-r--r--examples/statemachine/citizenquartz/clockbutton.h25
-rw-r--r--examples/statemachine/citizenquartz/clockdisplay.cpp140
-rw-r--r--examples/statemachine/citizenquartz/clockdisplay.h75
-rw-r--r--examples/statemachine/citizenquartz/images/alarm.pngbin0 -> 434 bytes
-rw-r--r--examples/statemachine/citizenquartz/main.cpp23
-rw-r--r--examples/statemachine/citizenquartz/propertyaddstate.cpp46
-rw-r--r--examples/statemachine/citizenquartz/propertyaddstate.h33
-rw-r--r--examples/statemachine/citizenquartz/sound/alarm.wavbin0 -> 3238264 bytes
-rw-r--r--examples/statemachine/citizenquartz/timeperiod.h84
-rw-r--r--examples/statemachine/clockticking/clockticking.pro10
-rw-r--r--examples/statemachine/clockticking/main.cpp101
-rw-r--r--examples/statemachine/composition/composition.pro7
-rw-r--r--examples/statemachine/composition/main.cpp74
-rw-r--r--examples/statemachine/eventtransitions/eventtransitions.pro7
-rw-r--r--examples/statemachine/eventtransitions/main.cpp72
-rw-r--r--examples/statemachine/factorial/factorial.pro10
-rw-r--r--examples/statemachine/factorial/main.cpp140
-rw-r--r--examples/statemachine/helloworld/helloworld.pro10
-rw-r--r--examples/statemachine/helloworld/main.cpp48
-rw-r--r--examples/statemachine/pauseandresume/main.cpp72
-rw-r--r--examples/statemachine/pauseandresume/pauseandresume.pro7
-rw-r--r--examples/statemachine/pingpong/main.cpp112
-rw-r--r--examples/statemachine/pingpong/pingpong.pro10
-rw-r--r--examples/statemachine/statemachine.pro17
-rw-r--r--examples/statemachine/trafficlight/main.cpp158
-rw-r--r--examples/statemachine/trafficlight/trafficlight.pro12
-rw-r--r--examples/statemachine/twowaybutton/main.cpp48
-rw-r--r--examples/statemachine/twowaybutton/twowaybutton.pro7
34 files changed, 1890 insertions, 0 deletions
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
new file mode 100644
index 0000000..a19778d
--- /dev/null
+++ b/examples/statemachine/citizenquartz/images/alarm.png
Binary files differ
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 &current, 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 &current, 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
new file mode 100644
index 0000000..1d9486f
--- /dev/null
+++ b/examples/statemachine/citizenquartz/sound/alarm.wav
Binary files differ
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