# include <QLabel>
# include <QFile>
# include <QPushButton>
# include <QJsonObject>
# include <QJsonDocument>
# 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 ( ) ;
updateAvailable = false ;
std : : vector < char > 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 : 55 px ;
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 : 20 px ;
border : 2 px solid white ;
background - color : # 114267 ;
}
QPushButton {
padding : 20 px ;
font - size : 35 px ;
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 : 40 px ;
font - weight : bold ;
border - radius : 30 px ;
border : 2 px 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 : 20 px ;
font - size : 35 px ;
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 < 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 ) ;
}
}
}