UI: improved nav destination entry (#28476)
After Width: | Height: | Size: 466 B |
After Width: | Height: | Size: 757 B |
After Width: | Height: | Size: 315 B |
After Width: | Height: | Size: 489 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 910 B |
After Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 1.4 MiB |
@ -0,0 +1,34 @@ |
|||||||
|
#include "selfdrive/ui/qt/maps/map_panel.h" |
||||||
|
|
||||||
|
#include <QHBoxLayout> |
||||||
|
#include <QWidget> |
||||||
|
|
||||||
|
#include "selfdrive/ui/qt/maps/map.h" |
||||||
|
#include "selfdrive/ui/qt/maps/map_settings.h" |
||||||
|
#include "selfdrive/ui/qt/util.h" |
||||||
|
#include "selfdrive/ui/ui.h" |
||||||
|
|
||||||
|
MapPanel::MapPanel(const QMapboxGLSettings &mapboxSettings, QWidget *parent) : QFrame(parent) { |
||||||
|
content_stack = new QStackedLayout(this); |
||||||
|
content_stack->setContentsMargins(0, 0, 0, 0); |
||||||
|
|
||||||
|
auto map = new MapWindow(mapboxSettings); |
||||||
|
QObject::connect(uiState(), &UIState::offroadTransition, map, &MapWindow::offroadTransition); |
||||||
|
QObject::connect(map, &MapWindow::requestVisible, [=](bool visible) { |
||||||
|
setVisible(visible); |
||||||
|
}); |
||||||
|
QObject::connect(map, &MapWindow::openSettings, [=]() { |
||||||
|
content_stack->setCurrentIndex(1); |
||||||
|
}); |
||||||
|
content_stack->addWidget(map); |
||||||
|
|
||||||
|
auto settings = new MapSettings(true, parent); |
||||||
|
QObject::connect(settings, &MapSettings::closeSettings, [=]() { |
||||||
|
content_stack->setCurrentIndex(0); |
||||||
|
}); |
||||||
|
content_stack->addWidget(settings); |
||||||
|
} |
||||||
|
|
||||||
|
bool MapPanel::isShowingMap() const { |
||||||
|
return content_stack->currentIndex() == 0; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QFrame> |
||||||
|
#include <QMapboxGL> |
||||||
|
#include <QStackedLayout> |
||||||
|
|
||||||
|
class MapPanel : public QFrame { |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
explicit MapPanel(const QMapboxGLSettings &settings, QWidget *parent = nullptr); |
||||||
|
|
||||||
|
bool isShowingMap() const; |
||||||
|
|
||||||
|
private: |
||||||
|
QStackedLayout *content_stack; |
||||||
|
}; |
@ -1,46 +1,120 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
|
#include <QFrame> |
||||||
#include <QJsonArray> |
#include <QJsonArray> |
||||||
#include <QJsonDocument> |
#include <QJsonDocument> |
||||||
#include <QJsonObject> |
#include <QJsonObject> |
||||||
#include <QLabel> |
#include <QLabel> |
||||||
#include <QPushButton> |
#include <QPushButton> |
||||||
#include <QVBoxLayout> |
#include <QVBoxLayout> |
||||||
#include <QWidget> |
|
||||||
#include <QStackedWidget> |
|
||||||
|
|
||||||
#include "common/params.h" |
#include "common/params.h" |
||||||
|
#include "selfdrive/ui/qt/util.h" |
||||||
#include "selfdrive/ui/qt/widgets/controls.h" |
#include "selfdrive/ui/qt/widgets/controls.h" |
||||||
|
|
||||||
const int MAP_PANEL_ICON_SIZE = 200; |
|
||||||
|
|
||||||
const QString NAV_TYPE_FAVORITE = "favorite"; |
const QString NAV_TYPE_FAVORITE = "favorite"; |
||||||
const QString NAV_TYPE_RECENT = "recent"; |
const QString NAV_TYPE_RECENT = "recent"; |
||||||
|
|
||||||
const QString NAV_FAVORITE_LABEL_HOME = "home"; |
const QString NAV_FAVORITE_LABEL_HOME = "home"; |
||||||
const QString NAV_FAVORITE_LABEL_WORK = "work"; |
const QString NAV_FAVORITE_LABEL_WORK = "work"; |
||||||
|
|
||||||
class MapPanel : public QWidget { |
class NavDestination; |
||||||
|
class DestinationWidget; |
||||||
|
|
||||||
|
class MapSettings : public QFrame { |
||||||
Q_OBJECT |
Q_OBJECT |
||||||
public: |
public: |
||||||
explicit MapPanel(QWidget* parent = nullptr); |
explicit MapSettings(bool closeable = false, QWidget *parent = nullptr); |
||||||
|
|
||||||
void navigateTo(const QJsonObject &place); |
void navigateTo(const QJsonObject &place); |
||||||
void parseResponse(const QString &response, bool success); |
void parseResponse(const QString &response, bool success); |
||||||
void updateCurrentRoute(); |
void updateCurrentRoute(); |
||||||
void clear(); |
|
||||||
|
|
||||||
private: |
private: |
||||||
void showEvent(QShowEvent *event) override; |
void showEvent(QShowEvent *event) override; |
||||||
void refresh(); |
void refresh(); |
||||||
|
|
||||||
Params params; |
Params params; |
||||||
QString prev_destinations, cur_destinations; |
QString cur_destinations; |
||||||
QPushButton *home_button, *work_button; |
QVBoxLayout *destinations_layout; |
||||||
QLabel *home_address, *work_address; |
NavDestination *current_destination; |
||||||
QVBoxLayout *recent_layout; |
DestinationWidget *current_widget; |
||||||
QWidget *current_widget; |
|
||||||
ButtonControl *current_route; |
QPixmap close_icon; |
||||||
|
|
||||||
signals: |
signals: |
||||||
void closeSettings(); |
void closeSettings(); |
||||||
}; |
}; |
||||||
|
|
||||||
|
class NavDestination { |
||||||
|
public: |
||||||
|
explicit NavDestination(const QJsonObject &place) |
||||||
|
: type_(place["save_type"].toString()), label_(place["label"].toString()), |
||||||
|
name_(place["place_name"].toString()), details_(place["place_details"].toString()), |
||||||
|
latitude_(place["latitude"].toDouble()), longitude_(place["longitude"].toDouble()) { |
||||||
|
// if details starts with `name, ` remove it
|
||||||
|
if (details_.startsWith(name_ + ", ")) { |
||||||
|
details_ = details_.mid(name_.length() + 2); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
QString type() const { return type_; } |
||||||
|
QString label() const { return label_; } |
||||||
|
QString name() const { return name_; } |
||||||
|
QString details() const { return details_; } |
||||||
|
|
||||||
|
bool isFavorite() const { return type_ == NAV_TYPE_FAVORITE; } |
||||||
|
bool isRecent() const { return type_ == NAV_TYPE_RECENT; } |
||||||
|
|
||||||
|
bool operator==(const NavDestination &rhs) { |
||||||
|
return type_ == rhs.type_ && label_ == rhs.label_ && name_ == rhs.name_ && |
||||||
|
details_ == rhs.details_ && latitude_ == rhs.latitude_ && longitude_ == rhs.longitude_; |
||||||
|
} |
||||||
|
|
||||||
|
QJsonObject toJson() const { |
||||||
|
QJsonObject obj; |
||||||
|
obj["save_type"] = type_; |
||||||
|
obj["label"] = label_; |
||||||
|
obj["place_name"] = name_; |
||||||
|
obj["place_details"] = details_; |
||||||
|
obj["latitude"] = latitude_; |
||||||
|
obj["longitude"] = longitude_; |
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
QString type_, label_, name_, details_; |
||||||
|
double latitude_, longitude_; |
||||||
|
}; |
||||||
|
|
||||||
|
class DestinationWidget : public QPushButton { |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit DestinationWidget(QWidget *parent = nullptr); |
||||||
|
|
||||||
|
void set(NavDestination *, bool current = false); |
||||||
|
void unset(const QString &label, bool current = false); |
||||||
|
|
||||||
|
signals: |
||||||
|
void actionClicked(); |
||||||
|
|
||||||
|
private: |
||||||
|
struct NavIcons { |
||||||
|
QPixmap home, work, favorite, recent, directions; |
||||||
|
}; |
||||||
|
|
||||||
|
static NavIcons icons() { |
||||||
|
static NavIcons nav_icons { |
||||||
|
loadPixmap("../assets/navigation/icon_home.svg", {48, 48}), |
||||||
|
loadPixmap("../assets/navigation/icon_work.svg", {48, 48}), |
||||||
|
loadPixmap("../assets/navigation/icon_favorite.svg", {48, 48}), |
||||||
|
loadPixmap("../assets/navigation/icon_recent.svg", {48, 48}), |
||||||
|
loadPixmap("../assets/navigation/icon_directions.svg", {48, 48}), |
||||||
|
}; |
||||||
|
return nav_icons; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
QLabel *icon, *title, *subtitle; |
||||||
|
QPushButton *action; |
||||||
|
}; |
||||||
|