September 10th, 2024 Patch

This commit is contained in:
FrogAi
2024-09-10 11:01:59 -07:00
parent c10b7f39ba
commit ced3a53a0d
9 changed files with 154 additions and 124 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ FrogPilot is a fully open-sourced fork of openpilot, featuring clear and concise
------
FrogPilot was last updated on:
**September 5th, 2024**
**September 10th, 2024**
Features
------
@@ -43,34 +43,30 @@ def handle_error(destination, error_message, error, download_param, progress_par
params_memory.put(progress_param, error_message)
def handle_request_error(error, destination, download_param, progress_param, params_memory):
if isinstance(error, requests.HTTPError):
if error.response.status_code == 404:
return
error_message = f"Server error ({error.response.status_code})" if error.response else "Server error."
elif isinstance(error, requests.ConnectionError):
error_message = "Connection dropped."
elif isinstance(error, requests.Timeout):
error_message = "Download timed out."
elif isinstance(error, requests.RequestException):
error_message = "Network request error. Check connection."
else:
error_message = "Unexpected error."
error_map = {
requests.HTTPError: lambda e: f"Server error ({e.response.status_code})" if e.response else "Server error.",
requests.ConnectionError: "Connection dropped.",
requests.Timeout: "Download timed out.",
requests.RequestException: "Network request error. Check connection."
}
error_message = error_map.get(type(error), "Unexpected error.")
if isinstance(error, requests.HTTPError) and error.response and error.response.status_code == 404:
return
handle_error(destination, f"Failed: {error_message}", error, download_param, progress_param, params_memory)
def get_remote_file_size(url):
try:
response = requests.head(url, headers={'Accept-Encoding': 'identity'}, timeout=5)
if response.status_code == 404:
print(f"URL not found: {url}")
return None
response.raise_for_status()
return int(response.headers.get('Content-Length', 0))
except requests.HTTPError as e:
if e.response.status_code == 404:
return 0
else:
handle_request_error(e, None, None, None, None)
except Exception as e:
except (requests.RequestException, ValueError) as e:
handle_request_error(e, None, None, None, None)
return 0
return None
def get_repository_url():
if is_url_pingable("https://github.com"):
@@ -84,17 +80,25 @@ def link_valid(url):
response = requests.head(url, allow_redirects=True, timeout=5)
response.raise_for_status()
return True
except requests.HTTPError as e:
if e.response.status_code != 404:
handle_request_error(e, None, None, None, None)
return False
except Exception as e:
handle_request_error(e, None, None, None, None)
return False
def verify_download(file_path, url):
if not os.path.exists(file_path):
if not os.path.isfile(file_path):
print(f"File not found: {file_path}")
return False
remote_file_size = get_remote_file_size(url)
if remote_file_size is None:
print(f"Error fetching remote size for {file_path}")
return None
if remote_file_size != os.path.getsize(file_path):
print(f"File size mismatch for {file_path}")
return False
return remote_file_size == os.path.getsize(file_path)
return True
@@ -1,7 +1,6 @@
import json
import os
import re
import requests
import shutil
import time
import urllib.request
@@ -46,16 +45,16 @@ class ModelManager:
def download_model(self, model_to_download):
model_path = os.path.join(MODELS_PATH, f"{model_to_download}.thneed")
if os.path.exists(model_path):
if os.path.isfile(model_path):
handle_error(model_path, "Model already exists...", "Model already exists...", self.download_param, self.download_progress_param, self.params_memory)
return
self.repo_url = get_repository_url()
if not self.repo_url:
repo_url = get_repository_url()
if not repo_url:
handle_error(model_path, "GitHub and GitLab are offline...", "Repository unavailable", self.download_param, self.download_progress_param, self.params_memory)
return
model_url = f"{self.repo_url}Models/{model_to_download}.thneed"
model_url = f"{repo_url}Models/{model_to_download}.thneed"
print(f"Downloading model: {model_to_download}")
download_file(self.cancel_download_param, model_path, self.download_progress_param, model_url, self.download_param, self.params_memory)
@@ -74,7 +73,7 @@ class ModelManager:
handle_request_error(error, None, None, None, None)
return []
def update_model_params(self, model_info):
def update_model_params(self, model_info, repo_url):
available_models, available_model_names, experimental_models, navigation_models, radarless_models = [], [], [], [], []
for model in model_info:
@@ -96,20 +95,23 @@ class ModelManager:
print("Models list updated successfully.")
if available_models:
models_downloaded = self.are_all_models_downloaded(available_models, available_model_names)
models_downloaded = self.are_all_models_downloaded(available_models, available_model_names, repo_url)
self.params.put_bool_nonblocking("ModelsDownloaded", models_downloaded)
def are_all_models_downloaded(self, available_models, available_model_names):
def are_all_models_downloaded(self, available_models, available_model_names, repo_url):
automatically_update_models = self.params.get_bool("AutomaticallyUpdateModels")
all_models_downloaded = True
for model in available_models:
model_path = os.path.join(MODELS_PATH, f"{model}.thneed")
model_url = f"{self.repo_url}Models/{model}.thneed"
model_url = f"{repo_url}Models/{model}.thneed"
if os.path.exists(model_path):
if os.path.isfile(model_path):
if automatically_update_models:
if not verify_download(model_path, model_url):
verify_result = verify_download(model_path, model_url)
if verify_result is None:
all_models_downloaded = False
elif not verify_result:
print(f"Model {model} is outdated. Re-downloading...")
delete_file(model_path)
self.remove_model_params(available_model_names, available_models, model)
@@ -152,6 +154,11 @@ class ModelManager:
if not available_models:
return
current_model_path = os.path.join(MODELS_PATH, f"{current_model}.thneed")
if not os.path.isfile(current_model_path):
print(f"Model {current_model} is not downloaded. Downloading...")
self.download_model(current_model)
for model_file in os.listdir(MODELS_PATH):
if model_file.replace(".thneed", "") not in available_models.split(','):
if model_file == current_model:
@@ -163,35 +170,38 @@ class ModelManager:
def copy_default_model(self):
default_model_path = os.path.join(MODELS_PATH, f"{DEFAULT_MODEL}.thneed")
if not os.path.exists(default_model_path):
if not os.path.isfile(default_model_path):
source_path = os.path.join(BASEDIR, "selfdrive", "modeld", "models", "supercombo.thneed")
if os.path.exists(source_path):
if os.path.isfile(source_path):
shutil.copyfile(source_path, default_model_path)
print(f"Copied default model from {source_path} to {default_model_path}")
else:
print(f"Source default model not found at {source_path}. Exiting...")
def update_models(self, boot_run=True):
def update_models(self, boot_run=False):
if boot_run:
self.copy_default_model()
self.repo_url = get_repository_url()
if self.repo_url is None:
repo_url = get_repository_url()
if repo_url is None:
print("GitHub and GitLab are offline...")
return
model_info = self.fetch_models(f"{self.repo_url}Versions/model_names_{VERSION}.json")
model_info = self.fetch_models(f"{repo_url}Versions/model_names_{VERSION}.json")
if model_info:
self.update_model_params(model_info)
self.update_model_params(model_info, repo_url)
if boot_run:
self.validate_models()
def download_all_models(self):
self.repo_url = get_repository_url()
if not self.repo_url:
repo_url = get_repository_url()
if not repo_url:
handle_error(None, "GitHub and GitLab are offline...", "Repository unavailable", self.download_param, self.download_progress_param, self.params_memory)
return
model_info = self.fetch_models(f"{self.repo_url}Versions/model_names_{VERSION}.json")
model_info = self.fetch_models(f"{repo_url}Versions/model_names_{VERSION}.json")
if not model_info:
handle_error(None, "Unable to update model list...", "Model list unavailable", self.download_param, self.download_progress_param, self.params_memory)
return
@@ -208,7 +218,7 @@ class ModelManager:
if self.params_memory.get_bool(self.cancel_download_param):
return
if not os.path.exists(os.path.join(MODELS_PATH, f"{model}.thneed")):
if not os.path.isfile(os.path.join(MODELS_PATH, f"{model}.thneed")):
model_index = available_models.index(model)
model_name = available_model_names[model_index]
@@ -220,7 +230,7 @@ class ModelManager:
while self.params_memory.get(self.download_param, encoding='utf-8'):
time.sleep(1)
while not all(os.path.exists(os.path.join(MODELS_PATH, f"{model}.thneed")) for model in available_models):
while not all(os.path.isfile(os.path.join(MODELS_PATH, f"{model}.thneed")) for model in available_models):
time.sleep(1)
self.params_memory.put(self.download_progress_param, "All models downloaded!")
@@ -258,7 +258,7 @@ class ThemeManager:
for ext in extentions:
theme_path = download_path + ext
if os.path.exists(theme_path):
if os.path.isfile(theme_path):
handle_error(theme_path, "Theme already exists...", "Theme already exists...", theme_param, self.download_progress_param, self.params_memory)
return
@@ -366,7 +366,7 @@ class ThemeManager:
self.previous_assets = {}
self.update_active_theme()
def update_themes(self):
def update_themes(self, boot_run=False):
if not os.path.exists(THEME_SAVE_PATH):
return
@@ -375,6 +375,9 @@ class ThemeManager:
print("GitHub and GitLab are offline...")
return
if boot_run:
self.validate_themes()
if repo_url == GITHUB_URL:
base_url = "https://github.com/FrogAi/FrogPilot-Resources/blob/Themes/"
distance_icons_files = self.fetch_files("https://github.com/FrogAi/FrogPilot-Resources/blob/Distance-Icons")
+4 -4
View File
@@ -86,13 +86,13 @@ def time_checks(automatic_updates, deviceState, model_manager, now, started, the
update_maps(now, params, params_memory)
with locks["update_models"]:
model_manager.update_models(boot_run=False)
model_manager.update_models()
with locks["update_themes"]:
theme_manager.update_themes()
def toggle_updates(frogpilot_toggles, started, time_validated, params, params_storage):
FrogPilotVariables.update_frogpilot_params(started, True)
FrogPilotVariables.update_frogpilot_params(started)
if not frogpilot_toggles.model_manager:
params.put_nonblocking("Model", DEFAULT_MODEL)
@@ -195,8 +195,8 @@ def frogpilot_thread():
if not time_validated:
continue
if deviceState.networkType == WIFI:
run_thread_with_lock("update_models", model_manager.update_models)
run_thread_with_lock("update_themes", theme_manager.update_themes)
run_thread_with_lock("update_models", model_manager.update_models, (True,))
run_thread_with_lock("update_themes", theme_manager.update_themes, (True,))
theme_manager.update_holiday()
+4 -12
View File
@@ -5,9 +5,6 @@ import stat
import subprocess
import time
import urllib.request
import http.client
import socket
import openpilot.system.sentry as sentry
from openpilot.common.realtime import Ratekeeper
@@ -26,9 +23,8 @@ def get_latest_version():
try:
with urllib.request.urlopen(url, timeout=5) as response:
return json.loads(response.read().decode('utf-8'))['version']
except (http.client.IncompleteRead, http.client.RemoteDisconnected, socket.gaierror, socket.timeout, urllib.error.HTTPError, urllib.error.URLError) as e:
sentry.capture_exception(e)
print(f"Failed to get latest version from {url}. Error: {e}")
except Exception as e:
print(f"Error fetching version from {url}: {e}")
print("Failed to get the latest version from both sources.")
return None
@@ -54,9 +50,8 @@ def download(current_version):
print(f"Successfully downloaded mapd from {url}")
return True
except (http.client.IncompleteRead, http.client.RemoteDisconnected, socket.gaierror, socket.timeout, urllib.error.HTTPError, urllib.error.URLError) as e:
sentry.capture_exception(e)
print(f"Failed to download from {url}. Error: {e}")
except Exception as e:
print(f"Failed to download from {url}: {e}")
print(f"Failed to download mapd for version {current_version} from both sources.")
return False
@@ -66,7 +61,6 @@ def ensure_mapd_is_running():
try:
subprocess.run([MAPD_PATH], check=True)
except Exception as e:
sentry.capture_exception(e)
print(f"Error running mapd process: {e}")
time.sleep(1)
@@ -89,7 +83,6 @@ def mapd_thread(sm=None, pm=None):
continue
ensure_mapd_is_running()
except Exception as e:
sentry.capture_exception(e)
print(f"Exception in mapd_thread: {e}")
time.sleep(1)
@@ -99,7 +92,6 @@ def main(sm=None, pm=None):
try:
mapd_thread(sm, pm)
except Exception as e:
sentry.capture_exception(e)
print(f"Unhandled exception in main: {e}")
if __name__ == "__main__":
@@ -14,31 +14,31 @@
#include "selfdrive/ui/ui.h"
QMap<QString, QString> northeastMap = {
{"CT", "Connecticut"}, {"DE", "Delaware"}, {"MA", "Massachusetts"},
{"MD", "Maryland"}, {"ME", "Maine"}, {"NH", "New Hampshire"},
{"CT", "Connecticut"}, {"DE", "Delaware"}, {"ME", "Maine"},
{"MD", "Maryland"}, {"MA", "Massachusetts"}, {"NH", "New Hampshire"},
{"NJ", "New Jersey"}, {"NY", "New York"}, {"PA", "Pennsylvania"},
{"RI", "Rhode Island"}, {"VT", "Vermont"}
};
QMap<QString, QString> midwestMap = {
{"IA", "Iowa"}, {"IL", "Illinois"}, {"IN", "Indiana"},
{"IL", "Illinois"}, {"IN", "Indiana"}, {"IA", "Iowa"},
{"KS", "Kansas"}, {"MI", "Michigan"}, {"MN", "Minnesota"},
{"MO", "Missouri"}, {"ND", "North Dakota"}, {"NE", "Nebraska"},
{"MO", "Missouri"}, {"NE", "Nebraska"}, {"ND", "North Dakota"},
{"OH", "Ohio"}, {"SD", "South Dakota"}, {"WI", "Wisconsin"}
};
QMap<QString, QString> southMap = {
{"AL", "Alabama"}, {"AR", "Arkansas"}, {"FL", "Florida"},
{"GA", "Georgia"}, {"KY", "Kentucky"}, {"LA", "Louisiana"},
{"MS", "Mississippi"}, {"NC", "North Carolina"}, {"OK", "Oklahoma"},
{"SC", "South Carolina"}, {"TN", "Tennessee"}, {"TX", "Texas"},
{"VA", "Virginia"}, {"WV", "West Virginia"}
{"MD", "Maryland"}, {"MS", "Mississippi"}, {"NC", "North Carolina"},
{"OK", "Oklahoma"}, {"SC", "South Carolina"}, {"TN", "Tennessee"},
{"TX", "Texas"}, {"VA", "Virginia"}, {"WV", "West Virginia"}
};
QMap<QString, QString> westMap = {
{"AK", "Alaska"}, {"AZ", "Arizona"}, {"CA", "California"},
{"CO", "Colorado"}, {"HI", "Hawaii"}, {"ID", "Idaho"},
{"MT", "Montana"}, {"NM", "New Mexico"}, {"NV", "Nevada"},
{"MT", "Montana"}, {"NV", "Nevada"}, {"NM", "New Mexico"},
{"OR", "Oregon"}, {"UT", "Utah"}, {"WA", "Washington"},
{"WY", "Wyoming"}
};
@@ -51,19 +51,23 @@ QMap<QString, QString> territoriesMap = {
QMap<QString, QString> africaMap = {
{"DZ", "Algeria"}, {"AO", "Angola"}, {"BJ", "Benin"}, {"BW", "Botswana"},
{"BF", "Burkina Faso"}, {"BI", "Burundi"}, {"CM", "Cameroon"}, {"CV", "Cape Verde"},
{"CF", "Central African Republic"}, {"TD", "Chad"}, {"KM", "Comoros"}, {"CG", "Congo (Brazzaville)"},
{"CD", "Congo (Kinshasa)"}, {"CI", "Ivory Coast"}, {"DJ", "Djibouti"}, {"EG", "Egypt"},
{"GQ", "Equatorial Guinea"}, {"ER", "Eritrea"}, {"SZ", "Eswatini"}, {"ET", "Ethiopia"},
{"GA", "Gabon"}, {"GM", "Gambia"}, {"GH", "Ghana"}, {"GN", "Guinea"},
{"GW", "Guinea-Bissau"}, {"KE", "Kenya"}, {"LS", "Lesotho"}, {"LR", "Liberia"},
{"LY", "Libya"}, {"MG", "Madagascar"}, {"MW", "Malawi"}, {"ML", "Mali"},
{"MR", "Mauritania"}, {"MU", "Mauritius"}, {"MA", "Morocco"}, {"MZ", "Mozambique"},
{"NA", "Namibia"}, {"NE", "Niger"}, {"NG", "Nigeria"}, {"RW", "Rwanda"},
{"ST", "Sao Tome and Principe"}, {"SN", "Senegal"}, {"SC", "Seychelles"}, {"SL", "Sierra Leone"},
{"SO", "Somalia"}, {"ZA", "South Africa"}, {"SS", "South Sudan"}, {"SD", "Sudan"},
{"TZ", "Tanzania"}, {"TG", "Togo"}, {"TN", "Tunisia"}, {"UG", "Uganda"},
{"EH", "Western Sahara"}, {"ZM", "Zambia"}, {"ZW", "Zimbabwe"}
{"BF", "Burkina Faso"}, {"BI", "Burundi"}, {"CV", "Cape Verde"},
{"CM", "Cameroon"}, {"CF", "Central African Republic"}, {"TD", "Chad"},
{"KM", "Comoros"}, {"CG", "Congo (Brazzaville)"}, {"CD", "Congo (Kinshasa)"},
{"CI", "Ivory Coast"}, {"DJ", "Djibouti"}, {"EG", "Egypt"},
{"GQ", "Equatorial Guinea"}, {"ER", "Eritrea"}, {"SZ", "Eswatini"},
{"ET", "Ethiopia"}, {"GA", "Gabon"}, {"GM", "Gambia"}, {"GH", "Ghana"},
{"GN", "Guinea"}, {"GW", "Guinea-Bissau"}, {"KE", "Kenya"},
{"LS", "Lesotho"}, {"LR", "Liberia"}, {"LY", "Libya"},
{"MG", "Madagascar"}, {"MW", "Malawi"}, {"ML", "Mali"}, {"MR", "Mauritania"},
{"MU", "Mauritius"}, {"MA", "Morocco"}, {"MZ", "Mozambique"},
{"NA", "Namibia"}, {"NE", "Niger"}, {"NG", "Nigeria"},
{"RW", "Rwanda"}, {"ST", "Sao Tome and Principe"},
{"SN", "Senegal"}, {"SC", "Seychelles"}, {"SL", "Sierra Leone"},
{"SO", "Somalia"}, {"ZA", "South Africa"}, {"SS", "South Sudan"},
{"SD", "Sudan"}, {"TZ", "Tanzania"}, {"TG", "Togo"}, {"TN", "Tunisia"},
{"UG", "Uganda"}, {"EH", "Western Sahara"}, {"ZM", "Zambia"},
{"ZW", "Zimbabwe"}
};
QMap<QString, QString> antarcticaMap = {
@@ -71,57 +75,66 @@ QMap<QString, QString> antarcticaMap = {
};
QMap<QString, QString> asiaMap = {
{"AF", "Afghanistan"}, {"AM", "Armenia"}, {"AZ", "Azerbaijan"}, {"BH", "Bahrain"},
{"BD", "Bangladesh"}, {"BT", "Bhutan"}, {"BN", "Brunei"}, {"KH", "Cambodia"},
{"CN", "China"}, {"CY", "Cyprus"}, {"GE", "Georgia"}, {"IN", "India"},
{"ID", "Indonesia"}, {"IR", "Iran"}, {"IQ", "Iraq"}, {"IL", "Israel"},
{"JP", "Japan"}, {"JO", "Jordan"}, {"KZ", "Kazakhstan"}, {"KP", "North Korea"},
{"KR", "South Korea"}, {"KW", "Kuwait"}, {"KG", "Kyrgyzstan"}, {"LA", "Laos"},
{"LB", "Lebanon"}, {"MY", "Malaysia"}, {"MV", "Maldives"}, {"MN", "Mongolia"},
{"MM", "Myanmar"}, {"NP", "Nepal"}, {"OM", "Oman"}, {"PK", "Pakistan"},
{"PS", "Palestine"}, {"PH", "Philippines"}, {"QA", "Qatar"}, {"SA", "Saudi Arabia"},
{"SG", "Singapore"}, {"LK", "Sri Lanka"}, {"SY", "Syria"}, {"TW", "Taiwan"},
{"TJ", "Tajikistan"}, {"TH", "Thailand"}, {"TL", "Timor-Leste"}, {"TR", "Turkey"},
{"TM", "Turkmenistan"}, {"AE", "United Arab Emirates"}, {"UZ", "Uzbekistan"}, {"VN", "Vietnam"},
{"YE", "Yemen"}
{"AF", "Afghanistan"}, {"AM", "Armenia"}, {"AZ", "Azerbaijan"},
{"BH", "Bahrain"}, {"BD", "Bangladesh"}, {"BT", "Bhutan"},
{"BN", "Brunei"}, {"MM", "Myanmar"}, {"KH", "Cambodia"}, {"CN", "China"},
{"CY", "Cyprus"}, {"GE", "Georgia"}, {"IN", "India"}, {"ID", "Indonesia"},
{"IR", "Iran"}, {"IQ", "Iraq"}, {"IL", "Israel"}, {"JP", "Japan"},
{"JO", "Jordan"}, {"KZ", "Kazakhstan"}, {"KW", "Kuwait"}, {"KG", "Kyrgyzstan"},
{"LA", "Laos"}, {"LB", "Lebanon"}, {"MV", "Maldives"}, {"MY", "Malaysia"},
{"MN", "Mongolia"}, {"NP", "Nepal"}, {"OM", "Oman"}, {"PK", "Pakistan"},
{"PH", "Philippines"}, {"QA", "Qatar"}, {"RU", "Russia"},
{"SA", "Saudi Arabia"}, {"SG", "Singapore"}, {"KR", "South Korea"},
{"LK", "Sri Lanka"}, {"SY", "Syria"}, {"TJ", "Tajikistan"},
{"TH", "Thailand"}, {"TL", "Timor-Leste"}, {"TR", "Turkey"},
{"TM", "Turkmenistan"}, {"AE", "United Arab Emirates"},
{"UZ", "Uzbekistan"}, {"VN", "Vietnam"}, {"YE", "Yemen"}
};
QMap<QString, QString> europeMap = {
{"AL", "Albania"}, {"AD", "Andorra"}, {"AT", "Austria"}, {"BY", "Belarus"},
{"BE", "Belgium"}, {"BA", "Bosnia and Herzegovina"}, {"BG", "Bulgaria"}, {"HR", "Croatia"},
{"CY", "Cyprus"}, {"CZ", "Czech Republic"}, {"DK", "Denmark"}, {"EE", "Estonia"},
{"FI", "Finland"}, {"FR", "France"}, {"DE", "Germany"}, {"GR", "Greece"},
{"HU", "Hungary"}, {"IS", "Iceland"}, {"IE", "Ireland"}, {"IT", "Italy"},
{"LV", "Latvia"}, {"LI", "Liechtenstein"}, {"LT", "Lithuania"}, {"LU", "Luxembourg"},
{"MT", "Malta"}, {"MD", "Moldova"}, {"MC", "Monaco"}, {"ME", "Montenegro"},
{"NL", "Netherlands"}, {"MK", "North Macedonia"}, {"NO", "Norway"}, {"PL", "Poland"},
{"PT", "Portugal"}, {"RO", "Romania"}, {"RU", "Russia"}, {"SM", "San Marino"},
{"RS", "Serbia"}, {"SK", "Slovakia"}, {"SI", "Slovenia"}, {"ES", "Spain"},
{"SE", "Sweden"}, {"CH", "Switzerland"}, {"TR", "Turkey"}, {"UA", "Ukraine"},
{"GB", "United Kingdom"}, {"VA", "Vatican City"}
{"AL", "Albania"}, {"AD", "Andorra"}, {"AT", "Austria"},
{"BY", "Belarus"}, {"BE", "Belgium"}, {"BA", "Bosnia and Herzegovina"},
{"BG", "Bulgaria"}, {"HR", "Croatia"}, {"CY", "Cyprus"},
{"CZ", "Czech Republic"}, {"DK", "Denmark"}, {"EE", "Estonia"},
{"FI", "Finland"}, {"FR", "France"}, {"GE", "Georgia"},
{"DE", "Germany"}, {"GR", "Greece"}, {"HU", "Hungary"},
{"IS", "Iceland"}, {"IE", "Ireland"}, {"IT", "Italy"},
{"LV", "Latvia"}, {"LI", "Liechtenstein"}, {"LT", "Lithuania"},
{"LU", "Luxembourg"}, {"MT", "Malta"}, {"MD", "Moldova"},
{"MC", "Monaco"}, {"ME", "Montenegro"}, {"NL", "Netherlands"},
{"MK", "North Macedonia"}, {"NO", "Norway"}, {"PL", "Poland"},
{"PT", "Portugal"}, {"RO", "Romania"}, {"RU", "Russia"},
{"SM", "San Marino"}, {"RS", "Serbia"}, {"SK", "Slovakia"},
{"SI", "Slovenia"}, {"ES", "Spain"}, {"SE", "Sweden"},
{"CH", "Switzerland"}, {"UA", "Ukraine"}, {"GB", "United Kingdom"},
{"VA", "Vatican City"}
};
QMap<QString, QString> northAmericaMap = {
{"AG", "Antigua and Barbuda"}, {"BS", "Bahamas"}, {"BB", "Barbados"}, {"BZ", "Belize"},
{"CA", "Canada"}, {"CR", "Costa Rica"}, {"CU", "Cuba"}, {"DM", "Dominica"},
{"DO", "Dominican Republic"}, {"SV", "El Salvador"}, {"GD", "Grenada"}, {"GT", "Guatemala"},
{"HT", "Haiti"}, {"HN", "Honduras"}, {"JM", "Jamaica"}, {"MX", "Mexico"},
{"NI", "Nicaragua"}, {"PA", "Panama"}, {"KN", "Saint Kitts and Nevis"}, {"LC", "Saint Lucia"},
{"VC", "Saint Vincent and the Grenadines"}, {"TT", "Trinidad and Tobago"}, {"US", "United States"}
{"AG", "Antigua and Barbuda"}, {"BS", "Bahamas"}, {"BB", "Barbados"},
{"BZ", "Belize"}, {"CA", "Canada"}, {"CR", "Costa Rica"},
{"CU", "Cuba"}, {"DM", "Dominica"}, {"DO", "Dominican Republic"},
{"SV", "El Salvador"}, {"GD", "Grenada"}, {"GT", "Guatemala"},
{"HT", "Haiti"}, {"HN", "Honduras"}, {"JM", "Jamaica"},
{"MX", "Mexico"}, {"NI", "Nicaragua"}, {"PA", "Panama"},
{"KN", "Saint Kitts and Nevis"}, {"LC", "Saint Lucia"},
{"VC", "Saint Vincent and the Grenadines"}, {"TT", "Trinidad and Tobago"},
{"US", "United States"}
};
QMap<QString, QString> oceaniaMap = {
{"AU", "Australia"}, {"FJ", "Fiji"}, {"KI", "Kiribati"}, {"MH", "Marshall Islands"},
{"FM", "Micronesia"}, {"NR", "Nauru"}, {"NZ", "New Zealand"}, {"PW", "Palau"},
{"PG", "Papua New Guinea"}, {"WS", "Samoa"}, {"SB", "Solomon Islands"}, {"TO", "Tonga"},
{"AU", "Australia"}, {"FJ", "Fiji"}, {"FM", "Micronesia"},
{"KI", "Kiribati"}, {"MH", "Marshall Islands"}, {"NR", "Nauru"},
{"NZ", "New Zealand"}, {"PW", "Palau"}, {"PG", "Papua New Guinea"},
{"WS", "Samoa"}, {"SB", "Solomon Islands"}, {"TO", "Tonga"},
{"TV", "Tuvalu"}, {"VU", "Vanuatu"}
};
QMap<QString, QString> southAmericaMap = {
{"AR", "Argentina"}, {"BO", "Bolivia"}, {"BR", "Brazil"}, {"CL", "Chile"},
{"CO", "Colombia"}, {"EC", "Ecuador"}, {"GY", "Guyana"}, {"PY", "Paraguay"},
{"PE", "Peru"}, {"SR", "Suriname"}, {"TT", "Trinidad and Tobago"}, {"UY", "Uruguay"},
{"VE", "Venezuela"}
{"AR", "Argentina"}, {"BO", "Bolivia"}, {"BR", "Brazil"},
{"CL", "Chile"}, {"CO", "Colombia"}, {"EC", "Ecuador"},
{"GY", "Guyana"}, {"PY", "Paraguay"}, {"PE", "Peru"},
{"SR", "Suriname"}, {"UY", "Uruguay"}, {"VE", "Venezuela"}
};
class ButtonSelectionControl : public QWidget {
@@ -145,7 +158,12 @@ public:
QJsonObject mapsSelected = QJsonDocument::fromJson(QString::fromStdString(Params().get("MapsSelected")).toUtf8()).object();
for (const QString &stateCode : map.keys()) {
QList<QString> sortedKeys = map.keys();
std::sort(sortedKeys.begin(), sortedKeys.end(), [&](const QString &a, const QString &b) {
return map[a] < map[b];
});
for (const QString &stateCode : sortedKeys) {
if (count % max == 0 && count != 0) {
buttonsLayout = new QHBoxLayout();
buttonsLayout->setSpacing(10);
+1 -1
View File
@@ -874,7 +874,7 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(int alert_height, const UISce
unconfirmedSpeedLimit = speedLimitController ? scene.unconfirmed_speed_limit : 0;
useViennaSLCSign = scene.use_vienna_slc_sign;
bool stoppedTimer = scene.stopped_timer && scene.standstill && scene.started_timer / UI_FREQ >= 10;
bool stoppedTimer = scene.stopped_timer && scene.standstill && scene.started_timer / UI_FREQ >= 10 && !mapOpen;
if (stoppedTimer) {
if (!standstillTimer.isValid()) {
standstillTimer.start();
+3
View File
@@ -161,6 +161,9 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) {
}
QPainter p(this);
if (use_stock_wheel) {
img = experimental_mode ? experimental_img : engage_img;
}
updateBackgroundColor();
drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
}