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 that
old-commit-hash: c4e63d14ab
			
			
				taco
			
			
		
							parent
							
								
									7cd138328e
								
							
						
					
					
						commit
						46cfb5c45b
					
				
				 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