diff options
Diffstat (limited to 'examples/statemachine/citizenquartz')
-rw-r--r-- | examples/statemachine/citizenquartz/citizenquartz.pro | 20 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/citizenquartz.qrc | 5 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clock.cpp | 382 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clock.h | 60 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clockbutton.cpp | 39 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clockbutton.h | 25 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clockdisplay.cpp | 140 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/clockdisplay.h | 75 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/images/alarm.png | bin | 0 -> 434 bytes | |||
-rw-r--r-- | examples/statemachine/citizenquartz/main.cpp | 23 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/propertyaddstate.cpp | 46 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/propertyaddstate.h | 33 | ||||
-rw-r--r-- | examples/statemachine/citizenquartz/sound/alarm.wav | bin | 0 -> 3238264 bytes | |||
-rw-r--r-- | examples/statemachine/citizenquartz/timeperiod.h | 84 |
14 files changed, 932 insertions, 0 deletions
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 |