move offroad alerts to home screen (#2681)

* move offroad alerts to home screen

* offroad aletrs work, but sidebar doesn't look nice

* fix sidebar

* looks better

* cleanup

* little bigger

Co-authored-by: grekiki <gregor1234567890@gmail.com>
albatross
Adeeb Shihadeh 2020-12-04 15:21:55 -08:00 committed by GitHub
parent fcb3ed727b
commit 8320a153fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 192 additions and 156 deletions

View File

@ -3,10 +3,12 @@
#include <fstream>
#include <thread>
#include <QLabel>
#include <QWidget>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QLayout>
#include <QDateTime>
#include "common/params.h"
@ -19,14 +21,16 @@
#define BACKLIGHT_TS 2.00
QWidget * home_widget() {
OffroadHome::OffroadHome(QWidget *parent) : QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout();
main_layout->setContentsMargins(sbr_w + 50, 50, 50, 50);
center_layout = new QStackedLayout();
// header
QHBoxLayout *header_layout = new QHBoxLayout();
QString date_str = QDateTime::currentDateTime().toString("dddd, MMMM d");
QLabel *date = new QLabel(date_str);
date = new QLabel();
date->setStyleSheet(R"(font-size: 55px;)");
header_layout->addWidget(date, 0, Qt::AlignTop | Qt::AlignLeft);
@ -36,33 +40,91 @@ QWidget * home_widget() {
main_layout->addLayout(header_layout);
alert_notification = new QPushButton();
QObject::connect(alert_notification, SIGNAL(released()), this, SLOT(openAlerts()));
main_layout->addWidget(alert_notification, 0, Qt::AlignTop | Qt::AlignRight);
// center
QLabel *drive = new QLabel("Drive me");
drive->setStyleSheet(R"(font-size: 175px;)");
main_layout->addWidget(drive, 1, Qt::AlignHCenter);
center_layout->addWidget(drive);
QWidget *w = new QWidget();
w->setLayout(main_layout);
w->setStyleSheet(R"(
* {
background-color: none;
}
)");
return w;
alerts_widget = new OffroadAlert();
QObject::connect(alerts_widget, SIGNAL(closeAlerts()), this, SLOT(closeAlerts()));
center_layout->addWidget(alerts_widget);
center_layout->setAlignment(alerts_widget, Qt::AlignCenter);
main_layout->addLayout(center_layout, 1);
// set up refresh timer
timer = new QTimer(this);
QObject::connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
refresh();
timer->start(10 * 1000);
setLayout(main_layout);
setStyleSheet(R"(background-color: none;)");
}
HomeWindow::HomeWindow(QWidget *parent) : QWidget(parent) {
void OffroadHome::openAlerts() {
center_layout->setCurrentIndex(1);
}
void OffroadHome::closeAlerts() {
center_layout->setCurrentIndex(0);
}
void OffroadHome::refresh() {
bool first_refresh = !date->text().size();
if (!isVisible() && !first_refresh) {
return;
}
date->setText(QDateTime::currentDateTime().toString("dddd, MMMM d"));
// update alerts
alerts_widget->refresh();
if (!alerts_widget->alerts.size() && !alerts_widget->updateAvailable){
alert_notification->setVisible(false);
return;
}
if (alerts_widget->updateAvailable){
// There is a new release
alert_notification->setText("UPDATE");
} else {
int alerts = alerts_widget->alerts.size();
alert_notification->setText(QString::number(alerts) + " ALERT" + (alerts == 1 ? "" : "S"));
}
alert_notification->setVisible(true);
alert_notification->setStyleSheet(QString(R"(
padding: 15px;
padding-left: 30px;
padding-right: 30px;
border: 1px solid;
border-radius: 5px;
font-size: 40px;
font-weight: bold;
background-color: red;
)"));
}
HomeWindow::HomeWindow(QWidget *parent) : QWidget(parent) {
layout = new QGridLayout;
layout->setMargin(0);
// onroad UI
glWindow = new GLWindow(this);
layout->addWidget(glWindow, 0, 0);
home = home_widget();
// draw offroad UI on top of onroad UI
home = new OffroadHome();
layout->addWidget(home, 0, 0);
QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SLOT(setVisibility(bool)));
QObject::connect(this, SIGNAL(openSettings()), home, SLOT(refresh()));
setLayout(layout);
setStyleSheet(R"(
* {

View File

@ -1,13 +1,17 @@
#pragma once
#include <QLabel>
#include <QTimer>
#include <QWidget>
#include <QGridLayout>
#include <QStackedWidget>
#include <QStackedLayout>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QPushButton>
#include "qt_sound.hpp"
#include "widgets/offroad_alerts.hpp"
#include "ui/ui.hpp"
@ -49,6 +53,28 @@ public slots:
void backlightUpdate();
};
// offroad home screen
class OffroadHome : public QWidget {
Q_OBJECT
public:
explicit OffroadHome(QWidget *parent = 0);
private:
QTimer *timer;
// offroad home screen widgets
QLabel *date;
QStackedLayout *center_layout;
OffroadAlert *alerts_widget;
QPushButton *alert_notification;
public slots:
void closeAlerts();
void openAlerts();
void refresh();
};
class HomeWindow : public QWidget {
Q_OBJECT
@ -64,8 +90,8 @@ protected:
void mousePressEvent(QMouseEvent *e) override;
private:
QWidget *home;
QGridLayout *layout;
OffroadHome *home;
private slots:
void setVisibility(bool offroad);

View File

@ -227,15 +227,6 @@ 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 = {
{"developer", developer_panel()},
@ -263,11 +254,6 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) {
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);
@ -288,55 +274,6 @@ 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->setVisible(false);
}

View File

@ -7,7 +7,6 @@
#include <QStackedLayout>
#include "wifi.hpp"
#include "widgets/offroad_alerts.hpp"
// *** settings widgets ***
@ -33,7 +32,6 @@ class SettingsWindow : public QWidget {
public:
explicit SettingsWindow(QWidget *parent = 0);
void refreshParams();
signals:
void closeSettings();
@ -41,14 +39,11 @@ signals:
private:
QPushButton *sidebar_alert_widget;
QWidget *sidebar_widget;
OffroadAlert *alerts_widget;
std::map<QString, QWidget *> panels;
QStackedLayout *panel_layout;
public slots:
void setActivePanel();
void closeAlerts();
void openAlerts();
void closeSidebar();
void openSidebar();
};

View File

@ -1,8 +1,8 @@
#include <QWidget>
#include <QLabel>
#include <QFile>
#include <QJsonDocument>
#include <QPushButton>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDebug>
#include "offroad_alerts.hpp"
@ -32,110 +32,99 @@ OffroadAlert::OffroadAlert(QWidget* parent){
setLayout(vlayout);
}
void OffroadAlert::refresh(){
void OffroadAlert::refresh() {
cleanLayout(vlayout);
parse_alerts();
bool updateAvailable = false;
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
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->addWidget(new QLabel("Update available"));
update_layout->setMargin(10);
update_layout->setSpacing(20);
std::vector<char> release_notes_bytes = Params().read_db_bytes("ReleaseNotes");
QString releaseNotes = vectorToQString(release_notes_bytes);
QLabel *notes_label = new QLabel(releaseNotes);
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->addSpacing(20);
update_layout->addWidget(notes_label);
update_layout->addSpacing(20);
update_layout->addWidget(notes_label, 1, Qt::AlignTop);
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");});
QObject::connect(update_button, &QPushButton::released, [=]() {std::system("sudo reboot");});
#endif
f->setLayout(update_layout);
f->setStyleSheet(R"(
.QFrame{
border-radius: 30px;
border-radius: 20px;
border: 2px solid white;
background-color: #114267;
}
QLabel{
font-size: 60px;
background-color: #114267;
QPushButton {
padding: 20px;
font-size: 35px;
color: white;
background-color: blue;
}
)");
vlayout->addWidget(f);
vlayout->addSpacing(60);
}else{
} 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
}
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);
}
//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()));
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
// We launch in selfdrive/ui
QFile inFile("../controls/lib/alerts_offroad.json");
inFile.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray data = inFile.readAll();
@ -145,11 +134,11 @@ void OffroadAlert::parse_alerts(){
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();

View File

@ -1,25 +1,20 @@
#pragma once
#include <QWidget>
#include <QFrame>
#include <QTimer>
#include <QCheckBox>
#include <QStackedLayout>
#include <QPushButton>
#include <QVBoxLayout>
struct Alert{
struct Alert {
QString text;
int severity;
};
class OffroadAlert : public QWidget{
class OffroadAlert : public QWidget {
Q_OBJECT
public:
explicit OffroadAlert(QWidget *parent = 0);
bool show_alert;
QVector<Alert> alerts;
bool updateAvailable;
private:
QVBoxLayout *vlayout;

View File

@ -32,7 +32,6 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
void MainWindow::openSettings() {
main_layout->setCurrentWidget(settingsWindow);
settingsWindow->refreshParams();
}
void MainWindow::closeSettings() {

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
import os
import sys
import time
import json
from common.basedir import BASEDIR
from common.params import Params
from selfdrive.controls.lib.alertmanager import set_offroad_alert
if __name__ == "__main__":
params = Params()
with open(os.path.join(BASEDIR, "selfdrive/controls/lib/alerts_offroad.json")) as f:
offroad_alerts = json.load(f)
t = 10 if len(sys.argv) < 2 else int(sys.argv[1])
while True:
print("setting alert update")
params.put("UpdateAvailable", "1")
params.put("ReleaseNotes", "this is a new version")
time.sleep(t)
params.put("UpdateAvailable", "0")
# cycle through normal alerts
for a in offroad_alerts:
print("setting alert:", a)
set_offroad_alert(a, True)
time.sleep(t)
set_offroad_alert(a, False)
print("no alert")
time.sleep(t)