// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "trafficlight.h" #include #include using namespace Qt::Literals::StringLiterals; class TrafficLightWidget : public QWidget { public: TrafficLightWidget(QWidget *parent = nullptr) : QWidget(parent), m_background(":/background.png"_L1) { QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setContentsMargins(0, 40, 0, 80); m_red = new LightWidget(":/red.png"_L1); vbox->addWidget(m_red, 0, Qt::AlignHCenter); m_yellow = new LightWidget(":/yellow.png"_L1); vbox->addWidget(m_yellow, 0, Qt::AlignHCenter); m_green = new LightWidget(":/green.png"_L1); vbox->addWidget(m_green, 0, Qt::AlignHCenter); setLayout(vbox); } LightWidget *redLight() const { return m_red; } LightWidget *yellowLight() const { return m_yellow; } LightWidget *greenLight() const { return m_green; } void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.drawImage(0, 0, m_background); } QSize sizeHint() const override { return m_background.size(); } private: QImage m_background; LightWidget *m_red; LightWidget *m_yellow; LightWidget *m_green; }; TrafficLight::TrafficLight(QScxmlStateMachine *machine, QWidget *parent) : QWidget(parent) , m_machine(machine) { TrafficLightWidget *widget = new TrafficLightWidget(this); setFixedSize(widget->sizeHint()); machine->connectToState(u"red"_s, widget->redLight(), &LightWidget::switchLight); machine->connectToState(u"redGoingGreen"_s, widget->redLight(), &LightWidget::switchLight); machine->connectToState(u"yellow"_s, widget->yellowLight(), &LightWidget::switchLight); machine->connectToState(u"blinking"_s, widget->yellowLight(), &LightWidget::switchLight); machine->connectToState(u"green"_s, widget->greenLight(), &LightWidget::switchLight); QAbstractButton *button = new ButtonWidget(this); auto setButtonGeometry = [this, button](){ QSize buttonSize = button->sizeHint(); button->setGeometry(width() - buttonSize.width() - 20, height() - buttonSize.height() - 20, buttonSize.width(), buttonSize.height()); }; connect(button, &QAbstractButton::toggled, this, setButtonGeometry); setButtonGeometry(); connect(button, &QAbstractButton::toggled, this, &TrafficLight::toggleWorking); } void TrafficLight::toggleWorking(bool pause) { m_machine->submitEvent(pause ? "smash" : "repair"); } LightWidget::LightWidget(const QString &image, QWidget *parent) : QWidget(parent) , m_image(image) {} bool LightWidget::isOn() const { return m_on; } void LightWidget::setOn(bool on) { if (on == m_on) return; m_on = on; update(); } void LightWidget::switchLight(bool onoff) { setOn(onoff); } void LightWidget::paintEvent(QPaintEvent *) { if (!m_on) return; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.drawImage(0, 0, m_image); } QSize LightWidget::sizeHint() const { return m_image.size(); } ButtonWidget::ButtonWidget(QWidget *parent) : QAbstractButton(parent), m_playIcon(":/play.png"_L1), m_pauseIcon(":/pause.png"_L1) { setCheckable(true); } void ButtonWidget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.drawImage(0, 0, isChecked() ? m_playIcon : m_pauseIcon); } QSize ButtonWidget::sizeHint() const { return isChecked() ? m_playIcon.size() : m_pauseIcon.size(); }