Qt offroad home screen (#2672)
	
		
	
				
					
				
			* some cleanup first * home sweet home * basic home screen * date * fix touch * fix mac * hide when onroad * box layout didn't do what i thoughtpull/214/head
							parent
							
								
									05fe01e30b
								
							
						
					
					
						commit
						fed642c4ed
					
				
				 9 changed files with 341 additions and 261 deletions
			
			
		@ -0,0 +1,220 @@ | 
				
			||||
#include <cmath> | 
				
			||||
#include <iostream> | 
				
			||||
#include <fstream> | 
				
			||||
#include <thread> | 
				
			||||
 | 
				
			||||
#include <QLabel> | 
				
			||||
#include <QMouseEvent> | 
				
			||||
#include <QHBoxLayout> | 
				
			||||
#include <QVBoxLayout> | 
				
			||||
#include <QDateTime> | 
				
			||||
 | 
				
			||||
#include "common/params.h" | 
				
			||||
 | 
				
			||||
#include "home.hpp" | 
				
			||||
#include "paint.hpp" | 
				
			||||
#include "qt_window.hpp" | 
				
			||||
 | 
				
			||||
#define BACKLIGHT_DT 0.25 | 
				
			||||
#define BACKLIGHT_TS 2.00 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
QWidget * home_widget() { | 
				
			||||
  QVBoxLayout *main_layout = new QVBoxLayout(); | 
				
			||||
  main_layout->setContentsMargins(sbr_w + 50, 50, 50, 50); | 
				
			||||
 | 
				
			||||
  // header
 | 
				
			||||
  QHBoxLayout *header_layout = new QHBoxLayout(); | 
				
			||||
  QString date_str = QDateTime::currentDateTime().toString("dddd, MMMM d"); | 
				
			||||
  QLabel *date = new QLabel(date_str); | 
				
			||||
  date->setStyleSheet(R"(font-size: 55px;)"); | 
				
			||||
  header_layout->addWidget(date, 0, Qt::AlignTop | Qt::AlignLeft); | 
				
			||||
 | 
				
			||||
  QLabel *version = new QLabel(QString::fromStdString("openpilot v" + Params().get("Version"))); | 
				
			||||
  version->setStyleSheet(R"(font-size: 45px;)"); | 
				
			||||
  header_layout->addWidget(version, 0, Qt::AlignTop | Qt::AlignRight); | 
				
			||||
 | 
				
			||||
  main_layout->addLayout(header_layout); | 
				
			||||
 | 
				
			||||
  // center
 | 
				
			||||
  QLabel *drive = new QLabel("Drive me"); | 
				
			||||
  drive->setStyleSheet(R"(font-size: 175px;)"); | 
				
			||||
  main_layout->addWidget(drive, 1, Qt::AlignHCenter); | 
				
			||||
 | 
				
			||||
  QWidget *w = new QWidget(); | 
				
			||||
  w->setLayout(main_layout); | 
				
			||||
  w->setStyleSheet(R"( | 
				
			||||
    * { | 
				
			||||
      background-color: none; | 
				
			||||
    } | 
				
			||||
  )"); | 
				
			||||
  return w; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
HomeWindow::HomeWindow(QWidget *parent) : QWidget(parent) { | 
				
			||||
 | 
				
			||||
  layout = new QGridLayout; | 
				
			||||
  layout->setMargin(0); | 
				
			||||
 | 
				
			||||
  glWindow = new GLWindow(this); | 
				
			||||
  layout->addWidget(glWindow, 0, 0); | 
				
			||||
 | 
				
			||||
  home = home_widget(); | 
				
			||||
  layout->addWidget(home, 0, 0); | 
				
			||||
  QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SLOT(setVisibility(bool))); | 
				
			||||
 | 
				
			||||
  setLayout(layout); | 
				
			||||
  setStyleSheet(R"( | 
				
			||||
    * { | 
				
			||||
      color: white; | 
				
			||||
    } | 
				
			||||
  )"); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void HomeWindow::setVisibility(bool offroad) { | 
				
			||||
  home->setVisible(offroad); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void HomeWindow::mousePressEvent(QMouseEvent *e) { | 
				
			||||
  UIState *ui_state = glWindow->ui_state; | 
				
			||||
 | 
				
			||||
  glWindow->wake(); | 
				
			||||
 | 
				
			||||
  // Settings button click
 | 
				
			||||
  if (!ui_state->scene.uilayout_sidebarcollapsed && settings_btn.ptInRect(e->x(), e->y())) { | 
				
			||||
    emit openSettings(); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // Vision click
 | 
				
			||||
  if (ui_state->started && (e->x() >= ui_state->scene.viz_rect.x - bdr_s)){ | 
				
			||||
    ui_state->scene.uilayout_sidebarcollapsed = !ui_state->scene.uilayout_sidebarcollapsed; | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
 | 
				
			||||
static void handle_display_state(UIState *s, int dt, bool user_input) { | 
				
			||||
  static int awake_timeout = 0; | 
				
			||||
  awake_timeout = std::max(awake_timeout-dt, 0); | 
				
			||||
 | 
				
			||||
  if (user_input || s->ignition || s->started) { | 
				
			||||
    s->awake = true; | 
				
			||||
    awake_timeout = 30*UI_FREQ; | 
				
			||||
  } else if (awake_timeout == 0){ | 
				
			||||
    s->awake = false; | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
static void set_backlight(int brightness){ | 
				
			||||
  std::ofstream brightness_control("/sys/class/backlight/panel0-backlight/brightness"); | 
				
			||||
  if (brightness_control.is_open()){ | 
				
			||||
    brightness_control << brightness << "\n"; | 
				
			||||
    brightness_control.close(); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
 | 
				
			||||
GLWindow::GLWindow(QWidget *parent) : QOpenGLWidget(parent) { | 
				
			||||
  timer = new QTimer(this); | 
				
			||||
  QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate())); | 
				
			||||
 | 
				
			||||
  backlight_timer = new QTimer(this); | 
				
			||||
  QObject::connect(backlight_timer, SIGNAL(timeout()), this, SLOT(backlightUpdate())); | 
				
			||||
 | 
				
			||||
  int result = read_param(&brightness_b, "BRIGHTNESS_B", true); | 
				
			||||
  result += read_param(&brightness_m, "BRIGHTNESS_M", true); | 
				
			||||
  if(result != 0) { | 
				
			||||
    brightness_b = 200.0; | 
				
			||||
    brightness_m = 10.0; | 
				
			||||
  } | 
				
			||||
  smooth_brightness = 512; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
GLWindow::~GLWindow() { | 
				
			||||
  makeCurrent(); | 
				
			||||
  doneCurrent(); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::initializeGL() { | 
				
			||||
  initializeOpenGLFunctions(); | 
				
			||||
  std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl; | 
				
			||||
  std::cout << "OpenGL vendor: " << glGetString(GL_VENDOR) << std::endl; | 
				
			||||
  std::cout << "OpenGL renderer: " << glGetString(GL_RENDERER) << std::endl; | 
				
			||||
  std::cout << "OpenGL language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; | 
				
			||||
 | 
				
			||||
  ui_state = new UIState(); | 
				
			||||
  ui_state->sound = &sound; | 
				
			||||
  ui_state->fb_w = vwp_w; | 
				
			||||
  ui_state->fb_h = vwp_h; | 
				
			||||
  ui_init(ui_state); | 
				
			||||
 | 
				
			||||
  wake(); | 
				
			||||
 | 
				
			||||
  timer->start(0); | 
				
			||||
  backlight_timer->start(BACKLIGHT_DT * 100); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::backlightUpdate(){ | 
				
			||||
  // Update brightness
 | 
				
			||||
  float k = (BACKLIGHT_DT / BACKLIGHT_TS) / (1.0f + BACKLIGHT_DT / BACKLIGHT_TS); | 
				
			||||
 | 
				
			||||
  float clipped_brightness = std::min(1023.0f, (ui_state->light_sensor*brightness_m) + brightness_b); | 
				
			||||
  smooth_brightness = clipped_brightness * k + smooth_brightness * (1.0f - k); | 
				
			||||
  int brightness = smooth_brightness; | 
				
			||||
 | 
				
			||||
  if (!ui_state->awake){ | 
				
			||||
    brightness = 0; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  std::thread{set_backlight, brightness}.detach(); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::timerUpdate() { | 
				
			||||
  if (ui_state->started != onroad){ | 
				
			||||
    onroad = ui_state->started; | 
				
			||||
    emit offroadTransition(!onroad); | 
				
			||||
#ifdef QCOM2 | 
				
			||||
    timer->setInterval(onroad ? 0 : 1000); | 
				
			||||
#endif | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // Fix awake timeout if running 1 Hz when offroad
 | 
				
			||||
  int dt = timer->interval() == 0 ? 1 : 20; | 
				
			||||
  handle_display_state(ui_state, dt, false); | 
				
			||||
 | 
				
			||||
  ui_update(ui_state); | 
				
			||||
  repaint(); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::resizeGL(int w, int h) { | 
				
			||||
  std::cout << "resize " << w << "x" << h << std::endl; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::paintGL() { | 
				
			||||
  ui_draw(ui_state); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void GLWindow::wake(){ | 
				
			||||
  // UI state might not be initialized yet
 | 
				
			||||
  if (ui_state != nullptr){ | 
				
			||||
    handle_display_state(ui_state, 1, true); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
GLuint visionimg_to_gl(const VisionImg *img, EGLImageKHR *pkhr, void **pph) { | 
				
			||||
  unsigned int texture; | 
				
			||||
  glGenTextures(1, &texture); | 
				
			||||
  glBindTexture(GL_TEXTURE_2D, texture); | 
				
			||||
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, *pph); | 
				
			||||
  glGenerateMipmap(GL_TEXTURE_2D); | 
				
			||||
  *pkhr = (EGLImageKHR)1; // not NULL
 | 
				
			||||
  return texture; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void visionimg_destroy_gl(EGLImageKHR khr, void *ph) { | 
				
			||||
  // empty
 | 
				
			||||
} | 
				
			||||
 | 
				
			||||
FramebufferState* framebuffer_init(const char* name, int32_t layer, int alpha, | 
				
			||||
                                   int *out_w, int *out_h) { | 
				
			||||
  return (FramebufferState*)1; // not null
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,73 @@ | 
				
			||||
#pragma once | 
				
			||||
 | 
				
			||||
#include <QTimer> | 
				
			||||
#include <QWidget> | 
				
			||||
#include <QGridLayout> | 
				
			||||
#include <QStackedWidget> | 
				
			||||
#include <QOpenGLWidget> | 
				
			||||
#include <QOpenGLFunctions> | 
				
			||||
 | 
				
			||||
#include "qt_sound.hpp" | 
				
			||||
#include "ui/ui.hpp" | 
				
			||||
 | 
				
			||||
 | 
				
			||||
// container window for onroad NVG UI
 | 
				
			||||
class GLWindow : public QOpenGLWidget, protected QOpenGLFunctions { | 
				
			||||
  Q_OBJECT | 
				
			||||
 | 
				
			||||
public: | 
				
			||||
  using QOpenGLWidget::QOpenGLWidget; | 
				
			||||
  explicit GLWindow(QWidget *parent = 0); | 
				
			||||
  void wake(); | 
				
			||||
  ~GLWindow(); | 
				
			||||
 | 
				
			||||
  UIState *ui_state = nullptr; | 
				
			||||
 | 
				
			||||
signals: | 
				
			||||
  void offroadTransition(bool offroad); | 
				
			||||
 | 
				
			||||
protected: | 
				
			||||
  void initializeGL() override; | 
				
			||||
  void resizeGL(int w, int h) override; | 
				
			||||
  void paintGL() override; | 
				
			||||
 | 
				
			||||
private: | 
				
			||||
  QTimer *timer; | 
				
			||||
  QTimer *backlight_timer; | 
				
			||||
 | 
				
			||||
  QtSound sound; | 
				
			||||
 | 
				
			||||
  bool onroad = true; | 
				
			||||
 | 
				
			||||
  // TODO: this shouldn't be here
 | 
				
			||||
  float brightness_b = 0; | 
				
			||||
  float brightness_m = 0; | 
				
			||||
  float smooth_brightness = 0; | 
				
			||||
 | 
				
			||||
public slots: | 
				
			||||
  void timerUpdate(); | 
				
			||||
  void backlightUpdate(); | 
				
			||||
}; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
class HomeWindow : public QWidget { | 
				
			||||
  Q_OBJECT | 
				
			||||
 | 
				
			||||
public: | 
				
			||||
  explicit HomeWindow(QWidget *parent = 0); | 
				
			||||
  GLWindow *glWindow; | 
				
			||||
 | 
				
			||||
signals: | 
				
			||||
  void openSettings(); | 
				
			||||
 | 
				
			||||
protected: | 
				
			||||
  void mousePressEvent(QMouseEvent *e) override; | 
				
			||||
 | 
				
			||||
private: | 
				
			||||
  QWidget *home; | 
				
			||||
  QGridLayout *layout; | 
				
			||||
 | 
				
			||||
private slots: | 
				
			||||
  void setVisibility(bool offroad); | 
				
			||||
}; | 
				
			||||
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue