11#include < QApplication>
22#include < QtWidgets>
33#include < QTimer>
4+ #include < QGraphicsScene>
45
56#include " cereal/messaging/messaging.h"
67#include " selfdrive/ui/ui.h"
78#include " selfdrive/ui/qt/qt_window.h"
89
10+ class StatusBar : public QGraphicsRectItem {
11+ private:
12+ QLinearGradient linear_gradient;
13+ QRadialGradient radial_gradient;
14+ QTimer animation_timer;
15+ const int animation_length = 10 ;
16+ int animation_index = 0 ;
17+
18+ public:
19+ StatusBar (double x, double y, double width, double height) : QGraphicsRectItem {x, y, width, height} {
20+ linear_gradient = QLinearGradient (0 , 0 , 0 , height/2 );
21+ linear_gradient.setSpread (QGradient::ReflectSpread);
22+
23+ radial_gradient = QRadialGradient (width/2 , height/2 , width/8 );
24+ QObject::connect (&animation_timer, &QTimer::timeout, [=]() {
25+ animation_index++;
26+ animation_index %= animation_length;
27+ });
28+ animation_timer.start (50 );
29+ }
30+
31+ void solidColor (QColor color) {
32+ QColor dark_color = QColor (color);
33+ dark_color.setAlphaF (0.5 );
34+
35+ linear_gradient.setColorAt (0 , dark_color);
36+ linear_gradient.setColorAt (1 , color);
37+ setBrush (QBrush (linear_gradient));
38+ }
39+
40+ // these need to be called continuously for the animations to work.
41+ // can probably clean that up with some more abstractions
42+ void blinkingColor (QColor color) {
43+ QColor dark_color = QColor (color);
44+ dark_color.setAlphaF (0.1 );
45+
46+ int radius = (rect ().width () / animation_length) * animation_index;
47+ QPoint center = QPoint (rect ().width ()/2 , rect ().height ()/2 );
48+ radial_gradient.setCenter (center);
49+ radial_gradient.setFocalPoint (center);
50+ radial_gradient.setRadius (radius);
51+
52+ radial_gradient.setColorAt (1 , dark_color);
53+ radial_gradient.setColorAt (0 , color);
54+ setBrush (QBrush (radial_gradient));
55+ }
56+
57+ void laneChange (cereal::LateralPlan::LaneChangeDirection direction) {
58+ QColor dark_color = QColor (bg_colors[STATUS_ENGAGED]);
59+ dark_color.setAlphaF (0.1 );
60+
61+ int x = (rect ().width () / animation_length) * animation_index;
62+ QPoint center = QPoint (((direction == cereal::LateralPlan::LaneChangeDirection::RIGHT) ? x : (rect ().width () - x)), rect ().height ()/2 );
63+ radial_gradient.setCenter (center);
64+ radial_gradient.setFocalPoint (center);
65+ radial_gradient.setRadius (rect ().width ()/5 );
66+
67+ radial_gradient.setColorAt (1 , dark_color);
68+ radial_gradient.setColorAt (0 , bg_colors[STATUS_ENGAGED]);
69+ setBrush (QBrush (radial_gradient));
70+ }
71+
72+ void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr ) override {
73+ painter->setPen (QPen ());
74+ painter->setBrush (brush ());
75+
76+ double rounding_radius = rect ().height ()/2 ;
77+ painter->drawRoundedRect (rect (), rounding_radius, rounding_radius);
78+ }
79+ };
80+
981int main (int argc, char *argv[]) {
1082 QApplication a (argc, argv);
1183 QWidget w;
@@ -15,12 +87,18 @@ int main(int argc, char *argv[]) {
1587
1688 // our beautiful UI
1789 QVBoxLayout *layout = new QVBoxLayout (&w);
18- QLabel *label = new QLabel (" 〇" );
19- layout->addWidget (label, 0 , Qt::AlignCenter);
90+
91+ QGraphicsScene *scene = new QGraphicsScene ();
92+ StatusBar *status_bar = new StatusBar (0 , 0 , 1000 , 50 );
93+ scene->addItem (status_bar);
94+
95+ QGraphicsView *graphics_view = new QGraphicsView (scene);
96+ layout->insertSpacing (0 , 400 );
97+ layout->addWidget (graphics_view, 0 , Qt::AlignCenter);
2098
2199 QTimer timer;
22100 QObject::connect (&timer, &QTimer::timeout, [=]() {
23- static SubMaster sm ({" deviceState" , " controlsState" });
101+ static SubMaster sm ({" deviceState" , " controlsState" , " lateralPlan " });
24102
25103 bool onroad_prev = sm.allAliveAndValid ({" deviceState" }) &&
26104 sm[" deviceState" ].getDeviceState ().getStarted ();
@@ -37,7 +115,16 @@ int main(int argc, char *argv[]) {
37115 } else if (cs.getAlertStatus () == cereal::ControlsState::AlertStatus::CRITICAL) {
38116 status = STATUS_ALERT;
39117 }
40- label->setStyleSheet (QString (" color: %1; font-size: 250px;" ).arg (bg_colors[status].name ()));
118+
119+ auto lp = sm[" lateralPlan" ].getLateralPlan ();
120+ if (lp.getLaneChangeState () == cereal::LateralPlan::LaneChangeState::PRE_LANE_CHANGE || status == STATUS_ALERT) {
121+ status_bar->blinkingColor (bg_colors[status]);
122+ } else if (lp.getLaneChangeState () == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_STARTING ||
123+ lp.getLaneChangeState () == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_FINISHING) {
124+ status_bar->laneChange (lp.getLaneChangeDirection ());
125+ } else {
126+ status_bar->solidColor (bg_colors[status]);
127+ }
41128 }
42129
43130 if ((onroad != onroad_prev) || sm.frame < 2 ) {
0 commit comments