#include "simulatorbase.h" SimulatorBase::SimulatorBase(Web_socket_wrapper* web_socket, QWidget* parent) : QMainWindow{parent}, m_error_dialog(new NetworkError(this)), m_web_socket(web_socket) { m_error_dialog->set_error("Connection timed out\nCheck if the server is running"); ui_lookup.reserve(40); } QWidget* SimulatorBase::id_to_ui(size_t id) { return ui_lookup.at(id); } void SimulatorBase::showEvent( QShowEvent* event ) { QWidget::showEvent( event ); QD << "Connecting callbacks"; setup_cb(); this->timer_update->start(refresh_rate); closed = false; } void SimulatorBase::closeEvent(QCloseEvent* event) { if (!closed) { QD << "Disconnecting callbacks"; QWidget::closeEvent(event); this->timer_update->stop(); disconnect(api, nullptr, nullptr, nullptr); this->parentWidget()->show(); } closed = true; } void SimulatorBase::setup_cb(void) { connect(m_web_socket, &Web_socket_wrapper::on_command_cb, this, [=, this](json& j){on_cmd_cb(j);}); connect(m_web_socket, &Web_socket_wrapper::on_event_cb, this, [=, this](json& j){on_event_cb(j);}); connect(m_web_socket, &Web_socket_wrapper::on_closed, this, [=, this]{m_error_dialog->open();}); } void SimulatorBase::on_cmd_cb(json& j) { auto response = magic_enum::enum_cast(std::string(j.at("type"))).value_or(Web_socket_wrapper::Command::end); switch (response) { case Web_socket_wrapper::Command::get_UI_elements: case Web_socket_wrapper::Command::get_UI_element: UI_item_parser(j); break; default: break; } } void SimulatorBase::on_event_cb(json& j) { auto response = magic_enum::enum_cast(std::string(j.at("type"))).value_or(Web_socket_wrapper::Event::end); switch (response) { case Web_socket_wrapper::Event::UI_changed: UI_item_parser(j); break; default: break; } } void SimulatorBase::push_ui_item(QWidget* item) { ui_lookup.emplace_back(item); setup_ui_item(item, ui_lookup.size()); } void SimulatorBase::button_update(size_t lookup) { m_web_socket->send_event(Web_socket_wrapper::Event::clicked, lookup); } void SimulatorBase::slider_update(size_t lookup) { QwtSlider* slider = qobject_cast(ui_lookup.at(lookup)); if (slider == nullptr) return; m_web_socket->send_event(Web_socket_wrapper::Event::value_changed, lookup, slider->value()); } void SimulatorBase::combobox_update(size_t lookup) { QComboBox* combobox = qobject_cast(ui_lookup.at(lookup)); if (combobox == nullptr) return; m_web_socket->send_event(Web_socket_wrapper::Event::selected, lookup, combobox->currentText()); } void SimulatorBase::UI_item_parser(json& input) { for (auto& uiItem : input["UI_items"]) { if (uiItem["type"] == "UI_button") { process_ui_button(uiItem); continue; } if (uiItem["type"] == "UI_led") { process_ui_led(uiItem); continue; } if (uiItem["type"] == "UI_slider") { process_ui_slider(uiItem); continue; } if (uiItem["type"] == "UI_dial") { process_ui_dial(uiItem); continue; } if (uiItem["type"] == "UI_thermo") { process_ui_thermo(uiItem); continue; } if (uiItem["type"] == "UI_textbox") { process_ui_textbox(uiItem); continue; } if (uiItem["type"] == "UI_label") { process_ui_label(uiItem); continue; } if (uiItem["type"] == "UI_combobox") { process_ui_combobox(uiItem); continue; } if (uiItem["type"] == "UIRadioButton") { process_ui_radiobutton(uiItem); continue; } } } void SimulatorBase::process_ui_label(json& uiItem) { QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto label = qobject_cast(widget); if (label == nullptr) { QD << "widget is not of type QLabel"; return; } QString value = QString::fromStdString(uiItem["text"]); if (label->text() != value) { label->setText(value); } } void SimulatorBase::process_ui_slider(json& uiItem) { QLabel* label = id_to_label(uiItem["id"]); QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto slider = qobject_cast(widget); if (slider == nullptr) { QD << "widget is not of type QwtSlider"; return; } double value = uiItem["value"]; bool enable = uiItem["enabled"]; bool visible = uiItem["visible"]; QString unit = QString::fromStdString(uiItem.at("unit")); if (slider->value() != value) { if (label != nullptr) { label->setText(QString("%0 %1").arg(value).arg(unit)); } slider->setValue(value); } if (slider->isReadOnly() != !enable) { slider->setReadOnly(!enable); } if (slider->isVisible() != visible) { slider->setVisible(visible); } //TODO: Add color for scale return; } void SimulatorBase::process_ui_dial(json& uiItem) { QLabel* label = id_to_label(uiItem["id"]); QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto dial = qobject_cast(widget); if (dial == nullptr) { QD << "widget is not of type QwtDial"; return; } double value = uiItem["value"]; bool visible = uiItem["visible"]; QString unit = QString::fromStdString(uiItem.at("unit")); if (dial->value() != value) { if (label != nullptr) { label->setText(QString("%0 %1").arg(value).arg(unit)); } dial->setValue(value); } if (dial->isVisible() != visible) { dial->setVisible(visible); } return; } void SimulatorBase::process_ui_thermo(json& uiItem) { QLabel* label = id_to_label(uiItem["id"]); QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto thermo = qobject_cast(widget); if (thermo == nullptr) { QD << "widget is not of type QwtThermo"; return; } double value = uiItem["value"]; bool visible = uiItem["visible"]; QString unit = QString::fromStdString(uiItem.at("unit")); if (thermo->value() != value) { if (label != nullptr) { label->setText(QString("%0 %1").arg(value).arg(unit)); } thermo->setValue(value); } if (thermo->isVisible() != visible) { thermo->setVisible(visible); } return; } void SimulatorBase::process_ui_textbox(json& uiItem) { QD << "Not implemented"; emit quit(); } void SimulatorBase::process_ui_combobox(json& uiItem) { QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto combobox = qobject_cast(widget); if (combobox == nullptr) { QD << "widget is not of type QComboBox"; return; } QString selected = QString::fromStdString(uiItem["selected"]); for (json& item : uiItem["options"]) { if (combobox->findText(QString::fromStdString(item)) == -1) combobox->addItem(QString::fromStdString(item)); } if (combobox->currentText() != selected) { combobox->setCurrentText(selected); } } void SimulatorBase::process_ui_radiobutton(json& uiItem) { QD << "Not implemented"; emit quit(); } void SimulatorBase::process_ui_button(json& uiItem) { //TODO: fix bgcolor and color QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto button = qobject_cast(widget); if (button == nullptr) { QD << "widget is not of type QPushButton"; return; } QColor bg_color = QColor(QString::fromStdString(uiItem["bg_color"])); QColor fg_color = QColor(QString::fromStdString(uiItem["fg_color"])); QString text = QString::fromStdString(uiItem["text"]); bool enabled = uiItem["enabled"]; if (button->text() != text) { button->setText(text); } if (button->isEnabled() != enabled) { button->setEnabled(enabled); } if (bg_color == QColor(0x83, 0x91, 0x92)) { reset_widget_color(button); return; } if (bg_color == QColor(0xFF, 0x00, 0x00)) { set_widget_color(button, QString("black"), QString("darkred")); return; } if (bg_color == QColor(0x00, 0xFF, 0x00)) { set_widget_color(button, QString("white"), QString("darkgreen")); return; } if (bg_color == QColor(0xFF8800)) { set_widget_color(button, QString("darkred"), QString("darkorange")); return; } if (bg_color != widget_bg_color(button) || fg_color != widget_color(button)) { set_widget_color(button, fg_color, bg_color); } } void SimulatorBase::process_ui_led(json& uiItem) { QWidget* widget = id_to_ui(uiItem["id"]); if (widget == nullptr) { QD << "id_to_ui returned null on " << QString::number((size_t)uiItem["id"]); return; } auto led = qobject_cast(widget); if (led == nullptr) { QD << "widget is not of type led"; return; } QColor bg_color = QColor(QString::fromStdString(uiItem["led_color"])); QColor color = QColor(~bg_color.red(), ~bg_color.green(), ~bg_color.blue()); QString text = QString::fromStdString(uiItem["text"]); if (text != led->text()) { led->setText(text); } if (bg_color == QColor(0x83, 0x91, 0x92)) { reset_widget_color(led); return; } if (bg_color == QColor(0xFF, 0x00, 0x00)) { set_widget_color(led, QString("black"), QString("darkred")); return; } if (bg_color == QColor(0x00, 0xFF, 0x00)) { set_widget_color(led, QString("white"), QString("darkgreen")); return; } if (bg_color == QColor(0xFF8800)) { set_widget_color(led, QString("darkred"), QString("darkorange")); return; } if (bg_color != widget_bg_color(led)) { set_widget_color(led, color, bg_color); } } void SimulatorBase::setup_ui_item(QWidget* item, size_t index) { setup_button(item, index); setup_combobox(item, index); setup_dial(item, index); setup_slider(item, index); } void SimulatorBase::setup_button(QWidget* item, size_t index) { QPushButton* button = qobject_cast(item); if (button == nullptr) return; connect(button, &QPushButton::clicked, this, [=, this]{button_update(index);}); } void SimulatorBase::setup_combobox(QWidget* item, size_t index) { QComboBox* combobox = qobject_cast(item); if (combobox == nullptr) return; connect(combobox, &QComboBox::currentIndexChanged, this, [=, this]{combobox_update(index);}); } void SimulatorBase::setup_dial(QWidget* item, size_t index) { QwtDial* dial = qobject_cast(item); if (dial == nullptr) return; create_dial_needle(dial); } void SimulatorBase::setup_slider(QWidget* item, size_t index) { QwtSlider* slider = qobject_cast(item); if (slider == nullptr) return; connect(slider, &QwtSlider::sliderMoved, this, [=, this]{slider_update(index);}); }