summaryrefslogtreecommitdiffstats
path: root/examples/statemachine/citizenquartz/clock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/statemachine/citizenquartz/clock.cpp')
-rw-r--r--examples/statemachine/citizenquartz/clock.cpp382
1 files changed, 382 insertions, 0 deletions
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();
+}
+