mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-07 06:32:08 +08:00
Offroad alerts (#2664)
We now have a working offroad alerts old-commit-hash: 744a3317e3ab608fadc9b172dd16897b8bbdc55e
This commit is contained in:
@@ -74,7 +74,7 @@ else:
|
||||
|
||||
qt_env.Library("qt_widgets",
|
||||
["qt/qt_window.cc", "qt/qt_sound.cc", "qt/widgets/keyboard.cc", "qt/widgets/input_field.cc",
|
||||
"qt/offroad/wifi.cc", "qt/offroad/wifiManager.cc", "qt/widgets/toggle.cc"],
|
||||
"qt/offroad/wifi.cc", "qt/offroad/wifiManager.cc", "qt/widgets/toggle.cc", "qt/widgets/offroad_alerts.cc"],
|
||||
LIBS=qt_libs)
|
||||
qt_libs.append("qt_widgets")
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "wifi.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "widgets/toggle.hpp"
|
||||
#include "widgets/offroad_alerts.hpp"
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/utilpp.h"
|
||||
@@ -224,7 +225,6 @@ void SettingsWindow::setActivePanel() {
|
||||
}
|
||||
|
||||
SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
// sidebar
|
||||
QVBoxLayout *sidebar_layout = new QVBoxLayout();
|
||||
panel_layout = new QStackedLayout();
|
||||
@@ -241,12 +241,21 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
|
||||
sidebar_layout->addWidget(close_button);
|
||||
QObject::connect(close_button, SIGNAL(released()), this, SIGNAL(closeSettings()));
|
||||
|
||||
// offroad alerts
|
||||
alerts_widget = new OffroadAlert();
|
||||
QObject::connect(alerts_widget, SIGNAL(closeAlerts()), this, SLOT(closeAlerts()));
|
||||
panel_layout->addWidget(alerts_widget);
|
||||
|
||||
sidebar_alert_widget = new QPushButton("");//Should get text when it is visible
|
||||
QObject::connect(sidebar_alert_widget, SIGNAL(released()), this, SLOT(openAlerts()));
|
||||
sidebar_layout->addWidget(sidebar_alert_widget);
|
||||
|
||||
// setup panels
|
||||
panels = {
|
||||
{"device", device_panel()},
|
||||
{"toggles", toggles_panel()},
|
||||
{"developer", developer_panel()},
|
||||
{"device", device_panel()},
|
||||
{"network", network_panel(this)},
|
||||
{"toggles", toggles_panel()},
|
||||
};
|
||||
|
||||
for (auto &panel : panels) {
|
||||
@@ -267,10 +276,14 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
|
||||
panel_layout->addWidget(panel.second);
|
||||
QObject::connect(btn, SIGNAL(released()), this, SLOT(setActivePanel()));
|
||||
}
|
||||
|
||||
// We either show the alerts, or the developer panel
|
||||
if (alerts_widget->show_alert){
|
||||
panel_layout->setCurrentWidget(alerts_widget);
|
||||
}
|
||||
|
||||
QHBoxLayout *settings_layout = new QHBoxLayout();
|
||||
settings_layout->addSpacing(45);
|
||||
|
||||
// settings_layout->addLayout(sidebar_layout);
|
||||
sidebar_widget = new QWidget;
|
||||
sidebar_widget->setLayout(sidebar_layout);
|
||||
sidebar_widget->setFixedWidth(SIDEBAR_WIDTH);
|
||||
@@ -280,7 +293,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
|
||||
settings_layout->addLayout(panel_layout);
|
||||
settings_layout->addSpacing(45);
|
||||
setLayout(settings_layout);
|
||||
|
||||
|
||||
setStyleSheet(R"(
|
||||
* {
|
||||
color: white;
|
||||
@@ -289,6 +302,51 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
|
||||
)");
|
||||
}
|
||||
|
||||
// Refreshes the offroad alerts from the params folder and sets up the sidebar alerts widget.
|
||||
// The function gets called every time a user opens the settings page
|
||||
void SettingsWindow::refreshParams(){
|
||||
alerts_widget->refresh();
|
||||
if (!alerts_widget->show_alert){
|
||||
sidebar_alert_widget->setFixedHeight(0);
|
||||
panel_layout->setCurrentIndex(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Panel 0 contains the alerts or release notes.
|
||||
panel_layout->setCurrentIndex(0);
|
||||
sidebar_alert_widget->setFixedHeight(100);
|
||||
sidebar_alert_widget->setStyleSheet(R"(
|
||||
background-color: #114267;
|
||||
)"); // light blue
|
||||
|
||||
// Check for alerts
|
||||
int alerts = alerts_widget->alerts.size();
|
||||
if (!alerts){
|
||||
//There is a new release
|
||||
sidebar_alert_widget->setText("UPDATE");
|
||||
return;
|
||||
}
|
||||
//Check if there is an important alert
|
||||
bool existsImportantAlert = false;
|
||||
for (auto alert : alerts_widget->alerts){
|
||||
if (alert.severity){
|
||||
existsImportantAlert = true;
|
||||
}
|
||||
}
|
||||
|
||||
sidebar_alert_widget->setText(QString::number(alerts) + " ALERT" + (alerts == 1 ? "" : "S"));
|
||||
if (existsImportantAlert){
|
||||
sidebar_alert_widget->setStyleSheet(R"(
|
||||
background-color: #661111;
|
||||
)"); //dark red
|
||||
}
|
||||
}
|
||||
void SettingsWindow::closeAlerts(){
|
||||
panel_layout->setCurrentIndex(1);
|
||||
}
|
||||
void SettingsWindow::openAlerts(){
|
||||
panel_layout->setCurrentIndex(0);
|
||||
}
|
||||
void SettingsWindow::closeSidebar(){
|
||||
sidebar_widget->setFixedWidth(0);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include <QTimer>
|
||||
#include <QCheckBox>
|
||||
#include <QStackedLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "wifi.hpp"
|
||||
|
||||
#include "widgets/offroad_alerts.hpp"
|
||||
|
||||
class ParamsToggle : public QFrame {
|
||||
Q_OBJECT
|
||||
@@ -29,17 +30,23 @@ class SettingsWindow : public QWidget {
|
||||
|
||||
public:
|
||||
explicit SettingsWindow(QWidget *parent = 0);
|
||||
void refreshParams();
|
||||
|
||||
signals:
|
||||
void closeSettings();
|
||||
|
||||
private:
|
||||
QPushButton *sidebar_alert_widget;
|
||||
QWidget *sidebar_widget;
|
||||
OffroadAlert *alerts_widget;
|
||||
std::map<QString, QWidget *> panels;
|
||||
QStackedLayout *panel_layout;
|
||||
|
||||
private slots:
|
||||
|
||||
public slots:
|
||||
void setActivePanel();
|
||||
void closeAlerts();
|
||||
void openAlerts();
|
||||
void closeSidebar();
|
||||
void openSidebar();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QDebug>
|
||||
|
||||
#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<char> 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();
|
||||
|
||||
bool updateAvailable = false;
|
||||
std::vector<char> bytes = Params().read_db_bytes("UpdateAvailable");
|
||||
if (bytes.size() && bytes[0] == '1'){
|
||||
updateAvailable = true;
|
||||
}
|
||||
show_alert = updateAvailable || alerts.size() ;
|
||||
|
||||
if (updateAvailable){
|
||||
//If there is update available, don't show alerts
|
||||
alerts.clear();
|
||||
|
||||
QFrame *f = new QFrame();
|
||||
|
||||
QVBoxLayout *update_layout = new QVBoxLayout;
|
||||
update_layout->addWidget(new QLabel("Update available"));
|
||||
|
||||
std::vector<char> release_notes_bytes = Params().read_db_bytes("ReleaseNotes");
|
||||
QString releaseNotes = vectorToQString(release_notes_bytes);
|
||||
QLabel *notes_label = new QLabel(releaseNotes);
|
||||
notes_label->setWordWrap(true);
|
||||
update_layout->addSpacing(20);
|
||||
update_layout->addWidget(notes_label);
|
||||
update_layout->addSpacing(20);
|
||||
|
||||
QPushButton *update_button = new QPushButton("Reboot and Update");
|
||||
update_layout->addWidget(update_button);
|
||||
update_layout->setMargin(10);
|
||||
#ifdef __aarch64__
|
||||
QObject::connect(update_button, &QPushButton::released,[=]() {std::system("sudo reboot");});
|
||||
#endif
|
||||
|
||||
f->setLayout(update_layout);
|
||||
f->setStyleSheet(R"(
|
||||
.QFrame{
|
||||
border-radius: 30px;
|
||||
border: 2px solid white;
|
||||
background-color: #114267;
|
||||
}
|
||||
QLabel{
|
||||
font-size: 60px;
|
||||
background-color: #114267;
|
||||
}
|
||||
)");
|
||||
|
||||
vlayout->addWidget(f);
|
||||
vlayout->addSpacing(60);
|
||||
}else{
|
||||
vlayout->addSpacing(60);
|
||||
|
||||
for (auto alert : alerts){
|
||||
QLabel *l = new QLabel(alert.text);
|
||||
l->setWordWrap(true);
|
||||
l->setMargin(60);
|
||||
|
||||
if (alert.severity){
|
||||
l->setStyleSheet(R"(
|
||||
QLabel {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
border-radius: 30px;
|
||||
background-color: #971b1c;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: white;
|
||||
}
|
||||
)");//red rounded rectange with white surround
|
||||
}else{
|
||||
l->setStyleSheet(R"(
|
||||
QLabel {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
border-radius: 30px;
|
||||
background-color: #114267;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: white;
|
||||
}
|
||||
)");//blue rounded rectange with white surround
|
||||
}
|
||||
|
||||
vlayout->addWidget(l);
|
||||
vlayout->addSpacing(20);
|
||||
}
|
||||
|
||||
//Pad the vlayout
|
||||
for (int i = alerts.size(); i < 4; i++){
|
||||
QWidget *w = new QWidget();
|
||||
vlayout->addWidget(w);
|
||||
vlayout->addSpacing(50);
|
||||
}
|
||||
}
|
||||
|
||||
QPushButton *hide_alerts_button = new QPushButton(updateAvailable ? "Later" : "Hide alerts");
|
||||
vlayout->addWidget(hide_alerts_button);
|
||||
QObject::connect(hide_alerts_button, 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<char> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
#include <QTimer>
|
||||
#include <QCheckBox>
|
||||
#include <QStackedLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
struct Alert{
|
||||
QString text;
|
||||
int severity;
|
||||
};
|
||||
|
||||
class OffroadAlert : public QWidget{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OffroadAlert(QWidget *parent = 0);
|
||||
bool show_alert;
|
||||
QVector<Alert> alerts;
|
||||
|
||||
private:
|
||||
QVBoxLayout *vlayout;
|
||||
|
||||
void parse_alerts();
|
||||
|
||||
signals:
|
||||
void closeAlerts();
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
};
|
||||
@@ -79,6 +79,7 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
void MainWindow::openSettings() {
|
||||
main_layout->setCurrentIndex(1);
|
||||
settingsWindow->refreshParams();
|
||||
}
|
||||
|
||||
void MainWindow::closeSettings() {
|
||||
|
||||
Reference in New Issue
Block a user