good updater experience (#25724)
	
		
	
				
					
				
			* good updater experience * set params on startup * no fetch on first loop * little type hinting * little more * update translations * always set params with valid overlay * wrap check * use the param * more wrapping * vanish * cleanup * remove thatpull/25695/head
							parent
							
								
									c7a0f23b45
								
							
						
					
					
						commit
						c4e63d14ab
					
				
				 18 changed files with 550 additions and 512 deletions
			
			
		| @ -0,0 +1,156 @@ | ||||
| #include "selfdrive/ui/qt/offroad/settings.h" | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <cmath> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <QDebug> | ||||
| #include <QLabel> | ||||
| 
 | ||||
| #include "common/params.h" | ||||
| #include "common/util.h" | ||||
| #include "selfdrive/ui/ui.h" | ||||
| #include "selfdrive/ui/qt/util.h" | ||||
| #include "selfdrive/ui/qt/widgets/controls.h" | ||||
| #include "selfdrive/ui/qt/widgets/input.h" | ||||
| #include "system/hardware/hw.h" | ||||
| 
 | ||||
| 
 | ||||
| void SoftwarePanel::checkForUpdates() { | ||||
|   std::system("pkill -SIGUSR1 -f selfdrive.updated"); | ||||
| } | ||||
| 
 | ||||
| SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) { | ||||
|   onroadLbl = new QLabel(tr("Updates are only downloaded while the car is off.")); | ||||
|   onroadLbl->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; padding-top: 30px; padding-bottom: 30px;"); | ||||
|   addItem(onroadLbl); | ||||
| 
 | ||||
|   // current version
 | ||||
|   versionLbl = new LabelControl(tr("Current Version"), ""); | ||||
|   addItem(versionLbl); | ||||
| 
 | ||||
|   // download update btn
 | ||||
|   downloadBtn = new ButtonControl(tr("Download"), tr("CHECK")); | ||||
|   connect(downloadBtn, &ButtonControl::clicked, [=]() { | ||||
|     downloadBtn->setEnabled(false); | ||||
|     if (downloadBtn->text() == tr("CHECK")) { | ||||
|       checkForUpdates(); | ||||
|     } else { | ||||
|       std::system("pkill -SIGHUP -f selfdrive.updated"); | ||||
|     } | ||||
|   }); | ||||
|   addItem(downloadBtn); | ||||
| 
 | ||||
|   // install update btn
 | ||||
|   installBtn = new ButtonControl(tr("Install Update"), tr("INSTALL")); | ||||
|   connect(installBtn, &ButtonControl::clicked, [=]() { | ||||
|     installBtn->setEnabled(false); | ||||
|     params.putBool("DoShutdown", true); | ||||
|   }); | ||||
|   addItem(installBtn); | ||||
| 
 | ||||
|   // branch selecting
 | ||||
|   targetBranchBtn = new ButtonControl(tr("Target Branch"), tr("SELECT")); | ||||
|   connect(targetBranchBtn, &ButtonControl::clicked, [=]() { | ||||
|     auto current = params.get("GitBranch"); | ||||
|     QStringList branches = QString::fromStdString(params.get("UpdaterAvailableBranches")).split(","); | ||||
|     for (QString b : {current.c_str(), "devel-staging", "devel", "master-ci", "master"}) { | ||||
|       auto i = branches.indexOf(b); | ||||
|       if (i >= 0) { | ||||
|         branches.removeAt(i); | ||||
|         branches.insert(0, b); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     QString cur = QString::fromStdString(params.get("UpdaterTargetBranch")); | ||||
|     QString selection = MultiOptionDialog::getSelection(tr("Select a branch"), branches, cur, this); | ||||
|     if (!selection.isEmpty()) { | ||||
|       params.put("UpdaterTargetBranch", selection.toStdString()); | ||||
|       targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); | ||||
|       checkForUpdates(); | ||||
|     } | ||||
|   }); | ||||
|   if (!params.getBool("IsTestedBranch")) { | ||||
|     addItem(targetBranchBtn); | ||||
|   } | ||||
| 
 | ||||
|   // uninstall button
 | ||||
|   auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL")); | ||||
|   connect(uninstallBtn, &ButtonControl::clicked, [&]() { | ||||
|     if (ConfirmationDialog::confirm(tr("Are you sure you want to uninstall?"), this)) { | ||||
|       params.putBool("DoUninstall", true); | ||||
|     } | ||||
|   }); | ||||
|   addItem(uninstallBtn); | ||||
| 
 | ||||
|   fs_watch = new QFileSystemWatcher(this); | ||||
|   QObject::connect(fs_watch, &QFileSystemWatcher::fileChanged, [=](const QString path) { | ||||
|     updateLabels(); | ||||
|   }); | ||||
| 
 | ||||
|   connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { | ||||
|     is_onroad = !offroad; | ||||
|     updateLabels(); | ||||
|   }); | ||||
| 
 | ||||
|   updateLabels(); | ||||
| } | ||||
| 
 | ||||
| void SoftwarePanel::showEvent(QShowEvent *event) { | ||||
|   // nice for testing on PC
 | ||||
|   installBtn->setEnabled(true); | ||||
| 
 | ||||
|   updateLabels(); | ||||
| } | ||||
| 
 | ||||
| void SoftwarePanel::updateLabels() { | ||||
|   // add these back in case the files got removed
 | ||||
|   fs_watch->addPath(QString::fromStdString(params.getParamPath("LastUpdateTime"))); | ||||
|   fs_watch->addPath(QString::fromStdString(params.getParamPath("UpdateFailedCount"))); | ||||
|   fs_watch->addPath(QString::fromStdString(params.getParamPath("UpdaterState"))); | ||||
|   fs_watch->addPath(QString::fromStdString(params.getParamPath("UpdateAvailable"))); | ||||
| 
 | ||||
|   if (!isVisible()) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   // updater only runs offroad
 | ||||
|   onroadLbl->setVisible(is_onroad); | ||||
|   downloadBtn->setVisible(!is_onroad); | ||||
| 
 | ||||
|   // download update
 | ||||
|   QString updater_state = QString::fromStdString(params.get("UpdaterState")); | ||||
|   bool failed = std::atoi(params.get("UpdateFailedCount").c_str()) > 0; | ||||
|   if (updater_state != "idle") { | ||||
|     downloadBtn->setEnabled(false); | ||||
|     downloadBtn->setValue(updater_state); | ||||
|   } else { | ||||
|     if (failed) { | ||||
|       downloadBtn->setText("CHECK"); | ||||
|       downloadBtn->setValue("failed to check for update"); | ||||
|     } else if (params.getBool("UpdaterFetchAvailable")) { | ||||
|       downloadBtn->setText("DOWNLOAD"); | ||||
|       downloadBtn->setValue("update available"); | ||||
|     } else { | ||||
|       QString lastUpdate = "never"; | ||||
|       auto tm = params.get("LastUpdateTime"); | ||||
|       if (!tm.empty()) { | ||||
|         lastUpdate = timeAgo(QDateTime::fromString(QString::fromStdString(tm + "Z"), Qt::ISODate)); | ||||
|       } | ||||
|       downloadBtn->setText("CHECK"); | ||||
|       downloadBtn->setValue("up to date, last checked " + lastUpdate); | ||||
|     } | ||||
|     downloadBtn->setEnabled(true); | ||||
|   } | ||||
|   targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); | ||||
| 
 | ||||
|   // current + new versions
 | ||||
|   versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription")).left(40)); | ||||
|   versionLbl->setDescription(QString::fromStdString(params.get("UpdaterCurrentReleaseNotes"))); | ||||
| 
 | ||||
|   installBtn->setVisible(!is_onroad && params.getBool("UpdateAvailable")); | ||||
|   installBtn->setValue(QString::fromStdString(params.get("UpdaterNewDescription")).left(35)); | ||||
|   installBtn->setDescription(QString::fromStdString(params.get("UpdaterNewReleaseNotes"))); | ||||
| 
 | ||||
|   update(); | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue