search with user input

This commit is contained in:
Jason Wen
2025-01-25 21:25:06 -05:00
parent 8998ed067e
commit 999feae5f3
17 changed files with 572 additions and 41 deletions
+2
View File
@@ -205,6 +205,8 @@ std::unordered_map<std::string, uint32_t> keys = {
{"CarParamsSP", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"CarParamsSPCache", CLEAR_ON_MANAGER_START},
{"CarParamsSPPersistent", PERSISTENT},
{"CarPlatform", PERSISTENT},
{"CarPlatformName", PERSISTENT},
{"EnableGithubRunner", PERSISTENT | BACKUP},
{"ModelRunnerTypeCache", CLEAR_ON_ONROAD_TRANSITION},
{"OffroadMode", CLEAR_ON_MANAGER_START},
+5 -1
View File
@@ -35,8 +35,12 @@ sunnypilot_panel_qt_src = [
"sunnypilot/qt/offroad/settings/sunnypilot/mads_settings.cc",
]
vehicle_panel_qt_src = [
"sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc",
]
sp_widgets_src = widgets_src
sp_qt_src = qt_src + sunnypilot_panel_qt_src
sp_qt_src = qt_src + sunnypilot_panel_qt_src + vehicle_panel_qt_src
sp_qt_util = qt_util
Export('sp_widgets_src', 'sp_qt_src', "sp_qt_util")
@@ -0,0 +1,178 @@
/**
* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
*
* This file is part of sunnypilot and is licensed under the MIT License.
* See the LICENSE.md file in the root directory for more details.
*/
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QMap>
PlatformSelector::PlatformSelector() : ButtonControl(tr("Vehicle"), "", "") {
QObject::connect(this, &ButtonControl::clicked, [=]() {
if (text() == tr("SEARCH")) {
QString query = InputDialog::getText(tr("Search your vehicle"), this, tr("Enter model year (e.g., 2021) and model name (Toyota Corolla):"), false);
if (query.length() > 0) {
setText(tr("SEARCHING"));
setEnabled(false);
searchPlatforms(query);
refresh();
}
} else {
params.remove("CarPlatform");
params.remove("CarPlatformName");
refresh();
}
});
refresh();
}
void PlatformSelector::refresh() {
QString platform_param = QString::fromStdString(params.get("CarPlatform"));
if (platform_param.length()) {
setValue(QString::fromStdString(params.get("CarPlatformName")));
setText("REMOVE");
} else {
setValue("");
setText("SEARCH");
}
setEnabled(true);
}
QMap<QString, QVariantMap> PlatformSelector::loadPlatformList() {
QMap<QString, QVariantMap> platforms;
std::string json_data = util::read_file("../../sunnypilot/selfdrive/car/car_list_extra.json").c_str();
if (json_data.empty()) {
return platforms;
}
QJsonParseError json_error;
QJsonDocument doc = QJsonDocument::fromJson(QString::fromStdString(json_data).toUtf8(), &json_error);
if (doc.isNull()) {
return platforms;
}
if (doc.isObject()) {
QJsonObject obj = doc.object();
for (const QString &key : obj.keys()) {
QJsonObject attributes = obj.value(key).toObject();
QVariantMap platform_data;
QJsonArray yearArray = attributes.value("year").toArray();
QVariantList yearList;
for (const QJsonValue &year : yearArray) {
yearList.append(year.toString());
}
platform_data["year"] = yearList;
platform_data["model"] = attributes.value("model").toString();
platform_data["package"] = attributes.value("package").toString();
platforms[key] = platform_data;
}
}
return platforms;
}
void PlatformSelector::searchPlatforms(const QString &query) {
if (query.isEmpty()) {
return;
}
QMap<QString, QVariantMap> platforms = loadPlatformList();
QSet<QString> matched_cars;
QString normalized_query = query.simplified().toLower();
QStringList tokens = normalized_query.split(" ", Qt::SkipEmptyParts);
int search_year = -1;
QStringList search_terms;
for (const QString &token : tokens) {
bool ok;
int year = token.toInt(&ok);
if (ok && year >= 1900 && year <= 2100) {
search_year = year;
} else {
search_terms << token;
}
}
for (auto it = platforms.constBegin(); it != platforms.constEnd(); ++it) {
QString platform_name = it.key();
QVariantMap platform_data = it.value();
QVariantList year_list = platform_data["year"].toList();
if (search_year != -1) {
bool year_match = false;
for (const QVariant &year_var : year_list) {
int year = year_var.toString().toInt();
if (year == search_year) {
year_match = true;
break;
}
}
if (!year_match) {
continue;
}
}
bool all_terms_match = true;
QString platform_search = platform_name.toLower();
// Normalize platform name for searching (remove diacritical marks)
QString normalized_platform = platform_search.normalized(QString::NormalizationForm_KD);
normalized_platform.remove(QRegExp("[^a-zA-Z0-9\\s]"));
for (const QString &term : search_terms) {
QString normalized_term = term.normalized(QString::NormalizationForm_KD);
normalized_term.remove(QRegExp("[^a-zA-Z0-9\\s]"));
if (term.contains(QRegExp("[a-z]\\d|\\d[a-z]", Qt::CaseInsensitive))) {
QString clean_platform = normalized_platform;
QString clean_term = normalized_term;
clean_platform.remove(" ");
clean_term.remove(" ");
if (!clean_platform.contains(clean_term, Qt::CaseInsensitive)) {
all_terms_match = false;
break;
}
} else {
QRegExp wordMatch(QString("\\b%1\\b").arg(QRegExp::escape(normalized_term)), Qt::CaseInsensitive);
if (!normalized_platform.contains(wordMatch)) {
all_terms_match = false;
break;
}
}
}
if (all_terms_match) {
matched_cars.insert(platform_name);
}
}
QStringList results = QStringList(matched_cars.begin(), matched_cars.end());
results.sort();
if (results.isEmpty()) {
ConfirmationDialog::alert(tr("No vehicles found for query: %1").arg(query), this);
return;
}
QString selected_platform = MultiOptionDialog::getSelection(tr("Select a vehicle"), results, "", this);
if (!selected_platform.isEmpty()) {
params.put("CarPlatform", selected_platform.toStdString());
params.put("CarPlatformName", selected_platform.toStdString());
}
}
@@ -0,0 +1,24 @@
/**
* Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
*
* This file is part of sunnypilot and is licensed under the MIT License.
* See the LICENSE.md file in the root directory for more details.
*/
#pragma once
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h"
class PlatformSelector : public ButtonControl {
Q_OBJECT
public:
PlatformSelector();
private:
Params params;
void refresh();
void searchPlatforms(const QString &query);
QMap<QString, QVariantMap> loadPlatformList();
};
@@ -6,6 +6,23 @@
*/
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h"
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h"
#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h"
VehiclePanel::VehiclePanel(QWidget *parent) : QFrame(parent) {
main_layout = new QStackedLayout(this);
ListWidget *list = new ListWidget(this);
vehicleScreen = new QWidget(this);
QVBoxLayout *vlayout = new QVBoxLayout(vehicleScreen);
vlayout->setContentsMargins(50, 20, 50, 20);
list->addItem(new PlatformSelector());
ScrollViewSP *scroller = new ScrollViewSP(list, this);
vlayout->addWidget(scroller);
main_layout->addWidget(vehicleScreen);
main_layout->setCurrentWidget(vehicleScreen);
}
@@ -14,4 +14,9 @@ class VehiclePanel : public QFrame {
public:
explicit VehiclePanel(QWidget *parent = nullptr);
private:
QStackedLayout* main_layout = nullptr;
QWidget* vehicleScreen = nullptr;
ButtonControl* carSelector = nullptr;
};
+31 -4
View File
@@ -509,10 +509,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">متقدم</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -658,6 +654,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>إلغاء</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -505,10 +505,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">Erweitert</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -653,6 +649,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>Aktivieren</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31
View File
@@ -650,6 +650,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>Cancelar</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -505,10 +505,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">Avancé</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -654,6 +650,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>Annuler</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">詳細</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -652,6 +648,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>を有効化</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">고급 설정</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -653,6 +649,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>활성화</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -505,10 +505,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">Avançado</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -654,6 +650,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>Ativar</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">ขั้นสูง</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -653,6 +649,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>ยกเลิก</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">Gelişmiş Seçenekler</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -652,6 +648,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">高级</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -653,6 +649,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>启用</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>
+31 -4
View File
@@ -504,10 +504,6 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
</context>
<context>
<name>NetworkingSP</name>
<message>
<source>Advanced</source>
<translation type="obsolete">進階</translation>
</message>
<message>
<source>Scan</source>
<translation type="unfinished"></translation>
@@ -653,6 +649,37 @@ Pause Steering: ALC will be paused after the brake pedal is manually pressed.</s
<translation>啟用</translation>
</message>
</context>
<context>
<name>PlatformSelector</name>
<message>
<source>Vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCH</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search your vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>SEARCHING</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No vehicles found for query: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select a vehicle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter model year (e.g., 2021) and model name (Toyota Corolla):</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrimeAdWidget</name>
<message>