@ -10,20 +10,21 @@
# include <curl/curl.h>
# include "selfdrive/hardware/hw.h"
# include "selfdrive/ui/qt/api.h"
# include "selfdrive/ui/qt/qt_window.h"
# include "selfdrive/ui/qt/offroad/networking.h"
# include "selfdrive/ui/qt/widgets/input.h"
# include "selfdrive/ui/qt/qt_window.h"
# define USER_AGENT "AGNOSSetup-0.1"
const char * USER_AGENT = " AGNOSSetup-0.1 " ;
const QString DASHCAM_URL = " https://dashcam.comma.ai " ;
void Setup : : download ( QString url ) {
QCoreApplication : : processEvents ( QEventLoop : : AllEvents , 1000 ) ;
setCurrentIndex ( count ( ) - 2 ) ;
const QString TEST_URL = " https://api.commadotai.com/v1/me " ;
void Setup : : download ( QString url ) {
CURL * curl = curl_easy_init ( ) ;
if ( ! curl ) {
emit downloadFailed ( ) ;
emit finished ( false ) ;
return ;
}
char tmpfile [ ] = " /tmp/installer_XXXXXX " ;
@ -38,121 +39,245 @@ void Setup::download(QString url) {
int ret = curl_easy_perform ( curl ) ;
if ( ret ! = CURLE_OK ) {
emit downloadFailed ( ) ;
emit finished ( false ) ;
return ;
}
curl_easy_cleanup ( curl ) ;
fclose ( fp ) ;
rename ( tmpfile , " /tmp/installer " ) ;
emit finished ( true ) ;
}
QLabel * title_label ( QString text ) {
QLabel * l = new QLabel ( text ) ;
l - > setStyleSheet ( R " (
font - size : 100 px ;
font - weight : 500 ;
) " );
return l ;
}
QWidget * Setup : : build_page ( QString title , QWidget * content , bool next , bool prev ) {
QWidget * Setup : : getting_started ( ) {
QWidget * widget = new QWidget ( ) ;
QVBoxLayout * main_layout = new QVBoxLayout ( widget ) ;
main_layout - > setMargin ( 50 ) ;
main_layout - > addWidget ( title_label ( title ) , 0 , Qt : : AlignLeft | Qt : : AlignTop ) ;
QHBoxLayout * main_layout = new QHBoxLayout ( widget ) ;
main_layout - > setMargin ( 0 ) ;
main_layout - > addWidget ( content ) ;
QVBoxLayout * vlayout = new QVBoxLayout ( ) ;
vlayout - > setContentsMargins ( 165 , 280 , 100 , 0 ) ;
main_layout - > addLayout ( vlayout ) ;
QHBoxLayout * nav_layout = new QHBoxLayout ( ) ;
QLabel * title = new QLabel ( " Getting Started " ) ;
title - > setStyleSheet ( " font-size: 90px; font-weight: 500; " ) ;
vlayout - > addWidget ( title , 0 , Qt : : AlignTop | Qt : : AlignLeft ) ;
if ( prev ) {
QPushButton * back_btn = new QPushButton ( " Back " ) ;
nav_layout - > addWidget ( back_btn , 1 , Qt : : AlignBottom | Qt : : AlignLeft ) ;
QObject : : connect ( back_btn , & QPushButton : : released , this , & Setup : : prevPage ) ;
}
vlayout - > addSpacing ( 90 ) ;
QLabel * desc = new QLabel ( " Before we get on the road, let’s finish installation and cover some details. " ) ;
desc - > setWordWrap ( true ) ;
desc - > setStyleSheet ( " font-size: 80px; font-weight: 300; " ) ;
vlayout - > addWidget ( desc , 0 , Qt : : AlignTop | Qt : : AlignLeft ) ;
if ( next ) {
QPushButton * continue_btn = new QPushButton ( " Continue " ) ;
nav_layout - > addWidget ( continue_btn , 0 , Qt : : AlignBottom | Qt : : AlignRight ) ;
QObject : : connect ( continue_btn , & QPushButton : : released , this , & Setup : : nextPage ) ;
}
vlayout - > addStretch ( ) ;
main_layout - > addLayout ( nav_layout , 0 ) ;
return widget ;
}
QPushButton * btn = new QPushButton ( ) ;
btn - > setIcon ( QIcon ( " ../../../assets/img_continue_triangle.svg " ) ) ;
btn - > setIconSize ( QSize ( 54 , 106 ) ) ;
btn - > setFixedSize ( 310 , 1080 ) ;
btn - > setProperty ( " primary " , true ) ;
btn - > setStyleSheet ( " border: none; " ) ;
main_layout - > addWidget ( btn , 0 , Qt : : AlignRight ) ;
QObject : : connect ( btn , & QPushButton : : clicked , this , & Setup : : nextPage ) ;
QWidget * Setup : : getting_started ( ) {
QLabel * body = new QLabel ( " Before we get on the road, let's finish \n installation and cover some details. " ) ;
body - > setAlignment ( Qt : : AlignHCenter ) ;
body - > setStyleSheet ( R " (font-size: 80px;) " ) ;
return build_page ( " Getting Started " , body , true , false ) ;
return widget ;
}
QWidget * Setup : : network_setup ( ) {
QWidget * widget = new QWidget ( ) ;
QVBoxLayout * main_layout = new QVBoxLayout ( widget ) ;
main_layout - > setContentsMargins ( 55 , 50 , 55 , 50 ) ;
// title
QLabel * title = new QLabel ( " Connect to WiFi " ) ;
title - > setStyleSheet ( " font-size: 90px; font-weight: 500; " ) ;
main_layout - > addWidget ( title , 0 , Qt : : AlignLeft | Qt : : AlignTop ) ;
// wifi widget
Networking * wifi = new Networking ( this , false ) ;
return build_page ( " Connect to WiFi " , wifi , true , true ) ;
main_layout - > addWidget ( wifi , 1 ) ;
// back + continue buttons
QHBoxLayout * blayout = new QHBoxLayout ;
main_layout - > addLayout ( blayout ) ;
blayout - > setSpacing ( 50 ) ;
QPushButton * back = new QPushButton ( " Back " ) ;
back - > setObjectName ( " navBtn " ) ;
QObject : : connect ( back , & QPushButton : : clicked , this , & Setup : : prevPage ) ;
blayout - > addWidget ( back ) ;
QPushButton * cont = new QPushButton ( ) ;
cont - > setObjectName ( " navBtn " ) ;
QObject : : connect ( cont , & QPushButton : : clicked , this , & Setup : : nextPage ) ;
blayout - > addWidget ( cont ) ;
// setup timer for testing internet connection
HttpRequest * request = new HttpRequest ( this , TEST_URL , false , 2500 ) ;
QObject : : connect ( request , & HttpRequest : : requestDone , [ = ] ( bool success ) {
cont - > setEnabled ( success ) ;
cont - > setText ( success ? " Continue " : " Waiting for internet " ) ;
repaint ( ) ;
} ) ;
QTimer * timer = new QTimer ( this ) ;
QObject : : connect ( timer , & QTimer : : timeout , [ = ] ( ) {
if ( ! request - > active ( ) & & cont - > isVisible ( ) ) {
request - > sendRequest ( TEST_URL ) ;
}
} ) ;
timer - > start ( 1000 ) ;
return widget ;
}
QWidget * radio_button ( QString title , QButtonGroup * group ) {
QPushButton * btn = new QPushButton ( title ) ;
btn - > setCheckable ( true ) ;
group - > addButton ( btn ) ;
btn - > setStyleSheet ( R " (
QPushButton {
height : 230 ;
padding - left : 100 px ;
padding - right : 100 px ;
text - align : left ;
font - size : 80 px ;
font - weight : 400 ;
border - radius : 10 px ;
background - color : # 4F 4F 4F ;
}
QPushButton : checked {
background - color : # 465 BEA ;
}
) " );
// checkmark icon
QPixmap pix ( " ../../../assets/img_circled_check.svg " ) ;
btn - > setIcon ( pix ) ;
btn - > setIconSize ( QSize ( 0 , 0 ) ) ;
btn - > setLayoutDirection ( Qt : : RightToLeft ) ;
QObject : : connect ( btn , & QPushButton : : toggled , [ = ] ( bool checked ) {
btn - > setIconSize ( checked ? QSize ( 104 , 104 ) : QSize ( 0 , 0 ) ) ;
} ) ;
return btn ;
}
QWidget * Setup : : software_selection ( ) {
QWidget * widget = new QWidget ( ) ;
QVBoxLayout * main_layout = new QVBoxLayout ( widget ) ;
main_layout - > setContentsMargins ( 55 , 50 , 55 , 50 ) ;
main_layout - > setSpacing ( 0 ) ;
QPushButton * dashcam_btn = new QPushButton ( " Dashcam " ) ;
main_layout - > addWidget ( dashcam_btn ) ;
QObject : : connect ( dashcam_btn , & QPushButton : : released , this , [ = ] ( ) {
this - > download ( " https://dashcam.comma.ai " ) ;
} ) ;
// title
QLabel * title = new QLabel ( " Choose Software to Install " ) ;
title - > setStyleSheet ( " font-size: 90px; font-weight: 500; " ) ;
main_layout - > addWidget ( title , 0 , Qt : : AlignLeft | Qt : : AlignTop ) ;
main_layout - > addSpacing ( 50 ) ;
QPushButton * custom_btn = new QPushButton ( " Custom " ) ;
main_layout - > addWidget ( custom_btn ) ;
QObject : : connect ( custom_btn , & QPushButton : : released , this , [ = ] ( ) {
QString input_url = InputDialog : : getText ( " Enter URL " , this ) ;
if ( input_url . size ( ) ) {
this - > download ( input_url ) ;
// dashcam + custom radio buttons
QButtonGroup * group = new QButtonGroup ( widget ) ;
group - > setExclusive ( true ) ;
QWidget * dashcam = radio_button ( " Dashcam " , group ) ;
main_layout - > addWidget ( dashcam ) ;
main_layout - > addSpacing ( 30 ) ;
QWidget * custom = radio_button ( " Custom Software " , group ) ;
main_layout - > addWidget ( custom ) ;
main_layout - > addStretch ( ) ;
// back + continue buttons
QHBoxLayout * blayout = new QHBoxLayout ;
main_layout - > addLayout ( blayout ) ;
blayout - > setSpacing ( 50 ) ;
QPushButton * back = new QPushButton ( " Back " ) ;
back - > setObjectName ( " navBtn " ) ;
QObject : : connect ( back , & QPushButton : : clicked , this , & Setup : : prevPage ) ;
blayout - > addWidget ( back ) ;
QPushButton * cont = new QPushButton ( " Continue " ) ;
cont - > setObjectName ( " navBtn " ) ;
cont - > setEnabled ( false ) ;
blayout - > addWidget ( cont ) ;
QObject : : connect ( cont , & QPushButton : : clicked , [ = ] ( ) {
QString url = DASHCAM_URL ;
if ( group - > checkedButton ( ) ! = dashcam ) {
url = InputDialog : : getText ( " Enter URL " , this ) ;
}
if ( ! url . isEmpty ( ) ) {
setCurrentWidget ( downloading_widget ) ;
QTimer : : singleShot ( 100 , this , [ = ] ( ) {
download ( url ) ;
} ) ;
}
} ) ;
return build_page ( " Choose Software " , widget , false , true ) ;
connect ( group , QOverload < QAbstractButton * > : : of ( & QButtonGroup : : buttonClicked ) , [ = ] ( QAbstractButton * btn ) {
btn - > setChecked ( true ) ;
cont - > setEnabled ( true ) ;
} ) ;
return widget ;
}
QWidget * Setup : : downloading ( ) {
QWidget * widget = new QWidget ( ) ;
QVBoxLayout * main_layout = new QVBoxLayout ( widget ) ;
main_layout - > addWidget ( title_label ( " Downloading... " ) , 0 , Qt : : AlignCenter ) ;
QLabel * txt = new QLabel ( " Downloading... " ) ;
txt - > setStyleSheet ( " font-size: 90px; font-weight: 500; " ) ;
main_layout - > addWidget ( txt , 0 , Qt : : AlignCenter ) ;
return widget ;
}
QWidget * Setup : : download_failed ( ) {
QWidget * widget = new QWidget ( ) ;
QVBoxLayout * main_layout = new QVBoxLayout ( widget ) ;
main_layout - > setContentsMargins ( 50 , 50 , 50 , 50 ) ;
main_layout - > addWidget ( title_label ( " Download Failed " ) , 0 , Qt : : AlignLeft | Qt : : AlignTop ) ;
main_layout - > setContentsMargins ( 55 , 225 , 55 , 55 ) ;
main_layout - > setSpacing ( 0 ) ;
QLabel * title = new QLabel ( " Download Failed " ) ;
title - > setStyleSheet ( " font-size: 90px; font-weight: 500; " ) ;
main_layout - > addWidget ( title , 0 , Qt : : AlignTop | Qt : : AlignLeft ) ;
main_layout - > addSpacing ( 67 ) ;
QLabel * body = new QLabel ( " Ensure the entered URL is valid, and the device's network connection is good. " ) ;
QLabel * body = new QLabel ( " Ensure the entered URL is valid, and the device’s internet connection is good. " ) ;
body - > setWordWrap ( true ) ;
body - > setAlignment ( Qt : : AlignHCenter ) ;
body - > setStyleSheet ( R " (font-size: 80px;) " ) ;
body - > setAlignment ( Qt : : AlignTop | Qt : : AlignLeft ) ;
body - > setStyleSheet ( " font-size: 80px; font-weight: 300; margin-right: 100px; " ) ;
main_layout - > addWidget ( body ) ;
QHBoxLayout * nav_layout = new QHBoxLayout ( ) ;
main_layout - > addStretch ( ) ;
QPushButton * reboot_btn = new QPushButton ( " Reboot " ) ;
nav_layout - > addWidget ( reboot_btn , 0 , Qt : : AlignBottom | Qt : : AlignLeft ) ;
QObject : : connect ( reboot_btn , & QPushButton : : released , this , [ = ] ( ) {
if ( Hardware : : TICI ( ) ) {
std : : system ( " sudo reboot " ) ;
}
// reboot + start over buttons
QHBoxLayout * blayout = new QHBoxLayout ( ) ;
blayout - > setSpacing ( 50 ) ;
main_layout - > addLayout ( blayout , 0 ) ;
QPushButton * reboot = new QPushButton ( " Reboot device " ) ;
reboot - > setObjectName ( " navBtn " ) ;
blayout - > addWidget ( reboot ) ;
QObject : : connect ( reboot , & QPushButton : : released , this , [ = ] ( ) {
Hardware : : reboot ( ) ;
} ) ;
QPushButton * restart_btn = new QPushButton ( " Start over " ) ;
nav_layout - > addWidget ( restart_btn , 0 , Qt : : AlignBottom | Qt : : AlignRight ) ;
QObject : : connect ( restart_btn , & QPushButton : : released , this , [ = ] ( ) {
QPushButton * restart = new QPushButton ( " Start over " ) ;
restart - > setObjectName ( " navBtn " ) ;
restart - > setProperty ( " primary " , true ) ;
blayout - > addWidget ( restart ) ;
QObject : : connect ( restart , & QPushButton : : released , this , [ = ] ( ) {
setCurrentIndex ( 0 ) ;
} ) ;
main_layout - > addLayout ( nav_layout , 0 ) ;
widget - > setStyleSheet ( R " (
QLabel {
margin - left : 117 ;
}
) " );
return widget ;
}
@ -168,24 +293,47 @@ Setup::Setup(QWidget *parent) : QStackedWidget(parent) {
addWidget ( getting_started ( ) ) ;
addWidget ( network_setup ( ) ) ;
addWidget ( software_selection ( ) ) ;
addWidget ( downloading ( ) ) ;
addWidget ( download_failed ( ) ) ;
QObject : : connect ( this , & Setup : : downloadFailed , this , & Setup : : nextPage ) ;
downloading_widget = downloading ( ) ;
addWidget ( downloading_widget ) ;
failed_widget = download_failed ( ) ;
addWidget ( failed_widget ) ;
QObject : : connect ( this , & Setup : : finished , [ = ] ( bool success ) {
// hide setup on success
qDebug ( ) < < " finished " < < success ;
setVisible ( ! success ) ;
setCurrentWidget ( failed_widget ) ;
} ) ;
// TODO: revisit pressed bg color
setStyleSheet ( R " (
* {
font - family : Inter ;
color : white ;
font - family : Inter ;
}
Setup {
background - color : black ;
}
QPushButton {
padding : 50 px ;
padding - right : 100 px ;
padding - left : 100 px ;
border : 7 px solid white ;
border - radius : 20 px ;
font - size : 50 px ;
QPushButton # navBtn {
height : 160 ;
font - size : 55 px ;
font - weight : 400 ;
border - radius : 10 px ;
background - color : # 333333 ;
}
QPushButton # navBtn : disabled {
color : # 808080 ;
}
QPushButton # navBtn : pressed {
background - color : # 444444 ;
}
QPushButton [ primary = ' true ' ] , # navBtn [ primary = ' true ' ] {
background - color : # 465 BEA ;
}
QPushButton [ primary = ' true ' ] : pressed , # navBtn : pressed [ primary = ' true ' ] {
background - color : # 3049F 4 ;
}
) " );
}