#include #include #include #include #include #include #include "offroad_alerts.hpp" #include "common/params.h" void cleanLayout(QLayout* layout) { while (QLayoutItem* item = layout->takeAt(0)) { if (QWidget* widget = item->widget()) { widget->deleteLater(); } if (QLayout* childLayout = item->layout()) { cleanLayout(childLayout); } delete item; } } QString vectorToQString(std::vector v) { return QString::fromStdString(std::string(v.begin(), v.end())); } OffroadAlert::OffroadAlert(QWidget* parent) { vlayout = new QVBoxLayout; refresh(); setLayout(vlayout); } void OffroadAlert::refresh() { cleanLayout(vlayout); parse_alerts(); updateAvailable = false; std::vector bytes = Params().read_db_bytes("UpdateAvailable"); if (bytes.size() && bytes[0] == '1') { updateAvailable = true; } if (updateAvailable) { // If there is an update available, don't show alerts alerts.clear(); QFrame *f = new QFrame(); QVBoxLayout *update_layout = new QVBoxLayout; update_layout->setMargin(10); update_layout->setSpacing(20); QLabel *title = new QLabel("Update available"); title->setStyleSheet(R"( font-size: 55px; font-weight: bold; )"); update_layout->addWidget(title, 0, Qt::AlignTop); QString release_notes = QString::fromStdString(Params().get("ReleaseNotes")); QLabel *notes_label = new QLabel(release_notes); notes_label->setStyleSheet(R"(font-size: 40px;)"); notes_label->setWordWrap(true); update_layout->addWidget(notes_label, 1, Qt::AlignTop); QPushButton *update_button = new QPushButton("Reboot and Update"); update_layout->addWidget(update_button); #ifdef __aarch64__ QObject::connect(update_button, &QPushButton::released, [=]() {std::system("sudo reboot");}); #endif f->setLayout(update_layout); f->setStyleSheet(R"( .QFrame{ border-radius: 20px; border: 2px solid white; background-color: #114267; } QPushButton { padding: 20px; font-size: 35px; color: white; background-color: blue; } )"); vlayout->addWidget(f); vlayout->addSpacing(60); } else { vlayout->addSpacing(60); for (const auto &alert : alerts) { QLabel *l = new QLabel(alert.text); l->setWordWrap(true); l->setMargin(60); QString style = R"( font-size: 40px; font-weight: bold; border-radius: 30px; border: 2px solid; border-color: white; )"; style.append("background-color: " + QString(alert.severity ? "#971b1c" : "#114267")); l->setStyleSheet(style); vlayout->addWidget(l); vlayout->addSpacing(20); } } QPushButton *hide_btn = new QPushButton(updateAvailable ? "Later" : "Hide alerts"); hide_btn->setStyleSheet(R"( padding: 20px; font-size: 35px; color: white; background-color: blue; )"); vlayout->addWidget(hide_btn); QObject::connect(hide_btn, SIGNAL(released()), this, SIGNAL(closeAlerts())); } void OffroadAlert::parse_alerts() { alerts.clear(); // We launch in selfdrive/ui QFile inFile("../controls/lib/alerts_offroad.json"); inFile.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray data = inFile.readAll(); inFile.close(); QJsonDocument doc = QJsonDocument::fromJson(data); if (doc.isNull()) { qDebug() << "Parse failed"; } QJsonObject json = doc.object(); for (const QString &key : json.keys()) { std::vector bytes = Params().read_db_bytes(key.toStdString().c_str()); if (bytes.size()) { QJsonDocument doc_par = QJsonDocument::fromJson(QByteArray(bytes.data(), bytes.size())); QJsonObject obj = doc_par.object(); Alert alert = {obj.value("text").toString(), obj.value("severity").toInt()}; alerts.push_back(alert); } } }