UI: new class ListWidget (#21273)

* ListWidget

* continue

* remove function horizontal_line

* cleanup

* default spacing 25

* fix networkpanel margin on EON

* solid expanding

* 0 width

* cleanup

* apply reviews

* remove function addLayout,make it looks like QLIstWidget

* rename addWidget to addItem

* rebase master

* rebase master

* merge master

* cleanup

* fixed title bar position

* no flash while folding

* cleanup

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: abffc8b2ad
commatwo_master
Dean Lee 4 years ago committed by GitHub
parent e2332a0275
commit 2fefa32476
  1. 31
      selfdrive/ui/qt/offroad/networking.cc
  2. 75
      selfdrive/ui/qt/offroad/settings.cc
  3. 6
      selfdrive/ui/qt/offroad/settings.h
  4. 6
      selfdrive/ui/qt/widgets/controls.cc
  5. 36
      selfdrive/ui/qt/widgets/controls.h

@ -10,6 +10,7 @@
#include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h" #include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/ui/qt/widgets/controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h" #include "selfdrive/ui/qt/widgets/scrollview.h"
@ -123,11 +124,11 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
connect(back, &QPushButton::clicked, [=]() { emit backPress(); }); connect(back, &QPushButton::clicked, [=]() { emit backPress(); });
main_layout->addWidget(back, 0, Qt::AlignLeft); main_layout->addWidget(back, 0, Qt::AlignLeft);
ListWidget *list = new ListWidget(this);
// Enable tethering layout // Enable tethering layout
tetheringToggle = new ToggleControl("Enable Tethering", "", "", wifi->isTetheringEnabled()); tetheringToggle = new ToggleControl("Enable Tethering", "", "", wifi->isTetheringEnabled());
main_layout->addWidget(tetheringToggle); list->addItem(tetheringToggle);
QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering); QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering);
main_layout->addWidget(horizontal_line(), 0);
// Change tethering password // Change tethering password
ButtonControl *editPasswordButton = new ButtonControl("Tethering Password", "EDIT"); ButtonControl *editPasswordButton = new ButtonControl("Tethering Password", "EDIT");
@ -137,19 +138,15 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
wifi->changeTetheringPassword(pass); wifi->changeTetheringPassword(pass);
} }
}); });
main_layout->addWidget(editPasswordButton, 0); list->addItem(editPasswordButton);
main_layout->addWidget(horizontal_line(), 0);
// IP address // IP address
ipLabel = new LabelControl("IP Address", wifi->ipv4_address); ipLabel = new LabelControl("IP Address", wifi->ipv4_address);
main_layout->addWidget(ipLabel, 0); list->addItem(ipLabel);
main_layout->addWidget(horizontal_line(), 0);
// SSH keys // SSH keys
main_layout->addWidget(new SshToggle()); list->addItem(new SshToggle());
main_layout->addWidget(horizontal_line(), 0); list->addItem(new SshControl());
main_layout->addWidget(new SshControl());
main_layout->addWidget(horizontal_line(), 0);
// Roaming toggle // Roaming toggle
const bool roamingEnabled = params.getBool("GsmRoaming"); const bool roamingEnabled = params.getBool("GsmRoaming");
@ -159,8 +156,9 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
params.putBool("GsmRoaming", state); params.putBool("GsmRoaming", state);
wifi->setRoamingEnabled(state); wifi->setRoamingEnabled(state);
}); });
main_layout->addWidget(roamingToggle); list->addItem(roamingToggle);
main_layout->addWidget(list);
main_layout->addStretch(1); main_layout->addStretch(1);
} }
@ -253,7 +251,7 @@ void WifiUI::refresh() {
std::sort(sortedNetworks.begin(), sortedNetworks.end(), compare_by_strength); std::sort(sortedNetworks.begin(), sortedNetworks.end(), compare_by_strength);
// add networks // add networks
int i = 0; ListWidget *list = new ListWidget(this);
for (Network &network : sortedNetworks) { for (Network &network : sortedNetworks) {
QHBoxLayout *hlayout = new QHBoxLayout; QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->setContentsMargins(44, 0, 73, 0); hlayout->setContentsMargins(44, 0, 73, 0);
@ -309,13 +307,8 @@ void WifiUI::refresh() {
strength->setPixmap(strengths[std::clamp((int)round(network.strength / 33.), 0, 3)]); strength->setPixmap(strengths[std::clamp((int)round(network.strength / 33.), 0, 3)]);
hlayout->addWidget(strength, 0, Qt::AlignRight); hlayout->addWidget(strength, 0, Qt::AlignRight);
main_layout->addLayout(hlayout); list->addItem(hlayout);
// Don't add the last horizontal line
if (i+1 < wifi->seenNetworks.size()) {
main_layout->addWidget(horizontal_line(), 0);
}
i++;
} }
main_layout->addWidget(list);
main_layout->addStretch(1); main_layout->addStretch(1);
} }

@ -25,38 +25,34 @@
#include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h" #include "selfdrive/ui/qt/qt_window.h"
TogglesPanel::TogglesPanel(QWidget *parent) : QWidget(parent) { TogglesPanel::TogglesPanel(QWidget *parent) : ListWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this); addItem(new ParamControl("OpenpilotEnabledToggle",
QList<ParamControl*> toggles;
toggles.append(new ParamControl("OpenpilotEnabledToggle",
"Enable openpilot", "Enable openpilot",
"Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.", "Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.",
"../assets/offroad/icon_openpilot.png", "../assets/offroad/icon_openpilot.png",
this)); this));
toggles.append(new ParamControl("IsLdwEnabled", addItem(new ParamControl("IsLdwEnabled",
"Enable Lane Departure Warnings", "Enable Lane Departure Warnings",
"Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31mph (50kph).", "Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31mph (50kph).",
"../assets/offroad/icon_warning.png", "../assets/offroad/icon_warning.png",
this)); this));
toggles.append(new ParamControl("IsRHD", addItem(new ParamControl("IsRHD",
"Enable Right-Hand Drive", "Enable Right-Hand Drive",
"Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.", "Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.",
"../assets/offroad/icon_openpilot_mirrored.png", "../assets/offroad/icon_openpilot_mirrored.png",
this)); this));
toggles.append(new ParamControl("IsMetric", addItem(new ParamControl("IsMetric",
"Use Metric System", "Use Metric System",
"Display speed in km/h instead of mp/h.", "Display speed in km/h instead of mp/h.",
"../assets/offroad/icon_metric.png", "../assets/offroad/icon_metric.png",
this)); this));
toggles.append(new ParamControl("CommunityFeaturesToggle", addItem(new ParamControl("CommunityFeaturesToggle",
"Enable Community Features", "Enable Community Features",
"Use features from the open source community that are not maintained or supported by comma.ai and have not been confirmed to meet the standard safety model. These features include community supported cars and community supported hardware. Be extra cautious when using these features", "Use features from the open source community that are not maintained or supported by comma.ai and have not been confirmed to meet the standard safety model. These features include community supported cars and community supported hardware. Be extra cautious when using these features",
"../assets/offroad/icon_shell.png", "../assets/offroad/icon_shell.png",
this)); this));
toggles.append(new ParamControl("UploadRaw", addItem(new ParamControl("UploadRaw",
"Upload Raw Logs", "Upload Raw Logs",
"Upload full logs and full resolution video by default while on WiFi. If not enabled, individual logs can be marked for upload at my.comma.ai/useradmin.", "Upload full logs and full resolution video by default while on WiFi. If not enabled, individual logs can be marked for upload at my.comma.ai/useradmin.",
"../assets/offroad/icon_network.png", "../assets/offroad/icon_network.png",
@ -67,15 +63,15 @@ TogglesPanel::TogglesPanel(QWidget *parent) : QWidget(parent) {
"Upload data from the driver facing camera and help improve the driver monitoring algorithm.", "Upload data from the driver facing camera and help improve the driver monitoring algorithm.",
"../assets/offroad/icon_monitoring.png", "../assets/offroad/icon_monitoring.png",
this); this);
toggles.append(record_toggle); addItem(record_toggle);
toggles.append(new ParamControl("EndToEndToggle", addItem(new ParamControl("EndToEndToggle",
"\U0001f96c Disable use of lanelines (Alpha) \U0001f96c", "\U0001f96c Disable use of lanelines (Alpha) \U0001f96c",
"In this mode openpilot will ignore lanelines and just drive how it thinks a human would.", "In this mode openpilot will ignore lanelines and just drive how it thinks a human would.",
"../assets/offroad/icon_road.png", "../assets/offroad/icon_road.png",
this)); this));
#ifdef ENABLE_MAPS #ifdef ENABLE_MAPS
toggles.append(new ParamControl("NavSettingTime24h", addItem(new ParamControl("NavSettingTime24h",
"Show ETA in 24h format", "Show ETA in 24h format",
"Use 24h format instead of am/pm", "Use 24h format instead of am/pm",
"../assets/offroad/icon_metric.png", "../assets/offroad/icon_metric.png",
@ -84,23 +80,15 @@ TogglesPanel::TogglesPanel(QWidget *parent) : QWidget(parent) {
bool record_lock = Params().getBool("RecordFrontLock"); bool record_lock = Params().getBool("RecordFrontLock");
record_toggle->setEnabled(!record_lock); record_toggle->setEnabled(!record_lock);
for(ParamControl *toggle : toggles) {
if(main_layout->count() != 0) {
main_layout->addWidget(horizontal_line());
}
main_layout->addWidget(toggle);
}
} }
DevicePanel::DevicePanel(QWidget* parent) : QWidget(parent) { DevicePanel::DevicePanel(QWidget* parent) : ListWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this); setSpacing(50);
Params params = Params(); Params params = Params();
main_layout->addWidget(new LabelControl("Dongle ID", getDongleId().value_or("N/A"))); addItem(new LabelControl("Dongle ID", getDongleId().value_or("N/A")));
main_layout->addWidget(horizontal_line());
QString serial = QString::fromStdString(params.get("HardwareSerial", false)); QString serial = QString::fromStdString(params.get("HardwareSerial", false));
main_layout->addWidget(new LabelControl("Serial", serial)); addItem(new LabelControl("Serial", serial));
// offroad-only buttons // offroad-only buttons
@ -158,9 +146,8 @@ DevicePanel::DevicePanel(QWidget* parent) : QWidget(parent) {
for (auto btn : {dcamBtn, resetCalibBtn, retrainingBtn, regulatoryBtn}) { for (auto btn : {dcamBtn, resetCalibBtn, retrainingBtn, regulatoryBtn}) {
if (btn) { if (btn) {
main_layout->addWidget(horizontal_line());
connect(parent, SIGNAL(offroadTransition(bool)), btn, SLOT(setEnabled(bool))); connect(parent, SIGNAL(offroadTransition(bool)), btn, SLOT(setEnabled(bool)));
main_layout->addWidget(btn); addItem(btn);
} }
} }
@ -196,10 +183,10 @@ DevicePanel::DevicePanel(QWidget* parent) : QWidget(parent) {
#poweroff_btn { background-color: #E22C2C; } #poweroff_btn { background-color: #E22C2C; }
#poweroff_btn:pressed { background-color: #FF2424; } #poweroff_btn:pressed { background-color: #FF2424; }
)"); )");
main_layout->addLayout(power_layout); addItem(power_layout);
} }
SoftwarePanel::SoftwarePanel(QWidget* parent) : QWidget(parent) { SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
gitBranchLbl = new LabelControl("Git Branch"); gitBranchLbl = new LabelControl("Git Branch");
gitCommitLbl = new LabelControl("Git Commit"); gitCommitLbl = new LabelControl("Git Commit");
osVersionLbl = new LabelControl("OS Version"); osVersionLbl = new LabelControl("OS Version");
@ -216,12 +203,6 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : QWidget(parent) {
std::system("pkill -1 -f selfdrive.updated"); std::system("pkill -1 -f selfdrive.updated");
}); });
QVBoxLayout *main_layout = new QVBoxLayout(this);
QWidget *widgets[] = {versionLbl, lastUpdateLbl, updateBtn, gitBranchLbl, gitCommitLbl, osVersionLbl};
for (int i = 0; i < std::size(widgets); ++i) {
main_layout->addWidget(widgets[i]);
main_layout->addWidget(horizontal_line());
}
auto uninstallBtn = new ButtonControl("Uninstall " + getBrand(), "UNINSTALL"); auto uninstallBtn = new ButtonControl("Uninstall " + getBrand(), "UNINSTALL");
connect(uninstallBtn, &ButtonControl::clicked, [=]() { connect(uninstallBtn, &ButtonControl::clicked, [=]() {
@ -230,7 +211,11 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : QWidget(parent) {
} }
}); });
connect(parent, SIGNAL(offroadTransition(bool)), uninstallBtn, SLOT(setEnabled(bool))); connect(parent, SIGNAL(offroadTransition(bool)), uninstallBtn, SLOT(setEnabled(bool)));
main_layout->addWidget(uninstallBtn);
QWidget *widgets[] = {versionLbl, lastUpdateLbl, updateBtn, gitBranchLbl, gitCommitLbl, osVersionLbl, uninstallBtn};
for (QWidget* w : widgets) {
addItem(w);
}
fs_watch = new QFileSystemWatcher(this); fs_watch = new QFileSystemWatcher(this);
QObject::connect(fs_watch, &QFileSystemWatcher::fileChanged, [=](const QString path) { QObject::connect(fs_watch, &QFileSystemWatcher::fileChanged, [=](const QString path) {
@ -269,24 +254,24 @@ QWidget * network_panel(QWidget * parent) {
#ifdef QCOM #ifdef QCOM
QWidget *w = new QWidget(parent); QWidget *w = new QWidget(parent);
QVBoxLayout *layout = new QVBoxLayout(w); QVBoxLayout *layout = new QVBoxLayout(w);
layout->setSpacing(30); layout->setContentsMargins(50, 0, 50, 0);
ListWidget *list = new ListWidget();
list->setSpacing(30);
// wifi + tethering buttons // wifi + tethering buttons
auto wifiBtn = new ButtonControl("WiFi Settings", "OPEN"); auto wifiBtn = new ButtonControl("WiFi Settings", "OPEN");
QObject::connect(wifiBtn, &ButtonControl::clicked, [=]() { HardwareEon::launch_wifi(); }); QObject::connect(wifiBtn, &ButtonControl::clicked, [=]() { HardwareEon::launch_wifi(); });
layout->addWidget(wifiBtn); list->addItem(wifiBtn);
layout->addWidget(horizontal_line());
auto tetheringBtn = new ButtonControl("Tethering Settings", "OPEN"); auto tetheringBtn = new ButtonControl("Tethering Settings", "OPEN");
QObject::connect(tetheringBtn, &ButtonControl::clicked, [=]() { HardwareEon::launch_tethering(); }); QObject::connect(tetheringBtn, &ButtonControl::clicked, [=]() { HardwareEon::launch_tethering(); });
layout->addWidget(tetheringBtn); list->addItem(tetheringBtn);
layout->addWidget(horizontal_line());
// SSH key management // SSH key management
layout->addWidget(new SshToggle()); list->addItem(new SshToggle());
layout->addWidget(horizontal_line()); list->addItem(new SshControl());
layout->addWidget(new SshControl());
layout->addWidget(list);
layout->addStretch(1); layout->addStretch(1);
#else #else
Networking *w = new Networking(parent); Networking *w = new Networking(parent);

@ -13,7 +13,7 @@
// ********** settings window + top-level panels ********** // ********** settings window + top-level panels **********
class DevicePanel : public QWidget { class DevicePanel : public ListWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit DevicePanel(QWidget* parent = nullptr); explicit DevicePanel(QWidget* parent = nullptr);
@ -22,13 +22,13 @@ signals:
void showDriverView(); void showDriverView();
}; };
class TogglesPanel : public QWidget { class TogglesPanel : public ListWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit TogglesPanel(QWidget *parent = nullptr); explicit TogglesPanel(QWidget *parent = nullptr);
}; };
class SoftwarePanel : public QWidget { class SoftwarePanel : public ListWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit SoftwarePanel(QWidget* parent = nullptr); explicit SoftwarePanel(QWidget* parent = nullptr);

@ -18,6 +18,8 @@ QFrame *horizontal_line(QWidget *parent) {
} }
AbstractControl::AbstractControl(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) { AbstractControl::AbstractControl(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) {
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
QVBoxLayout *main_layout = new QVBoxLayout(this); QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(0); main_layout->setMargin(0);
@ -36,7 +38,8 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
// title // title
title_label = new QPushButton(title); title_label = new QPushButton(title);
title_label->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left;"); title_label->setFixedHeight(120);
title_label->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left");
hlayout->addWidget(title_label); hlayout->addWidget(title_label);
main_layout->addLayout(hlayout); main_layout->addLayout(hlayout);
@ -57,6 +60,7 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
description->setVisible(!description->isVisible()); description->setVisible(!description->isVisible());
}); });
} }
main_layout->addStretch();
} }
void AbstractControl::hideEvent(QHideEvent *e) { void AbstractControl::hideEvent(QHideEvent *e) {

@ -3,6 +3,7 @@
#include <QFrame> #include <QFrame>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QPainter>
#include <QPushButton> #include <QPushButton>
#include "selfdrive/common/params.h" #include "selfdrive/common/params.h"
@ -47,12 +48,6 @@ protected:
AbstractControl(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr); AbstractControl(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr);
void hideEvent(QHideEvent *e) override; void hideEvent(QHideEvent *e) override;
QSize minimumSizeHint() const override {
QSize size = QFrame::minimumSizeHint();
size.setHeight(120);
return size;
};
QHBoxLayout *hlayout; QHBoxLayout *hlayout;
QPushButton *title_label; QPushButton *title_label;
QLabel *description = nullptr; QLabel *description = nullptr;
@ -137,3 +132,32 @@ private:
std::string key; std::string key;
Params params; Params params;
}; };
class ListWidget : public QWidget {
Q_OBJECT
public:
explicit ListWidget(QWidget *parent = 0) : QWidget(parent), outer_layout(this) {
outer_layout.setMargin(0);
outer_layout.setSpacing(0);
outer_layout.addLayout(&inner_layout);
inner_layout.setMargin(0);
inner_layout.setSpacing(25); // default spacing is 25
outer_layout.addStretch();
}
inline void addItem(QWidget *w) { inner_layout.addWidget(w); }
inline void addItem(QLayout *layout) { inner_layout.addLayout(layout); }
inline void setSpacing(int spacing) { inner_layout.setSpacing(spacing); }
private:
void paintEvent(QPaintEvent *) override {
QPainter p(this);
p.setPen(Qt::gray);
for (int i = 0; i < inner_layout.count() - 1; ++i) {
QRect r = inner_layout.itemAt(i)->geometry();
int bottom = r.bottom() + inner_layout.spacing() / 2;
p.drawLine(r.left() + 40, bottom, r.right() - 40, bottom);
}
}
QVBoxLayout outer_layout;
QVBoxLayout inner_layout;
};

Loading…
Cancel
Save