Qt setup + installer (#2511)
	
		
	
				
					
				
			* getting started * setup screens * cleanupg * url input * installer * setup * installerpull/214/head
							parent
							
								
									91f79acac3
								
							
						
					
					
						commit
						7b72bbe9f3
					
				
				 5 changed files with 283 additions and 0 deletions
			
			
		| @ -0,0 +1,68 @@ | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
| #include <cstdlib> | ||||
| #include <iostream> | ||||
| 
 | ||||
| #ifndef BRANCH | ||||
| #define BRANCH "master" | ||||
| #endif | ||||
| 
 | ||||
| #define GIT_CLONE_COMMAND "git clone https://github.com/commaai/openpilot.git"
 | ||||
| 
 | ||||
| #define CONTINUE_PATH "/home/comma/continue.sh" | ||||
| 
 | ||||
| bool time_valid() { | ||||
|   time_t rawtime; | ||||
|   time(&rawtime); | ||||
| 
 | ||||
|   struct tm * sys_time = gmtime(&rawtime); | ||||
|   return (1900 + sys_time->tm_year) >= 2019; | ||||
| } | ||||
| 
 | ||||
| int fresh_clone() { | ||||
|   int err; | ||||
| 
 | ||||
|   // Cleanup
 | ||||
|   err = std::system("rm -rf /tmp/openpilot"); | ||||
|   if(err) return 1; | ||||
|   err = std::system("rm -rf /data/openpilot"); | ||||
|   if(err) return 1; | ||||
| 
 | ||||
|   // Clone
 | ||||
|   err = std::system(GIT_CLONE_COMMAND " -b " BRANCH " --depth=1 /tmp/openpilot"); | ||||
|   if(err) return 1; | ||||
|   err = std::system("cd /tmp/openpilot && git submodule update --init"); | ||||
|   if(err) return 1; | ||||
| 
 | ||||
|   err = std::system("mv /tmp/openpilot /data"); | ||||
|   if(err) return 1; | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int install() { 
 | ||||
|   int err; | ||||
| 
 | ||||
|   // TODO: Disable SSH after install done
 | ||||
| 
 | ||||
|   // Wait for valid time
 | ||||
|   while (!time_valid()) { | ||||
|     usleep(500 * 1000); | ||||
|     std::cout << "Waiting for valid time\n"; | ||||
|   } | ||||
| 
 | ||||
|   std::cout << "Doing fresh clone\n"; | ||||
|   err = fresh_clone(); | ||||
|   if(err) return 1; | ||||
| 
 | ||||
|   // Write continue.sh
 | ||||
|   err = std::system("cp /data/openpilot/installer/continue_openpilot.sh " CONTINUE_PATH); | ||||
|   if(err == -1) return 1; | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
|   // TODO: make a small installation UI
 | ||||
|   return install(); | ||||
| } | ||||
| @ -0,0 +1,184 @@ | ||||
| #include <stdio.h> | ||||
| #include <curl/curl.h> | ||||
| 
 | ||||
| #include <QString> | ||||
| #include <QLabel> | ||||
| #include <QWidget> | ||||
| #include <QLineEdit> | ||||
| #include <QPushButton> | ||||
| #include <QVBoxLayout> | ||||
| #include <QApplication> | ||||
| 
 | ||||
| #include "setup.hpp" | ||||
| 
 | ||||
| #ifdef QCOM2 | ||||
| #include <qpa/qplatformnativeinterface.h> | ||||
| #include <QPlatformSurfaceEvent> | ||||
| #include <wayland-client-protocol.h> | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| int download(std::string url) { | ||||
|   CURL *curl; | ||||
|   curl = curl_easy_init(); | ||||
|   if (!curl) return -1; | ||||
| 
 | ||||
|   FILE *fp; | ||||
|   fp = fopen("/tmp/installer", "wb"); | ||||
|   curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); | ||||
|   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL); | ||||
|   curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); | ||||
|   curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); | ||||
|   curl_easy_perform(curl); | ||||
|   curl_easy_cleanup(curl); | ||||
|   fclose(fp); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| QLabel * title_label(QString text) { | ||||
|   QLabel *l = new QLabel(text); | ||||
|   l->setStyleSheet(R"( | ||||
|     QLabel { | ||||
|       font-size: 100px; | ||||
|       font-weight: bold; | ||||
|     } | ||||
|   )"); | ||||
|   return l; | ||||
| } | ||||
| 
 | ||||
| QWidget * Setup::getting_started() { | ||||
|   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||
|   main_layout->setContentsMargins(200, 100, 200, 100); | ||||
| 
 | ||||
|   main_layout->addWidget(title_label("Getting Started"), 0, Qt::AlignCenter); | ||||
| 
 | ||||
|   QLabel *body = new QLabel("Before we get on the road, let's finish\ninstallation and cover some details."); | ||||
|   body->setStyleSheet(R"(font-size: 65px;)"); | ||||
|   main_layout->addWidget(body, 0, Qt::AlignCenter); | ||||
| 
 | ||||
|   main_layout->addSpacing(100); | ||||
| 
 | ||||
|   QPushButton *btn = new QPushButton("Continue"); | ||||
|   main_layout->addWidget(btn); | ||||
|   QObject::connect(btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||
| 
 | ||||
|   main_layout->addSpacing(100); | ||||
| 
 | ||||
|   QWidget *widget = new QWidget(); | ||||
|   widget->setLayout(main_layout); | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| QWidget * Setup::network_setup() { | ||||
|   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||
|   main_layout->setMargin(100); | ||||
| 
 | ||||
|   main_layout->addWidget(title_label("Connect to WiFi"), 0, Qt::AlignCenter); | ||||
| 
 | ||||
|   QPushButton *btn = new QPushButton("Continue"); | ||||
|   main_layout->addWidget(btn); | ||||
|   QObject::connect(btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||
| 
 | ||||
|   QWidget *widget = new QWidget(); | ||||
|   widget->setLayout(main_layout); | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| QWidget * Setup::software_selection() { | ||||
|   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||
|   main_layout->setMargin(100); | ||||
| 
 | ||||
|   main_layout->addWidget(title_label("Choose Software"), 0, Qt::AlignCenter); | ||||
| 
 | ||||
|   QPushButton *dashcam_btn = new QPushButton("Dashcam"); | ||||
|   main_layout->addWidget(dashcam_btn); | ||||
|   QObject::connect(dashcam_btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||
| 
 | ||||
|   main_layout->addSpacing(50); | ||||
| 
 | ||||
|   const char* env_url = getenv("CUSTOM_URL"); | ||||
|   QString default_url = env_url == NULL ? "" : QString::fromStdString(env_url); | ||||
|   url_input = new QLineEdit(default_url); | ||||
|   url_input->setStyleSheet(R"( | ||||
|     color: black; | ||||
|     background-color: white; | ||||
|     font-size: 55px; | ||||
|     padding: 40px; | ||||
|   )"); | ||||
|   main_layout->addWidget(url_input); | ||||
| 
 | ||||
|   QPushButton *custom_btn = new QPushButton("Custom"); | ||||
|   main_layout->addWidget(custom_btn); | ||||
|   QObject::connect(custom_btn, SIGNAL(released()), this, SLOT(nextPage())); | ||||
| 
 | ||||
|   QWidget *widget = new QWidget(); | ||||
|   widget->setLayout(main_layout); | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| QWidget * Setup::downloading() { | ||||
|   QVBoxLayout *main_layout = new QVBoxLayout(); | ||||
| 
 | ||||
|   main_layout->addWidget(title_label("Downloading..."), 0, Qt::AlignCenter); | ||||
| 
 | ||||
|   QWidget *widget = new QWidget(); | ||||
|   widget->setLayout(main_layout); | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| void Setup::nextPage() { | ||||
|   layout->setCurrentIndex(layout->currentIndex() + 1); | ||||
| 
 | ||||
|   // start download
 | ||||
|   if (layout->currentIndex() == layout->count() - 1)  { | ||||
|     std::string url = url_input->text().toStdString(); | ||||
|     download(url); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Setup::Setup(QWidget *parent) { | ||||
|   layout = new QStackedLayout(); | ||||
|   layout->addWidget(getting_started()); | ||||
|   layout->addWidget(network_setup()); | ||||
|   layout->addWidget(software_selection()); | ||||
|   layout->addWidget(downloading()); | ||||
| 
 | ||||
|   setLayout(layout); | ||||
|   setStyleSheet(R"( | ||||
|     QWidget { | ||||
|       color: white; | ||||
|       background-color: black; | ||||
|     } | ||||
|     QPushButton { | ||||
|       font-size: 60px; | ||||
|       padding: 60px; | ||||
|       width: 800px; | ||||
|       color: white; | ||||
|       background-color: blue; | ||||
|     } | ||||
|   )"); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
| #ifdef QCOM2 | ||||
|   int w = 2160, h = 1080; | ||||
| #else | ||||
|   int w = 1920, h = 1080; | ||||
| #endif | ||||
| 
 | ||||
|   QApplication a(argc, argv); | ||||
| 
 | ||||
|   Setup setup; | ||||
|   setup.setFixedSize(w, h); | ||||
|   setup.show(); | ||||
| 
 | ||||
| #ifdef QCOM2 | ||||
|   QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); | ||||
|   wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", setup.windowHandle())); | ||||
|   wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270); | ||||
|   wl_surface_commit(s); | ||||
|   setup.showFullScreen(); | ||||
| #endif | ||||
| 
 | ||||
|   return a.exec(); | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| #include <QWidget> | ||||
| #include <QLineEdit> | ||||
| #include <QStackedLayout> | ||||
| 
 | ||||
| class Setup : public QWidget { | ||||
|   Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|   explicit Setup(QWidget *parent = 0); | ||||
| 
 | ||||
| private: | ||||
|   QStackedLayout *layout; | ||||
| 
 | ||||
|   QLineEdit *url_input; | ||||
| 
 | ||||
|   QWidget *getting_started(); | ||||
|   QWidget *network_setup(); | ||||
|   QWidget *software_selection(); | ||||
|   QWidget *downloading(); | ||||
| 
 | ||||
| public slots: | ||||
|   void nextPage(); | ||||
| }; | ||||
					Loading…
					
					
				
		Reference in new issue