You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							381 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
	
	
							381 lines
						
					
					
						
							13 KiB
						
					
					
				#include "selfdrive/ui/qt/network/networking.h"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
#include <QHBoxLayout>
 | 
						|
#include <QScrollBar>
 | 
						|
#include <QStyle>
 | 
						|
 | 
						|
#include "selfdrive/ui/qt/qt_window.h"
 | 
						|
#include "selfdrive/ui/qt/util.h"
 | 
						|
#include "selfdrive/ui/qt/widgets/controls.h"
 | 
						|
#include "selfdrive/ui/qt/widgets/scrollview.h"
 | 
						|
 | 
						|
static const int ICON_WIDTH = 49;
 | 
						|
 | 
						|
// Networking functions
 | 
						|
 | 
						|
Networking::Networking(QWidget* parent, bool show_advanced) : QFrame(parent) {
 | 
						|
  main_layout = new QStackedLayout(this);
 | 
						|
 | 
						|
  wifi = new WifiManager(this);
 | 
						|
  connect(wifi, &WifiManager::refreshSignal, this, &Networking::refresh);
 | 
						|
  connect(wifi, &WifiManager::wrongPassword, this, &Networking::wrongPassword);
 | 
						|
 | 
						|
  wifiScreen = new QWidget(this);
 | 
						|
  QVBoxLayout* vlayout = new QVBoxLayout(wifiScreen);
 | 
						|
  vlayout->setContentsMargins(20, 20, 20, 20);
 | 
						|
  if (show_advanced) {
 | 
						|
    QPushButton* advancedSettings = new QPushButton(tr("Advanced"));
 | 
						|
    advancedSettings->setObjectName("advanced_btn");
 | 
						|
    advancedSettings->setStyleSheet("margin-right: 30px;");
 | 
						|
    advancedSettings->setFixedSize(400, 100);
 | 
						|
    connect(advancedSettings, &QPushButton::clicked, [=]() { main_layout->setCurrentWidget(an); });
 | 
						|
    vlayout->addSpacing(10);
 | 
						|
    vlayout->addWidget(advancedSettings, 0, Qt::AlignRight);
 | 
						|
    vlayout->addSpacing(10);
 | 
						|
  }
 | 
						|
 | 
						|
  wifiWidget = new WifiUI(this, wifi);
 | 
						|
  wifiWidget->setObjectName("wifiWidget");
 | 
						|
  connect(wifiWidget, &WifiUI::connectToNetwork, this, &Networking::connectToNetwork);
 | 
						|
 | 
						|
  ScrollView *wifiScroller = new ScrollView(wifiWidget, this);
 | 
						|
  wifiScroller->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
 | 
						|
  vlayout->addWidget(wifiScroller, 1);
 | 
						|
  main_layout->addWidget(wifiScreen);
 | 
						|
 | 
						|
  an = new AdvancedNetworking(this, wifi);
 | 
						|
  connect(an, &AdvancedNetworking::backPress, [=]() { main_layout->setCurrentWidget(wifiScreen); });
 | 
						|
  connect(an, &AdvancedNetworking::requestWifiScreen, [=]() { main_layout->setCurrentWidget(wifiScreen); });
 | 
						|
  main_layout->addWidget(an);
 | 
						|
 | 
						|
  QPalette pal = palette();
 | 
						|
  pal.setColor(QPalette::Window, QColor(0x29, 0x29, 0x29));
 | 
						|
  setAutoFillBackground(true);
 | 
						|
  setPalette(pal);
 | 
						|
 | 
						|
  setStyleSheet(R"(
 | 
						|
    #wifiWidget > QPushButton, #back_btn, #advanced_btn {
 | 
						|
      font-size: 50px;
 | 
						|
      margin: 0px;
 | 
						|
      padding: 15px;
 | 
						|
      border-width: 0;
 | 
						|
      border-radius: 30px;
 | 
						|
      color: #dddddd;
 | 
						|
      background-color: #393939;
 | 
						|
    }
 | 
						|
    #back_btn:pressed, #advanced_btn:pressed {
 | 
						|
      background-color:  #4a4a4a;
 | 
						|
    }
 | 
						|
  )");
 | 
						|
  main_layout->setCurrentWidget(wifiScreen);
 | 
						|
}
 | 
						|
 | 
						|
void Networking::setPrimeType(PrimeState::Type type) {
 | 
						|
  an->setGsmVisible(type == PrimeState::PRIME_TYPE_NONE || type == PrimeState::PRIME_TYPE_LITE);
 | 
						|
  wifi->ipv4_forward = (type == PrimeState::PRIME_TYPE_NONE || type == PrimeState::PRIME_TYPE_LITE);
 | 
						|
}
 | 
						|
 | 
						|
void Networking::refresh() {
 | 
						|
  wifiWidget->refresh();
 | 
						|
  an->refresh();
 | 
						|
}
 | 
						|
 | 
						|
void Networking::connectToNetwork(const Network n) {
 | 
						|
  if (wifi->isKnownConnection(n.ssid)) {
 | 
						|
    wifi->activateWifiConnection(n.ssid);
 | 
						|
  } else if (n.security_type == SecurityType::OPEN) {
 | 
						|
    wifi->connect(n, false);
 | 
						|
  } else if (n.security_type == SecurityType::WPA) {
 | 
						|
    QString pass = InputDialog::getText(tr("Enter password"), this, tr("for \"%1\"").arg(QString::fromUtf8(n.ssid)), true, 8);
 | 
						|
    if (!pass.isEmpty()) {
 | 
						|
      wifi->connect(n, false, pass);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void Networking::wrongPassword(const QString &ssid) {
 | 
						|
  if (wifi->seenNetworks.contains(ssid)) {
 | 
						|
    const Network &n = wifi->seenNetworks.value(ssid);
 | 
						|
    QString pass = InputDialog::getText(tr("Wrong password"), this, tr("for \"%1\"").arg(QString::fromUtf8(n.ssid)), true, 8);
 | 
						|
    if (!pass.isEmpty()) {
 | 
						|
      wifi->connect(n, false, pass);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void Networking::showEvent(QShowEvent *event) {
 | 
						|
  wifi->start();
 | 
						|
}
 | 
						|
 | 
						|
void Networking::hideEvent(QHideEvent *event) {
 | 
						|
  main_layout->setCurrentWidget(wifiScreen);
 | 
						|
  wifi->stop();
 | 
						|
}
 | 
						|
 | 
						|
// AdvancedNetworking functions
 | 
						|
 | 
						|
AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWidget(parent), wifi(wifi) {
 | 
						|
 | 
						|
  QVBoxLayout* main_layout = new QVBoxLayout(this);
 | 
						|
  main_layout->setMargin(40);
 | 
						|
  main_layout->setSpacing(20);
 | 
						|
 | 
						|
  // Back button
 | 
						|
  QPushButton* back = new QPushButton(tr("Back"));
 | 
						|
  back->setObjectName("back_btn");
 | 
						|
  back->setFixedSize(400, 100);
 | 
						|
  connect(back, &QPushButton::clicked, [=]() { emit backPress(); });
 | 
						|
  main_layout->addWidget(back, 0, Qt::AlignLeft);
 | 
						|
 | 
						|
  ListWidget *list = new ListWidget(this);
 | 
						|
  // Enable tethering layout
 | 
						|
  tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled());
 | 
						|
  list->addItem(tetheringToggle);
 | 
						|
  QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering);
 | 
						|
 | 
						|
  // Change tethering password
 | 
						|
  ButtonControl *editPasswordButton = new ButtonControl(tr("Tethering Password"), tr("EDIT"));
 | 
						|
  connect(editPasswordButton, &ButtonControl::clicked, [=]() {
 | 
						|
    QString pass = InputDialog::getText(tr("Enter new tethering password"), this, "", true, 8, wifi->getTetheringPassword());
 | 
						|
    if (!pass.isEmpty()) {
 | 
						|
      wifi->changeTetheringPassword(pass);
 | 
						|
    }
 | 
						|
  });
 | 
						|
  list->addItem(editPasswordButton);
 | 
						|
 | 
						|
  // IP address
 | 
						|
  ipLabel = new LabelControl(tr("IP Address"), wifi->ipv4_address);
 | 
						|
  list->addItem(ipLabel);
 | 
						|
 | 
						|
  // SSH keys
 | 
						|
  list->addItem(new SshToggle());
 | 
						|
  list->addItem(new SshControl());
 | 
						|
 | 
						|
  // Roaming toggle
 | 
						|
  const bool roamingEnabled = params.getBool("GsmRoaming");
 | 
						|
  roamingToggle = new ToggleControl(tr("Enable Roaming"), "", "", roamingEnabled);
 | 
						|
  QObject::connect(roamingToggle, &ToggleControl::toggleFlipped, [=](bool state) {
 | 
						|
    params.putBool("GsmRoaming", state);
 | 
						|
    wifi->updateGsmSettings(state, QString::fromStdString(params.get("GsmApn")), params.getBool("GsmMetered"));
 | 
						|
  });
 | 
						|
  list->addItem(roamingToggle);
 | 
						|
 | 
						|
  // APN settings
 | 
						|
  editApnButton = new ButtonControl(tr("APN Setting"), tr("EDIT"));
 | 
						|
  connect(editApnButton, &ButtonControl::clicked, [=]() {
 | 
						|
    const QString cur_apn = QString::fromStdString(params.get("GsmApn"));
 | 
						|
    QString apn = InputDialog::getText(tr("Enter APN"), this, tr("leave blank for automatic configuration"), false, -1, cur_apn).trimmed();
 | 
						|
 | 
						|
    if (apn.isEmpty()) {
 | 
						|
      params.remove("GsmApn");
 | 
						|
    } else {
 | 
						|
      params.put("GsmApn", apn.toStdString());
 | 
						|
    }
 | 
						|
    wifi->updateGsmSettings(params.getBool("GsmRoaming"), apn, params.getBool("GsmMetered"));
 | 
						|
  });
 | 
						|
  list->addItem(editApnButton);
 | 
						|
 | 
						|
  // Metered toggle
 | 
						|
  const bool metered = params.getBool("GsmMetered");
 | 
						|
  meteredToggle = new ToggleControl(tr("Cellular Metered"), tr("Prevent large data uploads when on a metered connection"), "", metered);
 | 
						|
  QObject::connect(meteredToggle, &SshToggle::toggleFlipped, [=](bool state) {
 | 
						|
    params.putBool("GsmMetered", state);
 | 
						|
    wifi->updateGsmSettings(params.getBool("GsmRoaming"), QString::fromStdString(params.get("GsmApn")), state);
 | 
						|
  });
 | 
						|
  list->addItem(meteredToggle);
 | 
						|
 | 
						|
  // Hidden Network
 | 
						|
  hiddenNetworkButton = new ButtonControl(tr("Hidden Network"), tr("CONNECT"));
 | 
						|
  connect(hiddenNetworkButton, &ButtonControl::clicked, [=]() {
 | 
						|
    QString ssid = InputDialog::getText(tr("Enter SSID"), this, "", false, 1);
 | 
						|
    if (!ssid.isEmpty()) {
 | 
						|
      QString pass = InputDialog::getText(tr("Enter password"), this, tr("for \"%1\"").arg(ssid), true, -1);
 | 
						|
      Network hidden_network;
 | 
						|
      hidden_network.ssid = ssid.toUtf8();
 | 
						|
      if (!pass.isEmpty()) {
 | 
						|
        hidden_network.security_type = SecurityType::WPA;
 | 
						|
        wifi->connect(hidden_network, true, pass);
 | 
						|
      } else {
 | 
						|
        wifi->connect(hidden_network, true);
 | 
						|
      }
 | 
						|
      emit requestWifiScreen();
 | 
						|
    }
 | 
						|
  });
 | 
						|
  list->addItem(hiddenNetworkButton);
 | 
						|
 | 
						|
  // Set initial config
 | 
						|
  wifi->updateGsmSettings(roamingEnabled, QString::fromStdString(params.get("GsmApn")), metered);
 | 
						|
 | 
						|
  main_layout->addWidget(new ScrollView(list, this));
 | 
						|
  main_layout->addStretch(1);
 | 
						|
}
 | 
						|
 | 
						|
void AdvancedNetworking::setGsmVisible(bool visible) {
 | 
						|
  roamingToggle->setVisible(visible);
 | 
						|
  editApnButton->setVisible(visible);
 | 
						|
  meteredToggle->setVisible(visible);
 | 
						|
}
 | 
						|
 | 
						|
void AdvancedNetworking::refresh() {
 | 
						|
  ipLabel->setText(wifi->ipv4_address);
 | 
						|
  tetheringToggle->setEnabled(true);
 | 
						|
  update();
 | 
						|
}
 | 
						|
 | 
						|
void AdvancedNetworking::toggleTethering(bool enabled) {
 | 
						|
  wifi->setTetheringEnabled(enabled);
 | 
						|
  tetheringToggle->setEnabled(false);
 | 
						|
}
 | 
						|
 | 
						|
// WifiUI functions
 | 
						|
 | 
						|
WifiUI::WifiUI(QWidget *parent, WifiManager* wifi) : QWidget(parent), wifi(wifi) {
 | 
						|
  QVBoxLayout *main_layout = new QVBoxLayout(this);
 | 
						|
  main_layout->setContentsMargins(0, 0, 0, 0);
 | 
						|
  main_layout->setSpacing(0);
 | 
						|
 | 
						|
  // load imgs
 | 
						|
  for (const auto &s : {"low", "medium", "high", "full"}) {
 | 
						|
    QPixmap pix(ASSET_PATH + "/offroad/icon_wifi_strength_" + s + ".svg");
 | 
						|
    strengths.push_back(pix.scaledToHeight(68, Qt::SmoothTransformation));
 | 
						|
  }
 | 
						|
  lock = QPixmap(ASSET_PATH + "offroad/icon_lock_closed.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation);
 | 
						|
  checkmark = QPixmap(ASSET_PATH + "offroad/icon_checkmark.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation);
 | 
						|
  circled_slash = QPixmap(ASSET_PATH + "img_circled_slash.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation);
 | 
						|
 | 
						|
  scanningLabel = new QLabel(tr("Scanning for networks..."));
 | 
						|
  scanningLabel->setStyleSheet("font-size: 65px;");
 | 
						|
  main_layout->addWidget(scanningLabel, 0, Qt::AlignCenter);
 | 
						|
 | 
						|
  wifi_list_widget = new ListWidget(this);
 | 
						|
  wifi_list_widget->setVisible(false);
 | 
						|
  main_layout->addWidget(wifi_list_widget);
 | 
						|
 | 
						|
  setStyleSheet(R"(
 | 
						|
    QScrollBar::handle:vertical {
 | 
						|
      min-height: 0px;
 | 
						|
      border-radius: 4px;
 | 
						|
      background-color: #8A8A8A;
 | 
						|
    }
 | 
						|
    #forgetBtn {
 | 
						|
      font-size: 32px;
 | 
						|
      font-weight: 600;
 | 
						|
      color: #292929;
 | 
						|
      background-color: #BDBDBD;
 | 
						|
      border-width: 1px solid #828282;
 | 
						|
      border-radius: 5px;
 | 
						|
      padding: 40px;
 | 
						|
      padding-bottom: 16px;
 | 
						|
      padding-top: 16px;
 | 
						|
    }
 | 
						|
    #forgetBtn:pressed {
 | 
						|
      background-color: #828282;
 | 
						|
    }
 | 
						|
    #connecting {
 | 
						|
      font-size: 32px;
 | 
						|
      font-weight: 600;
 | 
						|
      color: white;
 | 
						|
      border-radius: 0;
 | 
						|
      padding: 27px;
 | 
						|
      padding-left: 43px;
 | 
						|
      padding-right: 43px;
 | 
						|
      background-color: black;
 | 
						|
    }
 | 
						|
    #ssidLabel {
 | 
						|
      text-align: left;
 | 
						|
      border: none;
 | 
						|
      padding-top: 50px;
 | 
						|
      padding-bottom: 50px;
 | 
						|
    }
 | 
						|
    #ssidLabel:disabled {
 | 
						|
      color: #696969;
 | 
						|
    }
 | 
						|
  )");
 | 
						|
}
 | 
						|
 | 
						|
void WifiUI::refresh() {
 | 
						|
  bool is_empty = wifi->seenNetworks.isEmpty();
 | 
						|
  scanningLabel->setVisible(is_empty);
 | 
						|
  wifi_list_widget->setVisible(!is_empty);
 | 
						|
  if (is_empty) return;
 | 
						|
 | 
						|
  setUpdatesEnabled(false);
 | 
						|
 | 
						|
  const bool is_tethering_enabled = wifi->isTetheringEnabled();
 | 
						|
  QList<Network> sortedNetworks = wifi->seenNetworks.values();
 | 
						|
  std::sort(sortedNetworks.begin(), sortedNetworks.end(), compare_by_strength);
 | 
						|
 | 
						|
  int n = 0;
 | 
						|
  for (Network &network : sortedNetworks) {
 | 
						|
    QPixmap status_icon;
 | 
						|
    if (network.connected == ConnectedType::CONNECTED) {
 | 
						|
      status_icon = checkmark;
 | 
						|
    } else if (network.security_type == SecurityType::UNSUPPORTED) {
 | 
						|
      status_icon = circled_slash;
 | 
						|
    } else if (network.security_type == SecurityType::WPA) {
 | 
						|
      status_icon = lock;
 | 
						|
    }
 | 
						|
    bool show_forget_btn = wifi->isKnownConnection(network.ssid) && !is_tethering_enabled;
 | 
						|
    QPixmap strength = strengths[strengthLevel(network.strength)];
 | 
						|
 | 
						|
    auto item = getItem(n++);
 | 
						|
    item->setItem(network, status_icon, show_forget_btn, strength);
 | 
						|
    item->setVisible(true);
 | 
						|
  }
 | 
						|
  for (; n < wifi_items.size(); ++n) wifi_items[n]->setVisible(false);
 | 
						|
 | 
						|
  setUpdatesEnabled(true);
 | 
						|
}
 | 
						|
 | 
						|
WifiItem *WifiUI::getItem(int n) {
 | 
						|
  auto item = n < wifi_items.size() ? wifi_items[n] : wifi_items.emplace_back(new WifiItem(tr("CONNECTING..."), tr("FORGET")));
 | 
						|
  if (!item->parentWidget()) {
 | 
						|
    QObject::connect(item, &WifiItem::connectToNetwork, this, &WifiUI::connectToNetwork);
 | 
						|
    QObject::connect(item, &WifiItem::forgotNetwork, [this](const Network n) {
 | 
						|
      if (ConfirmationDialog::confirm(tr("Forget Wi-Fi Network \"%1\"?").arg(QString::fromUtf8(n.ssid)), tr("Forget"), this))
 | 
						|
        wifi->forgetConnection(n.ssid);
 | 
						|
    });
 | 
						|
    wifi_list_widget->addItem(item);
 | 
						|
  }
 | 
						|
  return item;
 | 
						|
}
 | 
						|
 | 
						|
// WifiItem
 | 
						|
 | 
						|
WifiItem::WifiItem(const QString &connecting_text, const QString &forget_text, QWidget *parent) : QWidget(parent) {
 | 
						|
  QHBoxLayout *hlayout = new QHBoxLayout(this);
 | 
						|
  hlayout->setContentsMargins(44, 0, 73, 0);
 | 
						|
  hlayout->setSpacing(50);
 | 
						|
 | 
						|
  hlayout->addWidget(ssidLabel = new ElidedLabel());
 | 
						|
  ssidLabel->setObjectName("ssidLabel");
 | 
						|
  ssidLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 | 
						|
  hlayout->addWidget(connecting = new QPushButton(connecting_text), 0, Qt::AlignRight);
 | 
						|
  connecting->setObjectName("connecting");
 | 
						|
  hlayout->addWidget(forgetBtn = new QPushButton(forget_text), 0, Qt::AlignRight);
 | 
						|
  forgetBtn->setObjectName("forgetBtn");
 | 
						|
  hlayout->addWidget(iconLabel = new QLabel(), 0, Qt::AlignRight);
 | 
						|
  hlayout->addWidget(strengthLabel = new QLabel(), 0, Qt::AlignRight);
 | 
						|
 | 
						|
  iconLabel->setFixedWidth(ICON_WIDTH);
 | 
						|
  QObject::connect(forgetBtn, &QPushButton::clicked, [this]() { emit forgotNetwork(network); });
 | 
						|
  QObject::connect(ssidLabel, &ElidedLabel::clicked, [this]() {
 | 
						|
    if (network.connected == ConnectedType::DISCONNECTED) emit connectToNetwork(network);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
void WifiItem::setItem(const Network &n, const QPixmap &status_icon, bool show_forget_btn, const QPixmap &strength_icon) {
 | 
						|
  network = n;
 | 
						|
 | 
						|
  ssidLabel->setText(n.ssid);
 | 
						|
  ssidLabel->setEnabled(n.security_type != SecurityType::UNSUPPORTED);
 | 
						|
  ssidLabel->setFont(InterFont(55, network.connected == ConnectedType::DISCONNECTED ? QFont::Normal : QFont::Bold));
 | 
						|
 | 
						|
  connecting->setVisible(n.connected == ConnectedType::CONNECTING);
 | 
						|
  forgetBtn->setVisible(show_forget_btn);
 | 
						|
 | 
						|
  iconLabel->setPixmap(status_icon);
 | 
						|
  strengthLabel->setPixmap(strength_icon);
 | 
						|
}
 | 
						|
 |