mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-19 23:34:14 +08:00
BURN THE WITCH
This commit is contained in:
@@ -23,11 +23,6 @@ on:
|
||||
type: boolean
|
||||
default: true
|
||||
required: false
|
||||
build_ui:
|
||||
description: "Build UI (selfdrive/ui)"
|
||||
type: boolean
|
||||
default: true
|
||||
required: false
|
||||
build_params:
|
||||
description: "Build params Python extension"
|
||||
type: boolean
|
||||
@@ -156,7 +151,6 @@ jobs:
|
||||
fi
|
||||
|
||||
TARGETS=()
|
||||
[[ "${{ inputs.build_ui }}" == "true" ]] && TARGETS+=("selfdrive/ui/ui")
|
||||
[[ "${{ inputs.build_params }}" == "true" ]] && TARGETS+=("common/params_pyx.so")
|
||||
[[ "${{ inputs.build_cereal }}" == "true" ]] && TARGETS+=("cereal/messaging/bridge")
|
||||
if [[ "${{ inputs.build_panda }}" == "true" ]]; then
|
||||
@@ -184,8 +178,8 @@ jobs:
|
||||
fi
|
||||
|
||||
if [[ ${#TARGETS[@]} -eq 0 ]]; then
|
||||
echo "No partial targets selected; defaulting to UI + panda"
|
||||
TARGETS=("selfdrive/ui/ui" "panda/board/obj/panda.bin.signed")
|
||||
echo "No partial targets selected; defaulting to panda"
|
||||
TARGETS=("panda/board/obj/panda.bin.signed")
|
||||
fi
|
||||
|
||||
echo "Running partial build for targets: ${TARGETS[*]}"
|
||||
|
||||
@@ -54,9 +54,6 @@ cereal/gen
|
||||
selfdrive/ui/translations/tmp
|
||||
selfdrive/car/tests/cars_dump
|
||||
system/camerad/test/ae_gray_test
|
||||
selfdrive/ui/ui.macos
|
||||
selfdrive/ui/ui.larch64
|
||||
|
||||
.coverage*
|
||||
coverage.xml
|
||||
htmlcov
|
||||
|
||||
Vendored
+1
-16
@@ -11,14 +11,6 @@
|
||||
"tools/sim/run_bridge.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cpp_process",
|
||||
"type": "pickString",
|
||||
"description": "Select the process to debug",
|
||||
"options": [
|
||||
"selfdrive/ui/ui"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "args",
|
||||
"description": "Arguments to pass to the process",
|
||||
@@ -40,13 +32,6 @@
|
||||
"justMyCode": true,
|
||||
"args": "${input:args}"
|
||||
},
|
||||
{
|
||||
"name": "C++: openpilot Process",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/${input:cpp_process}",
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Attach LLDB to Replay drive",
|
||||
"type": "lldb",
|
||||
@@ -82,4 +67,4 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+1
-114
@@ -37,10 +37,6 @@ AddOption('--coverage',
|
||||
action='store_true',
|
||||
help='build with test coverage options')
|
||||
|
||||
AddOption('--clazy',
|
||||
action='store_true',
|
||||
help='build with clazy')
|
||||
|
||||
AddOption('--ccflags',
|
||||
action='store',
|
||||
type='string',
|
||||
@@ -354,116 +350,7 @@ else:
|
||||
np_version = SCons.Script.Value(np.__version__)
|
||||
Export('envCython', 'np_version')
|
||||
|
||||
# Qt build environment
|
||||
qt_env = env.Clone()
|
||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "DBus", "Xml"]
|
||||
|
||||
qt_libs = []
|
||||
if arch == "Darwin":
|
||||
qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5"
|
||||
qt_dirs = [
|
||||
os.path.join(qt_env['QTDIR'], "include"),
|
||||
]
|
||||
qt_dirs += [f"{qt_env['QTDIR']}/include/Qt{m}" for m in qt_modules]
|
||||
qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")]
|
||||
qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"]
|
||||
qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin"))
|
||||
else:
|
||||
if arch == "larch64":
|
||||
qt_env.PrependENVPath('PATH', Dir("#third_party/qt5/larch64/bin/").abspath)
|
||||
# For laptop/device builds that mount an AGNOS sysroot, always prefer Qt
|
||||
# headers from that sysroot to keep headers/libs ABI-matched (Qt 5.12.x).
|
||||
if arch == "larch64" and os.environ.get("SP_TICI_SYSROOT"):
|
||||
qt_install_prefix = tici_libpath("/usr")
|
||||
qt_install_headers = tici_libpath("/usr/include/aarch64-linux-gnu/qt5")
|
||||
else:
|
||||
qmake = os.environ.get("SP_QMAKE", "qmake")
|
||||
qt_install_prefix = subprocess.check_output([qmake, '-query', 'QT_INSTALL_PREFIX'], encoding='utf8').strip()
|
||||
qt_install_headers = subprocess.check_output([qmake, '-query', 'QT_INSTALL_HEADERS'], encoding='utf8').strip()
|
||||
|
||||
qt_env['QTDIR'] = qt_install_prefix
|
||||
qt_dirs = [
|
||||
f"{qt_install_headers}",
|
||||
]
|
||||
|
||||
qt_gui_path = os.path.join(qt_install_headers, "QtGui")
|
||||
qt_gui_dirs = [d for d in os.listdir(qt_gui_path) if os.path.isdir(os.path.join(qt_gui_path, d))]
|
||||
qt_dirs += [f"{qt_install_headers}/QtGui/{qt_gui_dirs[0]}/QtGui", ] if qt_gui_dirs else []
|
||||
qt_dirs += [f"{qt_install_headers}/Qt{m}" for m in qt_modules]
|
||||
|
||||
qt_libs = [f"Qt5{m}" for m in qt_modules]
|
||||
if arch == "larch64":
|
||||
qt_libs += ["GLESv2", "wayland-client"]
|
||||
elif arch != "Darwin":
|
||||
qt_libs += ["GL"]
|
||||
qt_env['QT3DIR'] = qt_env['QTDIR']
|
||||
qt_env.Tool('qt3')
|
||||
if arch == "larch64" and os.environ.get("SP_TICI_SYSROOT"):
|
||||
qt_tool_bin = tici_libpath("/usr/lib/qt5/bin")
|
||||
qt_tool_root = tici_libpath("/")
|
||||
qt_arm_moc = os.path.join(qt_tool_bin, "moc")
|
||||
qt_arm_uic = os.path.join(qt_tool_bin, "uic")
|
||||
qt_arm_rcc = os.path.join(qt_tool_bin, "rcc")
|
||||
qt_host_bin = os.environ.get("SP_QT_HOST_BIN", "/usr/lib/qt5/bin")
|
||||
qt_host_moc = os.environ.get("SP_QT_HOST_MOC", os.path.join(qt_host_bin, "moc"))
|
||||
qt_host_uic = os.environ.get("SP_QT_HOST_UIC", os.path.join(qt_host_bin, "uic"))
|
||||
qt_host_rcc = os.environ.get("SP_QT_HOST_RCC", "rcc")
|
||||
if platform.machine() in ("aarch64", "arm64"):
|
||||
if "SP_QT_HOST_MOC" in os.environ:
|
||||
qt_env['QT3_MOC'] = qt_host_moc
|
||||
elif os.path.isfile(qt_arm_moc):
|
||||
qt_env['QT3_MOC'] = qt_arm_moc
|
||||
if "SP_QT_HOST_UIC" in os.environ:
|
||||
qt_env['QT3_UIC'] = qt_host_uic
|
||||
elif os.path.isfile(qt_arm_uic):
|
||||
qt_env['QT3_UIC'] = qt_arm_uic
|
||||
if "SP_QT_HOST_RCC" in os.environ:
|
||||
qt_env['SP_QT_RCC'] = qt_host_rcc
|
||||
elif os.path.isfile(qt_arm_rcc):
|
||||
qt_env['SP_QT_RCC'] = qt_arm_rcc
|
||||
else:
|
||||
qt_qemu = shutil.which("qemu-aarch64-static") or shutil.which("qemu-aarch64")
|
||||
|
||||
if qt_qemu and os.path.isfile(qt_arm_moc):
|
||||
qt_env['QT3_MOC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_moc}"
|
||||
else:
|
||||
qt_env['QT3_MOC'] = qt_host_moc
|
||||
|
||||
if qt_qemu and os.path.isfile(qt_arm_uic):
|
||||
qt_env['QT3_UIC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_uic}"
|
||||
else:
|
||||
qt_env['QT3_UIC'] = qt_host_uic
|
||||
|
||||
if qt_qemu and os.path.isfile(qt_arm_rcc):
|
||||
qt_env['SP_QT_RCC'] = f"{qt_qemu} -L {qt_tool_root} {qt_arm_rcc}"
|
||||
else:
|
||||
qt_env['SP_QT_RCC'] = qt_host_rcc
|
||||
|
||||
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
|
||||
qt_flags = [
|
||||
"-D_REENTRANT",
|
||||
"-DQT_NO_DEBUG",
|
||||
"-DQT_WIDGETS_LIB",
|
||||
"-DQT_GUI_LIB",
|
||||
"-DQT_CORE_LIB",
|
||||
"-DQT_MESSAGELOGCONTEXT",
|
||||
]
|
||||
qt_env['CXXFLAGS'] += qt_flags
|
||||
qt_env['LIBPATH'] += ['#selfdrive/ui', ]
|
||||
qt_env['LIBS'] = qt_libs
|
||||
|
||||
if GetOption("clazy"):
|
||||
checks = [
|
||||
"level0",
|
||||
"level1",
|
||||
"no-range-loop",
|
||||
"no-non-pod-global-static",
|
||||
]
|
||||
qt_env['CXX'] = 'clazy'
|
||||
qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
|
||||
qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
|
||||
|
||||
Export('env', 'qt_env', 'arch', 'real_arch')
|
||||
Export('env', 'arch', 'real_arch')
|
||||
|
||||
# Build common module
|
||||
SConscript(['common/SConscript'])
|
||||
|
||||
@@ -46,9 +46,6 @@ while [[ $# -gt 0 ]]; do
|
||||
shortcut_includes_panda=1
|
||||
add_panda_targets
|
||||
;;
|
||||
--ui|-ui)
|
||||
shortcut_targets+=("selfdrive/ui/ui")
|
||||
;;
|
||||
--cereal|-cereal)
|
||||
shortcut_targets+=(
|
||||
"cereal/libcereal.a"
|
||||
|
||||
@@ -137,8 +137,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"SecOCKey", {PERSISTENT | DONT_LOG, STRING}},
|
||||
{"ShowDebugInfo", {PERSISTENT, BOOL}},
|
||||
{"ShowAllToggles", {PERSISTENT, BOOL, "0", "0", 3}},
|
||||
{"TryRaylibUI", {PERSISTENT, BOOL, "1"}},
|
||||
{"UseOldUI", {PERSISTENT, BOOL, "0", std::nullopt, 0, SETTINGS_SIMPLE}},
|
||||
{"UsePrebuilt", {PERSISTENT, BOOL, "1"}},
|
||||
{"RouteCount", {PERSISTENT, INT, "0"}},
|
||||
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||
|
||||
@@ -7,19 +7,6 @@ class Spinner:
|
||||
def __init__(self):
|
||||
self.spinner_proc = None
|
||||
|
||||
# Prefer the legacy compiled spinner on device.
|
||||
legacy_spinner = os.path.join(BASEDIR, "selfdrive", "ui", "spinner")
|
||||
if os.path.isfile("/TICI") and os.path.isfile(legacy_spinner) and os.access(legacy_spinner, os.X_OK):
|
||||
try:
|
||||
self.spinner_proc = subprocess.Popen([legacy_spinner],
|
||||
stdin=subprocess.PIPE,
|
||||
cwd=os.path.join(BASEDIR, "selfdrive", "ui"),
|
||||
close_fds=True)
|
||||
return
|
||||
except OSError:
|
||||
self.spinner_proc = None
|
||||
|
||||
# Raylib spinner requires Python deps from the repo virtualenv.
|
||||
spinner_cwd = os.path.join(BASEDIR, "system", "ui")
|
||||
venv_python = os.path.join(BASEDIR, ".venv", "bin", "python")
|
||||
python_exec = venv_python if os.path.isfile(venv_python) else "python3"
|
||||
|
||||
@@ -9,18 +9,6 @@ class TextWindow:
|
||||
def __init__(self, text):
|
||||
self.text_proc = None
|
||||
|
||||
# Prefer the legacy compiled text window on device.
|
||||
legacy_text = os.path.join(BASEDIR, "selfdrive", "ui", "text")
|
||||
if os.path.isfile("/TICI") and os.path.isfile(legacy_text) and os.access(legacy_text, os.X_OK):
|
||||
try:
|
||||
self.text_proc = subprocess.Popen([legacy_text, text],
|
||||
stdin=subprocess.PIPE,
|
||||
cwd=os.path.join(BASEDIR, "selfdrive", "ui"),
|
||||
close_fds=True)
|
||||
return
|
||||
except OSError:
|
||||
self.text_proc = None
|
||||
|
||||
text_cwd = os.path.join(BASEDIR, "system", "ui")
|
||||
venv_python = os.path.join(BASEDIR, ".venv", "bin", "python")
|
||||
python_exec = venv_python if os.path.isfile(venv_python) else "python3"
|
||||
|
||||
@@ -203,6 +203,6 @@ Compilation validates JIT capture/replay, pickle round-trip, finite outputs, met
|
||||
2. Confirm `modeld` stays running.
|
||||
3. Confirm finite `modelV2` path, lane-line, lead, pose, and action data.
|
||||
4. Confirm `driverStateV2` on both supported camera resolutions.
|
||||
5. Test download, selection, deletion, randomization, migration, and fallback in QT, raylib/mici, and Galaxy.
|
||||
5. Test download, selection, deletion, randomization, migration, and fallback in both device UIs and Galaxy.
|
||||
|
||||
The built-in RDF artifact is `selfdrive/modeld/models/driving_tinygrad.pkl`. If migration cannot download the selected v23 artifact, StarPilot switches to that built-in model.
|
||||
|
||||
@@ -48,7 +48,7 @@ Use `./dev` for host-native tools. It creates and reuses an isolated environment
|
||||
./dev shell
|
||||
```
|
||||
|
||||
For desktop UI work, use `./c3`, `./c4`, or `./raybig`. These commands use the same isolated host environment.
|
||||
For desktop UI work, use `./c3` or `./c4`. These commands use the same isolated host environment.
|
||||
|
||||
Use `./build` when you need comma-compatible device artifacts. This is the expected validation for changes that affect compiled device code or runtime behavior:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This flow builds **device-target (`larch64`) binaries on your laptop** using a Linux/aarch64 container and a synced comma sysroot.
|
||||
|
||||
For the full StarPilot branch workflow, including host-native shorthand tools such as `./dev`, `./c3`, `./c4`, and `./raybig`, see the [StarPilot development guide](https://github.com/firestar5683/StarPilot/blob/Dom/tools/STARPILOT_DEVELOPMENT.md).
|
||||
For the full StarPilot branch workflow, including host-native shorthand tools such as `./dev`, `./c3`, and `./c4`, see the [StarPilot development guide](https://github.com/firestar5683/StarPilot/blob/Dom/tools/STARPILOT_DEVELOPMENT.md).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -71,10 +71,10 @@ This runs:
|
||||
- `SP_TICI_SYSROOT=/opt/tici-sysroot`
|
||||
- `touch prebuilt`
|
||||
|
||||
To run `scons` targets explicitly in the same device-compatible environment:
|
||||
To run SCons targets explicitly in the same device-compatible environment:
|
||||
|
||||
```bash
|
||||
scripts/laptop_device_build.sh scons selfdrive/ui/ui
|
||||
scripts/laptop_device_build.sh scons common/params_pyx.so
|
||||
```
|
||||
|
||||
On macOS, once `.comma_sysroot` is present, plain `scons ...` auto-routes to this containerized device build.
|
||||
@@ -112,7 +112,6 @@ Preferred host-side shorthand commands on this branch:
|
||||
```bash
|
||||
./c3
|
||||
./c4
|
||||
./raybig
|
||||
./dev replay
|
||||
./dev cabana
|
||||
./dev plotjuggler
|
||||
@@ -120,10 +119,9 @@ Preferred host-side shorthand commands on this branch:
|
||||
|
||||
These commands use the isolated `.host_runtime` cache so host-native artifacts do not churn the main tree.
|
||||
|
||||
Legacy direct script entrypoints still exist if needed:
|
||||
Direct script entrypoints are also available:
|
||||
|
||||
```bash
|
||||
scripts/launch_ui_desktop.sh
|
||||
scripts/launch_ui_c3_desktop.sh
|
||||
scripts/launch_ui_c4_desktop.sh
|
||||
scripts/launch_ui_raybig_desktop.sh
|
||||
```
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
exec "${ROOT_DIR}/scripts/host_tool_runner.sh" raybig "$@"
|
||||
@@ -21,7 +21,7 @@ mkdir -p "${OUT_DIR}"
|
||||
echo
|
||||
|
||||
echo "=== Process Snapshot ==="
|
||||
ps -eo pid,ppid,stat,ni,etime,comm,args | grep -E "(manager.py|selfdrive.ui.ui|/selfdrive/ui/ui|weston|loggerd|encoderd|modeld|dmonitoringmodeld)" || true
|
||||
ps -eo pid,ppid,stat,ni,etime,comm,args | grep -E "(manager.py|selfdrive.ui.ui|/selfdrive/ui/ui.py|weston|loggerd|encoderd|modeld|dmonitoringmodeld)" || true
|
||||
echo
|
||||
|
||||
echo "=== Manager State (tmux service output) ==="
|
||||
@@ -35,7 +35,7 @@ mkdir -p "${OUT_DIR}"
|
||||
echo
|
||||
|
||||
echo "=== UI PID + Watchdog Timestamp Delta ==="
|
||||
for ui_pid in $(pgrep -f "selfdrive.ui.ui|/selfdrive/ui/ui" 2>/dev/null || true); do
|
||||
for ui_pid in $(pgrep -f "selfdrive.ui.ui|/selfdrive/ui/ui.py" 2>/dev/null || true); do
|
||||
echo "ui_pid=${ui_pid}"
|
||||
wd_file="/dev/shm/wd_${ui_pid}"
|
||||
if [[ -f "${wd_file}" ]]; then
|
||||
@@ -74,7 +74,7 @@ PY
|
||||
echo
|
||||
|
||||
echo "=== open files for UI process(es) ==="
|
||||
for ui_pid in $(pgrep -f "selfdrive.ui.ui|/selfdrive/ui/ui" 2>/dev/null || true); do
|
||||
for ui_pid in $(pgrep -f "selfdrive.ui.ui|/selfdrive/ui/ui.py" 2>/dev/null || true); do
|
||||
echo "--- lsof for pid ${ui_pid} ---"
|
||||
lsof -p "${ui_pid}" 2>/dev/null | tail -n 200 || true
|
||||
done
|
||||
|
||||
+14
-38
@@ -24,9 +24,8 @@ Usage:
|
||||
./tools/host <command> [args...]
|
||||
|
||||
Commands:
|
||||
c3 Launch the desktop Qt UI from the isolated host cache.
|
||||
c3 Launch the large raylib UI from the isolated host cache.
|
||||
c4 Launch the small raylib UI from the isolated host cache.
|
||||
raybig Launch the large raylib UI from the isolated host cache.
|
||||
onroad Launch replay plus desktop UI(s) from the isolated host cache.
|
||||
replay Build and run replay from the isolated host cache.
|
||||
cabana Build and run cabana from the isolated host cache.
|
||||
@@ -43,9 +42,8 @@ Notes:
|
||||
- `cabana` uses its own host-runtime bucket, so it can run together with `plotjuggler`.
|
||||
- Other commands that share a bucket still wait on that bucket's lock.
|
||||
- `./build` remains the device-target flow.
|
||||
- For c3/c4/raybig, pass the jobs count first to preserve existing shorthand:
|
||||
- For c3/c4, pass the jobs count first to preserve existing shorthand:
|
||||
./dev c3 8
|
||||
./dev raybig 12
|
||||
- `./onroad --c3 f08912a233c1584f/2022-08-11--18-02-41/1` launches replay plus the selected desktop UI.
|
||||
- `./dev sync` refreshes all host buckets. Use `./dev sync cabana` to sync one.
|
||||
EOF
|
||||
@@ -65,7 +63,7 @@ resolve_host_bucket() {
|
||||
local name="${1:-shared}"
|
||||
|
||||
case "${name}" in
|
||||
shared|default|ui|c3|c4|raybig|onroad|replay|shell)
|
||||
shared|default|ui|c3|c4|onroad|replay|shell)
|
||||
echo "shared"
|
||||
;;
|
||||
cabana)
|
||||
@@ -235,16 +233,13 @@ purge_host_foreign_platform_artifacts() {
|
||||
esac
|
||||
}
|
||||
|
||||
purge_host_desktop_ui_artifacts() {
|
||||
rm -f \
|
||||
"${WORK_DIR}/selfdrive/ui/libqt_widgets.a" \
|
||||
"${WORK_DIR}/selfdrive/ui/libqt_util.a" \
|
||||
"${WORK_DIR}/selfdrive/ui/assets.o" \
|
||||
"${WORK_DIR}/selfdrive/ui/main.o" \
|
||||
"${WORK_DIR}/selfdrive/ui/moc_ui.o" \
|
||||
"${WORK_DIR}/selfdrive/ui/ui.o" \
|
||||
"${WORK_DIR}/selfdrive/ui/ui" \
|
||||
"${WORK_DIR}/cereal/gen/cpp/"*.capnp.o
|
||||
purge_host_generated_objects() {
|
||||
rm -f "${WORK_DIR}/cereal/gen/cpp/"*.capnp.o
|
||||
}
|
||||
|
||||
purge_host_obsolete_ui_artifacts() {
|
||||
find "${WORK_DIR}/selfdrive/ui" -maxdepth 1 -type f \
|
||||
\( -name 'ui' -o -name 'ui.macos' -o -name 'ui.larch64' -o -name '*.o' -o -name '*.a' \) -delete
|
||||
}
|
||||
|
||||
ensure_host_python_tools() {
|
||||
@@ -333,11 +328,6 @@ sync_worktree() {
|
||||
"tools/replay/tests/test_replay"
|
||||
"tools/cabana/cabana"
|
||||
"tools/cabana/tests/test_cabana"
|
||||
"selfdrive/ui/ui"
|
||||
"selfdrive/ui/ui.macos"
|
||||
"selfdrive/ui/ui.larch64"
|
||||
"selfdrive/ui/libqt_widgets.a"
|
||||
"selfdrive/ui/libqt_util.a"
|
||||
"cereal/libcereal.a"
|
||||
"cereal/libsocketmaster.a"
|
||||
"cereal/messaging/bridge"
|
||||
@@ -388,7 +378,8 @@ sync_worktree() {
|
||||
if [[ "${_capnp_before}" != "${_capnp_after}" ]]; then
|
||||
rm -rf "${SP_SCONS_CACHE_DIR:-${HOST_ROOT}/scons_cache}"
|
||||
fi
|
||||
purge_host_desktop_ui_artifacts
|
||||
purge_host_generated_objects
|
||||
purge_host_obsolete_ui_artifacts
|
||||
purge_host_foreign_platform_artifacts
|
||||
rm -f "${WORK_DIR}/third_party/libjson11.a" "${WORK_DIR}/third_party/libkaitai.a"
|
||||
sync_host_generated_headers
|
||||
@@ -478,7 +469,7 @@ launch_c3() {
|
||||
fi
|
||||
|
||||
sync_worktree
|
||||
run_in_worktree "${WORK_DIR}/scripts/launch_ui_desktop.sh" "${jobs}" "$@"
|
||||
run_in_worktree "${WORK_DIR}/scripts/launch_ui_c3_desktop.sh" "${jobs}" "$@"
|
||||
}
|
||||
|
||||
launch_c4() {
|
||||
@@ -493,18 +484,6 @@ launch_c4() {
|
||||
run_in_worktree "${WORK_DIR}/scripts/launch_ui_c4_desktop.sh" "${jobs}" "$@"
|
||||
}
|
||||
|
||||
launch_raybig() {
|
||||
local jobs
|
||||
jobs="$(default_jobs)"
|
||||
if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
|
||||
jobs="$1"
|
||||
shift || true
|
||||
fi
|
||||
|
||||
sync_worktree
|
||||
run_in_worktree "${WORK_DIR}/scripts/launch_ui_raybig_desktop.sh" "${jobs}" "$@"
|
||||
}
|
||||
|
||||
launch_onroad() {
|
||||
local jobs
|
||||
jobs="$(default_jobs)"
|
||||
@@ -609,7 +588,7 @@ main() {
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
c3|c4|raybig|onroad|replay|shell|python|pytest)
|
||||
c3|c4|onroad|replay|shell|python|pytest)
|
||||
set_host_bucket "shared"
|
||||
acquire_host_lock "${command} $*"
|
||||
;;
|
||||
@@ -650,9 +629,6 @@ main() {
|
||||
c4)
|
||||
launch_c4 "$@"
|
||||
;;
|
||||
raybig)
|
||||
launch_raybig "$@"
|
||||
;;
|
||||
onroad)
|
||||
launch_onroad "$@"
|
||||
;;
|
||||
|
||||
@@ -527,8 +527,7 @@ manager_artifacts_ready() {
|
||||
[[ -f "${ROOT_DIR}/selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so" ]] &&
|
||||
[[ -f "${ROOT_DIR}/selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/libacados_ocp_solver_lat.so" ]] &&
|
||||
[[ -f "${ROOT_DIR}/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so" ]] &&
|
||||
[[ -f "${ROOT_DIR}/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/libacados_ocp_solver_long.so" ]] &&
|
||||
[[ -f "${ROOT_DIR}/selfdrive/ui/ui" ]]
|
||||
[[ -f "${ROOT_DIR}/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/libacados_ocp_solver_long.so" ]]
|
||||
}
|
||||
|
||||
run_manager() {
|
||||
|
||||
@@ -27,24 +27,24 @@ env_var_truthy() {
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./onroad [jobs] [--c3 | --c4 | --raybig | --all | --replay-only] [--galaxy] [-nav] [--offroad] [-alert] [--cem] [--prefix name] <route-or-replay-args...>
|
||||
./onroad [jobs] [--c3 | --c4 | --all | --replay-only] [--galaxy] [-nav] [--offroad] [-alert] [--cem] [--prefix name] <route-or-replay-args...>
|
||||
|
||||
Examples:
|
||||
./onroad <route>
|
||||
./onroad --c3 <route>
|
||||
./onroad --c4 <route> --start 30
|
||||
./onroad --c4 -nav <route>
|
||||
./onroad --raybig --nav --offroad --demo
|
||||
./onroad --c3 --nav --offroad --demo
|
||||
./onroad --c4 --cem --demo
|
||||
./onroad --raybig --cem --demo
|
||||
./onroad --raybig --cem -alert --demo --no-loop
|
||||
./onroad --c3 --cem --demo
|
||||
./onroad --c3 --cem -alert --demo --no-loop
|
||||
./onroad --all <route>
|
||||
./onroad --replay-only --demo --no-vipc --no-loop
|
||||
|
||||
Notes:
|
||||
- This is host/dev only. It uses the isolated host worktree and does not touch the device path.
|
||||
- A private comma connect route still requires tools/lib/auth.py before replay can download it.
|
||||
- If no UI flag is provided, the route's logged device type selects the UI: mici/c4 -> c4, tici/tizi -> raybig unless UseOldUI was enabled.
|
||||
- If no UI flag is provided, the route's logged device type selects the UI: mici/c4 -> c4, all big devices -> c3.
|
||||
- Use multiple UI flags together if you want more than one desktop UI at once.
|
||||
- --galaxy starts a local Galaxy web session with the same preview params and prints the localhost URL. It blocks replay's logged customReserved9 stream so Galaxy can own the live Testing Grounds publisher.
|
||||
- -nav injects a fake navigation demo stream and blocks replay from publishing navInstruction/navRoute.
|
||||
@@ -101,13 +101,8 @@ parse_args() {
|
||||
UI_SELECTION_EXPLICIT=1
|
||||
shift
|
||||
;;
|
||||
--raybig)
|
||||
UI_TARGETS+=(raybig)
|
||||
UI_SELECTION_EXPLICIT=1
|
||||
shift
|
||||
;;
|
||||
--all)
|
||||
UI_TARGETS+=(c3 c4 raybig)
|
||||
UI_TARGETS+=(c3 c4)
|
||||
UI_SELECTION_EXPLICIT=1
|
||||
shift
|
||||
;;
|
||||
@@ -183,7 +178,7 @@ expand_ui_targets() {
|
||||
|
||||
case "${selection,,}" in
|
||||
all|"")
|
||||
UI_TARGETS=(c3 c4 raybig)
|
||||
UI_TARGETS=(c3 c4)
|
||||
return
|
||||
;;
|
||||
none)
|
||||
@@ -199,18 +194,18 @@ expand_ui_targets() {
|
||||
local raw=""
|
||||
for raw in "${raw_targets[@]}"; do
|
||||
case "${raw,,}" in
|
||||
c3|c4|raybig)
|
||||
c3|c4)
|
||||
normalized+=("${raw,,}")
|
||||
;;
|
||||
*)
|
||||
echo "Unknown UI target in --ui: ${raw}" >&2
|
||||
echo "Valid values: all, none, c3, c4, raybig" >&2
|
||||
echo "Valid values: all, none, c3, c4" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
local ordered_targets=(c3 c4 raybig)
|
||||
local ordered_targets=(c3 c4)
|
||||
local target=""
|
||||
for target in "${ordered_targets[@]}"; do
|
||||
local candidate=""
|
||||
@@ -224,7 +219,7 @@ expand_ui_targets() {
|
||||
}
|
||||
|
||||
dedupe_ui_targets() {
|
||||
local ordered_targets=(c3 c4 raybig)
|
||||
local ordered_targets=(c3 c4)
|
||||
local deduped=()
|
||||
local target=""
|
||||
for target in "${ordered_targets[@]}"; do
|
||||
@@ -402,7 +397,6 @@ prepare_env() {
|
||||
export USE_WEBCAM=1
|
||||
export SP_C3_FAKE_WIFI=0
|
||||
export SP_C4_FAKE_WIFI=0
|
||||
export SP_RAYBIG_FAKE_WIFI=0
|
||||
export SP_ALLOW_DESKTOP_FAKE_WIFI=0
|
||||
export SP_ONROAD_NAV_DEMO="${NAV_DEMO}"
|
||||
export SP_ONROAD_OFFROAD_DEMO="${OFFROAD_DEMO}"
|
||||
@@ -448,7 +442,7 @@ build_replay() {
|
||||
}
|
||||
|
||||
prepare_c3_runtime() {
|
||||
SP_C3_COMPILE_ONLY=1 "${ROOT_DIR}/scripts/launch_ui_desktop.sh" "${jobs}"
|
||||
SP_KEEP_DESKTOP_RUNTIME_ARTIFACTS=1 SP_C3_COMPILE_ONLY=1 "${ROOT_DIR}/scripts/launch_ui_c3_desktop.sh" "${jobs}"
|
||||
}
|
||||
|
||||
prepare_python_ui_runtime() {
|
||||
@@ -589,22 +583,6 @@ launch_galaxy() {
|
||||
echo "Access Galaxy with ${GALAXY_URL}"
|
||||
}
|
||||
|
||||
launch_c3_ui() {
|
||||
local os_ext="linux"
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
os_ext="macos"
|
||||
fi
|
||||
|
||||
local host_ui="${ROOT_DIR}/selfdrive/ui/ui.${os_ext}"
|
||||
if [[ ! -x "${host_ui}" ]]; then
|
||||
echo "Missing ${host_ui}. C3 build did not produce the desktop binary." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
"${host_ui}" &
|
||||
UI_PIDS+=("$!")
|
||||
}
|
||||
|
||||
launch_python_ui() {
|
||||
local big="$1"
|
||||
(
|
||||
@@ -680,7 +658,7 @@ if [[ "${REPLAY_ONLY}" != "1" && "${UI_SELECTION_EXPLICIT}" == "0" && ${#UI_TARG
|
||||
fi
|
||||
|
||||
if [[ "${REPLAY_ONLY}" != "1" && ${#UI_TARGETS[@]} -eq 0 ]]; then
|
||||
echo "Select at least one UI with --c3, --c4, --raybig, or use --replay-only." >&2
|
||||
echo "Select at least one UI with --c3, --c4, or use --replay-only." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -695,7 +673,7 @@ case " ${UI_TARGETS[*]-} " in
|
||||
esac
|
||||
|
||||
case " ${UI_TARGETS[*]-} " in
|
||||
*" c4 "*|*" raybig "*)
|
||||
*" c4 "*)
|
||||
prepare_python_ui_runtime
|
||||
;;
|
||||
esac
|
||||
@@ -739,16 +717,13 @@ has_raylib=0
|
||||
for local_target in "${UI_TARGETS[@]}"; do
|
||||
case "${local_target}" in
|
||||
c3)
|
||||
launch_c3_ui
|
||||
launch_python_ui 1
|
||||
has_raylib=1
|
||||
;;
|
||||
c4)
|
||||
launch_python_ui 0
|
||||
has_raylib=1
|
||||
;;
|
||||
raybig)
|
||||
launch_python_ui 1
|
||||
has_raylib=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
@@ -47,19 +47,19 @@ export PATH="${ROOT_DIR}/.venv/bin:${PATH}"
|
||||
export PYTHONPATH="${ROOT_DIR}:${ROOT_DIR}/starpilot/third_party"
|
||||
for d in "${ROOT_DIR}"/*_repo; do [[ -d "$d" ]] && export PYTHONPATH="${PYTHONPATH}:$d"; done
|
||||
[[ -d "${ROOT_DIR}/third_party/acados" ]] && export PYTHONPATH="${PYTHONPATH}:${ROOT_DIR}/third_party/acados"
|
||||
export OPENPILOT_ZMQ_NAMESPACE="${OPENPILOT_ZMQ_NAMESPACE:-desktop-raybig-$$}"
|
||||
export OPENPILOT_ZMQ_NAMESPACE="${OPENPILOT_ZMQ_NAMESPACE:-desktop-c3-$$}"
|
||||
export BIG=1
|
||||
export NOBOARD=1
|
||||
export SIMULATION=1
|
||||
export SKIP_FW_QUERY=1
|
||||
export USE_WEBCAM=1
|
||||
export PRIME_TYPE="${PRIME_TYPE:-0}"
|
||||
export SP_RAYBIG_FAKE_DRIVE_STATS="${SP_RAYBIG_FAKE_DRIVE_STATS:-1}"
|
||||
export SP_C3_FAKE_DRIVE_STATS="${SP_C3_FAKE_DRIVE_STATS:-1}"
|
||||
|
||||
backup_dir="$(mktemp -d /tmp/starpilot_raybig_ui_backup.XXXXXX)"
|
||||
backup_dir="$(mktemp -d /tmp/starpilot_c3_ui_backup.XXXXXX)"
|
||||
backup_manifest="${backup_dir}/.artifact_manifest"
|
||||
PRE_TRACKED_DIRTY="$(mktemp /tmp/starpilot_raybig_pretracked.XXXXXX)"
|
||||
POST_TRACKED_DIRTY="$(mktemp /tmp/starpilot_raybig_posttracked.XXXXXX)"
|
||||
PRE_TRACKED_DIRTY="$(mktemp /tmp/starpilot_c3_pretracked.XXXXXX)"
|
||||
POST_TRACKED_DIRTY="$(mktemp /tmp/starpilot_c3_posttracked.XXXXXX)"
|
||||
FAKE_WIFI_PID=""
|
||||
|
||||
runtime_artifacts=(
|
||||
@@ -175,7 +175,7 @@ prepare_common_host_artifacts() {
|
||||
|
||||
prepare_msgq_host_artifacts() {
|
||||
# Clear mixed-arch Python extension objects from both msgq trees. These
|
||||
# commonly conflict after switching between ./build (larch64) and ./raybig (macOS).
|
||||
# commonly conflict after switching between ./build (larch64) and ./c3 (macOS).
|
||||
remove_if_elf "msgq/ipc_pyx.o"
|
||||
remove_if_elf "msgq/visionipc/visionipc_pyx.o"
|
||||
remove_if_elf "msgq_repo/msgq/ipc_pyx.o"
|
||||
@@ -268,12 +268,12 @@ run_scons() {
|
||||
fi
|
||||
}
|
||||
|
||||
kill_stale_raybig_ui() {
|
||||
kill_stale_c3_ui() {
|
||||
pkill -f "selfdrive/ui/ui.py" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
start_fake_wifi() {
|
||||
if [[ ! "${SP_RAYBIG_FAKE_WIFI:-1}" =~ ^(1|true|yes|on)$ ]]; then
|
||||
if [[ ! "${SP_C3_FAKE_WIFI:-1}" =~ ^(1|true|yes|on)$ ]]; then
|
||||
export SP_ALLOW_DESKTOP_FAKE_WIFI=0
|
||||
return
|
||||
fi
|
||||
@@ -339,8 +339,8 @@ PY
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${SP_RAYBIG_COMPILE_ONLY:-0}" == "1" ]]; then
|
||||
echo "Raybig runtime artifacts prepared."
|
||||
if [[ "${SP_C3_COMPILE_ONLY:-0}" == "1" ]]; then
|
||||
echo "C3 runtime artifacts prepared."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -356,6 +356,6 @@ params.put_bool("IsDriverViewEnabled", False)
|
||||
PY
|
||||
|
||||
seed_starpilot_theme
|
||||
kill_stale_raybig_ui
|
||||
kill_stale_c3_ui
|
||||
start_fake_wifi
|
||||
"${PY_BIN}" selfdrive/ui/ui.py "$@"
|
||||
@@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${ROOT_DIR}"
|
||||
|
||||
if [[ ! -f .venv/bin/activate ]]; then
|
||||
echo "Missing .venv. Run tools/install_python_dependencies.sh first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
default_jobs() {
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
nproc
|
||||
elif command -v sysctl >/dev/null 2>&1; then
|
||||
sysctl -n hw.ncpu
|
||||
else
|
||||
echo 8
|
||||
fi
|
||||
}
|
||||
|
||||
jobs="$(default_jobs)"
|
||||
if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
|
||||
jobs="$1"
|
||||
shift || true
|
||||
fi
|
||||
|
||||
OS_EXT="linux"
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
OS_EXT="macos"
|
||||
fi
|
||||
HOST_UI="${ROOT_DIR}/selfdrive/ui/ui.${OS_EXT}"
|
||||
PRE_TRACKED_DIRTY="$(mktemp /tmp/starpilot_c3_pretracked.XXXXXX)"
|
||||
POST_TRACKED_DIRTY="$(mktemp /tmp/starpilot_c3_posttracked.XXXXXX)"
|
||||
BACKUP_DIR="$(mktemp -d /tmp/starpilot_c3_backup.XXXXXX)"
|
||||
BACKUP_MANIFEST="${BACKUP_DIR}/.artifact_manifest"
|
||||
FAKE_WIFI_PID=""
|
||||
|
||||
runtime_artifacts=(
|
||||
"selfdrive/ui/ui"
|
||||
"common/libcommon.a"
|
||||
"common/transformations/libtransformations.a"
|
||||
"cereal/libsocketmaster.a"
|
||||
"msgq_repo/libmsgq.a"
|
||||
"msgq_repo/libvisionipc.a"
|
||||
"common/params_pyx.so"
|
||||
"common/transformations/transformations.so"
|
||||
"msgq_repo/msgq/ipc_pyx.so"
|
||||
"msgq_repo/msgq/visionipc/visionipc_pyx.so"
|
||||
)
|
||||
|
||||
collect_tracked_dirty() {
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
if ! git -C "${ROOT_DIR}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
git -C "${ROOT_DIR}" status --porcelain --untracked-files=no | sed -E 's/^.. //'
|
||||
}
|
||||
|
||||
backup_artifact() {
|
||||
local rel="$1"
|
||||
local src="${ROOT_DIR}/${rel}"
|
||||
echo "${rel}" >> "${BACKUP_MANIFEST}"
|
||||
if [[ -f "${src}" ]]; then
|
||||
mkdir -p "${BACKUP_DIR}/$(dirname "${rel}")"
|
||||
cp -f "${src}" "${BACKUP_DIR}/${rel}"
|
||||
fi
|
||||
}
|
||||
|
||||
restore_runtime_artifacts() {
|
||||
if [[ ! -d "${BACKUP_DIR}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -f "${BACKUP_MANIFEST}" ]]; then
|
||||
while IFS= read -r rel; do
|
||||
[[ -z "${rel}" ]] && continue
|
||||
if [[ -f "${BACKUP_DIR}/${rel}" ]]; then
|
||||
cp -f "${BACKUP_DIR}/${rel}" "${ROOT_DIR}/${rel}"
|
||||
else
|
||||
rm -f "${ROOT_DIR}/${rel}"
|
||||
fi
|
||||
done < "${BACKUP_MANIFEST}"
|
||||
fi
|
||||
|
||||
rm -rf "${BACKUP_DIR}"
|
||||
}
|
||||
|
||||
restore_new_tracked_changes() {
|
||||
if ! collect_tracked_dirty > "${POST_TRACKED_DIRTY}"; then
|
||||
return
|
||||
fi
|
||||
|
||||
while IFS= read -r path; do
|
||||
[[ -z "${path}" ]] && continue
|
||||
if ! grep -Fxq "${path}" "${PRE_TRACKED_DIRTY}"; then
|
||||
git -C "${ROOT_DIR}" checkout -- "${path}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
done < "${POST_TRACKED_DIRTY}"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
restore_runtime_artifacts
|
||||
restore_new_tracked_changes
|
||||
stop_fake_wifi
|
||||
rm -f "${PRE_TRACKED_DIRTY}" "${POST_TRACKED_DIRTY}"
|
||||
}
|
||||
|
||||
start_fake_wifi() {
|
||||
if [[ ! "${SP_C3_FAKE_WIFI:-1}" =~ ^(1|true|yes|on)$ ]]; then
|
||||
export SP_ALLOW_DESKTOP_FAKE_WIFI=0
|
||||
return
|
||||
fi
|
||||
|
||||
export SP_ALLOW_DESKTOP_FAKE_WIFI=1
|
||||
"${ROOT_DIR}/.venv/bin/python3" selfdrive/debug/fake_wifi.py --network wifi --strength great --interval 0.2 &
|
||||
FAKE_WIFI_PID=$!
|
||||
}
|
||||
|
||||
seed_starpilot_theme() {
|
||||
"${ROOT_DIR}/.venv/bin/python3" - <<'PY'
|
||||
from openpilot.starpilot.common.starpilot_functions import seed_desktop_theme_assets
|
||||
|
||||
seed_desktop_theme_assets()
|
||||
PY
|
||||
}
|
||||
|
||||
starpilot_theme_runtime_ok() {
|
||||
"${ROOT_DIR}/.venv/bin/python3" - <<'PY'
|
||||
import openpilot.selfdrive.controls.lib.lateral_mpc_lib.c_generated_code.acados_ocp_solver_pyx # noqa: F401
|
||||
import openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.c_generated_code.acados_ocp_solver_pyx # noqa: F401
|
||||
PY
|
||||
}
|
||||
|
||||
ensure_starpilot_theme_runtime() {
|
||||
if starpilot_theme_runtime_ok >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Preparing C3 StarPilot theme runtime extensions..."
|
||||
remove_if_elf "selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so"
|
||||
remove_if_elf "selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so"
|
||||
scons -j"${jobs}" \
|
||||
selfdrive/controls/lib/lateral_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so \
|
||||
selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code/acados_ocp_solver_pyx.so
|
||||
}
|
||||
|
||||
stop_fake_wifi() {
|
||||
if [[ -n "${FAKE_WIFI_PID}" ]]; then
|
||||
kill "${FAKE_WIFI_PID}" >/dev/null 2>&1 || true
|
||||
FAKE_WIFI_PID=""
|
||||
fi
|
||||
}
|
||||
|
||||
archive_is_aarch64_elf() {
|
||||
local path="$1"
|
||||
[[ -f "${path}" ]] || return 1
|
||||
if command -v readelf >/dev/null 2>&1; then
|
||||
readelf -h "${path}" 2>/dev/null | grep -iq "aarch64"
|
||||
else
|
||||
objdump -a "${path}" 2>/dev/null | head -n 12 | grep -iqE "elf64-littleaarch64|aarch64"
|
||||
fi
|
||||
}
|
||||
|
||||
remove_if_elf() {
|
||||
local rel="$1"
|
||||
local path="${ROOT_DIR}/${rel}"
|
||||
if [[ -f "${path}" ]] && file "${path}" | grep -q "ELF"; then
|
||||
rm -f "${path}"
|
||||
fi
|
||||
}
|
||||
|
||||
purge_objects() {
|
||||
local root="$1"
|
||||
if [[ -d "${root}" ]]; then
|
||||
find "${root}" -type f \( -name '*.o' -o -name '*.os' \) -delete
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_host_artifacts() {
|
||||
if archive_is_aarch64_elf "${ROOT_DIR}/common/libcommon.a"; then
|
||||
rm -f "${ROOT_DIR}/common/libcommon.a" "${ROOT_DIR}/common/params_pyx.o"
|
||||
purge_objects "${ROOT_DIR}/common"
|
||||
fi
|
||||
|
||||
if archive_is_aarch64_elf "${ROOT_DIR}/cereal/libsocketmaster.a"; then
|
||||
rm -f "${ROOT_DIR}/cereal/libsocketmaster.a"
|
||||
purge_objects "${ROOT_DIR}/cereal/messaging"
|
||||
fi
|
||||
|
||||
if archive_is_aarch64_elf "${ROOT_DIR}/common/transformations/libtransformations.a"; then
|
||||
rm -f "${ROOT_DIR}/common/transformations/libtransformations.a" \
|
||||
"${ROOT_DIR}/common/transformations/transformations.o"
|
||||
purge_objects "${ROOT_DIR}/common/transformations"
|
||||
fi
|
||||
|
||||
if archive_is_aarch64_elf "${ROOT_DIR}/msgq_repo/libmsgq.a" || archive_is_aarch64_elf "${ROOT_DIR}/msgq_repo/libvisionipc.a"; then
|
||||
rm -f "${ROOT_DIR}/msgq_repo/libmsgq.a" "${ROOT_DIR}/msgq_repo/libvisionipc.a"
|
||||
purge_objects "${ROOT_DIR}/msgq_repo/msgq"
|
||||
purge_objects "${ROOT_DIR}/msgq_repo/msgq/visionipc"
|
||||
fi
|
||||
|
||||
remove_if_elf "common/params_pyx.so"
|
||||
remove_if_elf "common/transformations/transformations.so"
|
||||
remove_if_elf "msgq_repo/msgq/ipc_pyx.so"
|
||||
remove_if_elf "msgq_repo/msgq/visionipc/visionipc_pyx.so"
|
||||
|
||||
purge_objects "${ROOT_DIR}/selfdrive/ui"
|
||||
purge_objects "${ROOT_DIR}/starpilot/ui"
|
||||
rm -f "${ROOT_DIR}/selfdrive/ui/libqt_widgets.a" "${ROOT_DIR}/selfdrive/ui/libqt_util.a"
|
||||
rm -f "${ROOT_DIR}/selfdrive/ui/ui"
|
||||
}
|
||||
|
||||
collect_tracked_dirty > "${PRE_TRACKED_DIRTY}" || true
|
||||
trap cleanup EXIT
|
||||
|
||||
for rel in "${runtime_artifacts[@]}"; do
|
||||
backup_artifact "${rel}"
|
||||
done
|
||||
|
||||
source .venv/bin/activate
|
||||
if [[ -d /opt/homebrew/bin ]]; then
|
||||
export PATH="/opt/homebrew/bin:${PATH}"
|
||||
fi
|
||||
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
# Keep desktop host builds on Apple toolchain even if shell exports Homebrew llvm.
|
||||
export CC="/usr/bin/clang"
|
||||
export CXX="/usr/bin/clang++"
|
||||
export AR="/usr/bin/ar"
|
||||
export RANLIB="/usr/bin/ranlib"
|
||||
fi
|
||||
unset CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
|
||||
|
||||
prepare_host_artifacts
|
||||
|
||||
export PYTHONPATH="${ROOT_DIR}:${ROOT_DIR}/starpilot/third_party"
|
||||
for d in "${ROOT_DIR}"/*_repo; do [[ -d "$d" ]] && export PYTHONPATH="${PYTHONPATH}:$d"; done
|
||||
[[ -d "${ROOT_DIR}/third_party/acados" ]] && export PYTHONPATH="${PYTHONPATH}:${ROOT_DIR}/third_party/acados"
|
||||
export OPENPILOT_ZMQ_NAMESPACE="${OPENPILOT_ZMQ_NAMESPACE:-desktop-c3-$$}"
|
||||
|
||||
export SP_DISABLE_AUTO_DEVICE_SCONS=1
|
||||
scons -j"${jobs}" selfdrive/ui/ui
|
||||
|
||||
cp -f "${ROOT_DIR}/selfdrive/ui/ui" "${HOST_UI}"
|
||||
cleanup
|
||||
trap - EXIT
|
||||
|
||||
if [[ "${SP_C3_COMPILE_ONLY:-0}" == "1" ]]; then
|
||||
echo "C3 UI binary prepared."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ensure_starpilot_theme_runtime
|
||||
seed_starpilot_theme
|
||||
start_fake_wifi
|
||||
trap stop_fake_wifi EXIT
|
||||
"${HOST_UI}" "$@"
|
||||
rc=$?
|
||||
stop_fake_wifi
|
||||
trap - EXIT
|
||||
exit "${rc}"
|
||||
@@ -9,14 +9,14 @@ usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/starpilot_build_flow.sh verify
|
||||
scripts/starpilot_build_flow.sh mac [jobs]
|
||||
scripts/starpilot_build_flow.sh mac
|
||||
scripts/starpilot_build_flow.sh device [jobs]
|
||||
scripts/starpilot_build_flow.sh laptop-setup [device-host]
|
||||
scripts/starpilot_build_flow.sh laptop-device [jobs]
|
||||
|
||||
Modes:
|
||||
verify Check critical StarPilot parity build guards in-tree.
|
||||
mac Run macOS developer validation build (Qt UI + Python compile checks).
|
||||
mac Run macOS developer Python validation checks.
|
||||
device Run full on-device build (comma hardware only) and set prebuilt flag.
|
||||
laptop-setup Prepare laptop device-build environment (venv + image + sysroot).
|
||||
laptop-device Run full device-target build in Linux/aarch64 container on laptop.
|
||||
@@ -61,20 +61,6 @@ verify_tree() {
|
||||
echo "OK: timed.py guards timezonefinder usage."
|
||||
fi
|
||||
|
||||
if ! rg -q "if os.path.isfile\\(\"/TICI\"\\)" common/spinner.py; then
|
||||
echo "FAIL: common/spinner.py missing device-only legacy spinner path."
|
||||
failed=1
|
||||
else
|
||||
echo "OK: spinner uses device-only legacy fallback."
|
||||
fi
|
||||
|
||||
if ! rg -q "if os.path.isfile\\(\"/TICI\"\\)" common/text_window.py; then
|
||||
echo "FAIL: common/text_window.py missing device-only legacy text path."
|
||||
failed=1
|
||||
else
|
||||
echo "OK: text window uses device-only legacy fallback."
|
||||
fi
|
||||
|
||||
if ! source .venv/bin/activate >/dev/null 2>&1; then
|
||||
echo "FAIL: .venv is required for loggerd import checks."
|
||||
failed=1
|
||||
@@ -107,7 +93,6 @@ PY
|
||||
}
|
||||
|
||||
build_mac() {
|
||||
local jobs="${1:-8}"
|
||||
require_venv
|
||||
source .venv/bin/activate
|
||||
|
||||
@@ -129,8 +114,6 @@ build_mac() {
|
||||
starpilot/system/the_galaxy \
|
||||
starpilot/system/galaxy
|
||||
|
||||
SP_DISABLE_AUTO_DEVICE_SCONS=1 scons -j"${jobs}" selfdrive/ui/ui
|
||||
|
||||
echo "mac build validation complete."
|
||||
}
|
||||
|
||||
@@ -166,7 +149,7 @@ main() {
|
||||
verify_tree
|
||||
;;
|
||||
mac)
|
||||
build_mac "${1:-8}"
|
||||
build_mac
|
||||
;;
|
||||
device)
|
||||
build_device "${1:-$(nproc)}"
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
*.cc
|
||||
fonts/*.fnt
|
||||
fonts/*.png
|
||||
translations_assets.qrc
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file alias="bootstrap-icons.svg">../../third_party/bootstrap/bootstrap-icons.svg</file>
|
||||
<file>images/button_continue_triangle.svg</file>
|
||||
<file>icons/circled_check.svg</file>
|
||||
<file>icons/circled_slash.svg</file>
|
||||
<file>icons/eye_open.svg</file>
|
||||
<file>icons/eye_closed.svg</file>
|
||||
<file>icons/close.svg</file>
|
||||
<file>icons/lock_closed.svg</file>
|
||||
<file>icons/checkmark.svg</file>
|
||||
<file>icons/warning.png</file>
|
||||
<file>icons/wifi_strength_low.svg</file>
|
||||
<file>icons/wifi_strength_medium.svg</file>
|
||||
<file>icons/wifi_strength_high.svg</file>
|
||||
<file>icons/wifi_strength_full.svg</file>
|
||||
|
||||
<file alias="languages.json">../ui/translations/languages.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -52,6 +52,9 @@ HYUNDAI_ELANTRA_STOPPED_LEAD_MAX_EGO_SPEED = 2.0
|
||||
HYUNDAI_ELANTRA_STOPPED_LEAD_MAX_SPEED = 0.5
|
||||
HYUNDAI_ELANTRA_STOPPED_LEAD_MIN_CLOSING_SPEED = 0.25
|
||||
HYUNDAI_ELANTRA_STOPPED_LEAD_MAX_CREEP_ACCEL = 0.05
|
||||
HYUNDAI_SANTA_FE_FINAL_STOP_MAX_SPEED = 1.0
|
||||
HYUNDAI_SANTA_FE_FINAL_STOP_CAP_BP = [0.0, 0.2, 0.5, HYUNDAI_SANTA_FE_FINAL_STOP_MAX_SPEED]
|
||||
HYUNDAI_SANTA_FE_FINAL_STOP_CAP_V = [-0.25, -0.30, -0.50, -0.90]
|
||||
|
||||
|
||||
def get_bolt_acc_pedal_friction_bias(output_accel, a_target, v_ego):
|
||||
@@ -131,6 +134,9 @@ class LongControlVehicleTuning:
|
||||
self.is_hyundai_elantra_2021 = bool(
|
||||
CP.brand == "hyundai" and str(getattr(CP, "carFingerprint", "")) == "HYUNDAI_ELANTRA_2021"
|
||||
)
|
||||
self.is_hyundai_santa_fe_2022 = bool(
|
||||
CP.brand == "hyundai" and str(getattr(CP, "carFingerprint", "")) == "HYUNDAI_SANTA_FE_2022"
|
||||
)
|
||||
self.is_bolt_acc_pedal_friction_car = bool(
|
||||
CP.brand == "gm" and
|
||||
CP.enableGasInterceptorDEPRECATED and
|
||||
@@ -153,6 +159,14 @@ class LongControlVehicleTuning:
|
||||
|
||||
def shape_stopping_accel(self, output_accel, a_target, should_stop, v_ego, has_lead, stop_accel):
|
||||
"""Release a stale hard lead brake once the stop target has eased."""
|
||||
if (
|
||||
self.is_hyundai_santa_fe_2022 and
|
||||
v_ego <= HYUNDAI_SANTA_FE_FINAL_STOP_MAX_SPEED and
|
||||
a_target <= 0.1
|
||||
):
|
||||
final_stop_cap = float(interp(v_ego, HYUNDAI_SANTA_FE_FINAL_STOP_CAP_BP, HYUNDAI_SANTA_FE_FINAL_STOP_CAP_V))
|
||||
return max(float(output_accel), final_stop_cap)
|
||||
|
||||
if (
|
||||
not self.is_hyundai_elantra_2021 or
|
||||
not has_lead or not should_stop or v_ego > 2.0 or
|
||||
|
||||
@@ -1217,6 +1217,15 @@ def test_gm_stock_truck_target_filter_bypasses_low_speed_and_other_cars():
|
||||
assert bolt_tuning.shape_gm_truck_accel_target(-0.10, 20.0, False) == pytest.approx(-0.10)
|
||||
|
||||
|
||||
def test_santa_fe_final_stop_cap_softens_only_last_kmh():
|
||||
CP = make_longcontrol_cp(brand="hyundai", carFingerprint="HYUNDAI_SANTA_FE_2022")
|
||||
tuning = LongControl(CP).vehicle_tuning
|
||||
|
||||
assert tuning.shape_stopping_accel(-2.0, -0.2, True, 0.2, False, -2.0) == pytest.approx(-0.30)
|
||||
assert tuning.shape_stopping_accel(-2.0, -0.2, True, 1.5, False, -2.0) == pytest.approx(-2.0)
|
||||
assert tuning.shape_stopping_accel(-2.0, 0.3, False, 0.2, False, -2.0) == pytest.approx(-2.0)
|
||||
|
||||
|
||||
def test_toyota_sienna_target_filter_smooths_mild_high_speed_handoffs():
|
||||
CP = make_longcontrol_cp(brand="toyota", carFingerprint=TOYOTA_CAR.TOYOTA_SIENNA_4TH_GEN)
|
||||
tuning = vehicle_tunes.LongControlVehicleTuning(CP)
|
||||
|
||||
+28
-123
@@ -1,128 +1,33 @@
|
||||
import json
|
||||
import os
|
||||
Import('env', 'qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations')
|
||||
Import('env', 'arch', 'common')
|
||||
|
||||
base_libs = [common, messaging, visionipc, transformations,
|
||||
'm', 'OpenCL', 'ssl', 'crypto', 'pthread'] + qt_env["LIBS"]
|
||||
if GetOption('extras') and arch != "Darwin":
|
||||
raylib_env = env.Clone()
|
||||
raylib_env['LIBPATH'] += [f'#third_party/raylib/{arch}/']
|
||||
raylib_env['LINKFLAGS'].append('-Wl,-strip-debug')
|
||||
|
||||
base_libs += ['avcodec', 'avformat', 'avutil', 'swresample', 'yuv']
|
||||
raylib_libs = common + ["raylib"]
|
||||
if arch == "larch64":
|
||||
raylib_libs += ["GLESv2", "wayland-client", "wayland-egl", "EGL"]
|
||||
else:
|
||||
raylib_libs += ["GL"]
|
||||
|
||||
# OpenMAX is only available in the device-target runtime/sysroot. Host desktop
|
||||
# UI builds on Linux should not need or link it.
|
||||
if arch == 'larch64':
|
||||
base_libs.append('OmxCore')
|
||||
release = "release3"
|
||||
installers = [
|
||||
("openpilot", release),
|
||||
("openpilot_test", f"{release}-staging"),
|
||||
("openpilot_nightly", "nightly"),
|
||||
("openpilot_internal", "nightly-dev"),
|
||||
]
|
||||
|
||||
if arch == 'larch64':
|
||||
base_libs.append('EGL')
|
||||
cont = raylib_env.Command("installer/continue_openpilot.o", "installer/continue_openpilot.sh",
|
||||
"ld -r -b binary -o $TARGET $SOURCE")
|
||||
inter = raylib_env.Command("installer/inter_ttf.o", "installer/inter-ascii.ttf",
|
||||
"ld -r -b binary -o $TARGET $SOURCE")
|
||||
for name, branch in installers:
|
||||
defines = {'BRANCH': f"'\"{branch}\"'"}
|
||||
if "internal" in name:
|
||||
defines['INTERNAL'] = "1"
|
||||
|
||||
if arch == "Darwin":
|
||||
del base_libs[base_libs.index('OpenCL')]
|
||||
qt_env['FRAMEWORKS'] += ['OpenCL']
|
||||
|
||||
# FIXME: remove this once we're on 5.15 (24.04)
|
||||
qt_env['CXXFLAGS'] += ["-Wno-deprecated-declarations"]
|
||||
|
||||
qt_util = qt_env.Library("qt_util", ["#selfdrive/ui/qt/api.cc", "#selfdrive/ui/qt/util.cc"], LIBS=base_libs)
|
||||
widgets_src = ["qt/widgets/input.cc", "qt/prime_state.cc",
|
||||
"qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc",
|
||||
"qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc",
|
||||
"qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc",
|
||||
"qt/request_repeater.cc", "qt/qt_window.cc", "qt/network/networking.cc", "qt/network/wifi_manager.cc"]
|
||||
|
||||
starpilot_widgets_src = ["../../starpilot/ui/qt/widgets/starpilot_controls.cc"]
|
||||
widgets_src += starpilot_widgets_src
|
||||
|
||||
widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=base_libs)
|
||||
Export('widgets')
|
||||
qt_libs = [widgets, qt_util] + base_libs
|
||||
|
||||
qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc",
|
||||
"qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
|
||||
"qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc",
|
||||
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc",
|
||||
"qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc", "qt/onroad/model.cc",
|
||||
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"]
|
||||
|
||||
qt_env['CPPPATH'] += ["../../starpilot/ui/screenrecorder/openmax/include/"]
|
||||
|
||||
starpilot_src = ["../../starpilot/ui/starpilot_ui.cc", "../../starpilot/ui/qt/offroad/data_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/device_settings.cc", "../../starpilot/ui/qt/offroad/starpilot_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/expandable_multi_option_dialog.cc",
|
||||
"../../starpilot/ui/qt/offroad/lateral_settings.cc", "../../starpilot/ui/qt/offroad/longitudinal_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/maps_settings.cc", "../../starpilot/ui/qt/offroad/model_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/navigation_settings.cc", "../../starpilot/ui/qt/offroad/sounds_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/theme_settings.cc", "../../starpilot/ui/qt/offroad/utilities.cc",
|
||||
"../../starpilot/ui/qt/offroad/vehicle_settings.cc", "../../starpilot/ui/qt/offroad/visual_settings.cc",
|
||||
"../../starpilot/ui/qt/offroad/wheel_settings.cc", "../../starpilot/ui/qt/onroad/starpilot_annotated_camera.cc",
|
||||
"../../starpilot/ui/qt/onroad/starpilot_buttons.cc", "../../starpilot/ui/qt/onroad/starpilot_onroad.cc",
|
||||
"../../starpilot/ui/qt/widgets/developer_sidebar.cc", "../../starpilot/ui/qt/widgets/drive_stats.cc",
|
||||
"../../starpilot/ui/qt/widgets/drive_summary.cc",
|
||||
"../../starpilot/ui/qt/widgets/navigation_functions.cc",
|
||||
"../../starpilot/ui/screenrecorder/omx_encoder.cc", "../../starpilot/ui/screenrecorder/screenrecorder.cc"]
|
||||
qt_src += starpilot_src
|
||||
|
||||
# build translation files
|
||||
with open(File("translations/languages.json").abspath) as f:
|
||||
languages = json.loads(f.read())
|
||||
translation_sources = [f"#selfdrive/ui/translations/{l}.ts" for l in languages.values()]
|
||||
translation_targets = [src.replace(".ts", ".qm") for src in translation_sources]
|
||||
lrelease_bin = os.environ.get("SP_QT_HOST_LRELEASE", "lrelease") if arch == 'larch64' else 'lrelease'
|
||||
|
||||
lrelease = qt_env.Command(translation_targets, translation_sources, f"{lrelease_bin} $SOURCES")
|
||||
qt_env.NoClean(translation_sources)
|
||||
qt_env.Precious(translation_sources)
|
||||
|
||||
# create qrc file for compiled translations to include with assets
|
||||
translations_assets_src = "#selfdrive/assets/translations_assets.qrc"
|
||||
with open(File(translations_assets_src).abspath, 'w') as f:
|
||||
f.write('<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n')
|
||||
f.write('\n'.join([f'<file alias="{l}">../ui/translations/{l}.qm</file>' for l in languages.values()]))
|
||||
f.write('\n</qresource>\n</RCC>')
|
||||
|
||||
# build assets
|
||||
assets = "#selfdrive/assets/assets.cc"
|
||||
assets_src = "#selfdrive/assets/assets.qrc"
|
||||
rcc_bin = qt_env.get("SP_QT_RCC", "rcc")
|
||||
qt_env.Command(assets, [assets_src, translations_assets_src], f"{rcc_bin} $SOURCES -o $TARGET")
|
||||
qt_env.Depends(assets, Glob('#selfdrive/assets/*', exclude=[assets, assets_src, translations_assets_src, "#selfdrive/assets/assets.o"]) + [lrelease])
|
||||
asset_obj = qt_env.Object("assets", assets)
|
||||
|
||||
# build main UI
|
||||
qt_env.Program("ui", qt_src + [asset_obj], LIBS=qt_libs)
|
||||
if GetOption('extras'):
|
||||
qt_src.remove("main.cc") # replaced by test_runner
|
||||
qt_env.Program('tests/test_translations', [asset_obj, 'tests/test_runner.cc', 'tests/test_translations.cc'] + qt_src, LIBS=qt_libs)
|
||||
|
||||
# build installers
|
||||
if arch != "Darwin":
|
||||
raylib_env = env.Clone()
|
||||
raylib_env['LIBPATH'] += [f'#third_party/raylib/{arch}/']
|
||||
raylib_env['LINKFLAGS'].append('-Wl,-strip-debug')
|
||||
|
||||
raylib_libs = common + ["raylib"]
|
||||
if arch == "larch64":
|
||||
raylib_libs += ["GLESv2", "wayland-client", "wayland-egl", "EGL"]
|
||||
else:
|
||||
raylib_libs += ["GL"]
|
||||
|
||||
release = "release3"
|
||||
installers = [
|
||||
("openpilot", release),
|
||||
("openpilot_test", f"{release}-staging"),
|
||||
("openpilot_nightly", "nightly"),
|
||||
("openpilot_internal", "nightly-dev"),
|
||||
]
|
||||
|
||||
cont = raylib_env.Command("installer/continue_openpilot.o", "installer/continue_openpilot.sh",
|
||||
"ld -r -b binary -o $TARGET $SOURCE")
|
||||
inter = raylib_env.Command("installer/inter_ttf.o", "installer/inter-ascii.ttf",
|
||||
"ld -r -b binary -o $TARGET $SOURCE")
|
||||
for name, branch in installers:
|
||||
d = {'BRANCH': f"'\"{branch}\"'"}
|
||||
if "internal" in name:
|
||||
d['INTERNAL'] = "1"
|
||||
|
||||
obj = raylib_env.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=d)
|
||||
f = raylib_env.Program(f"installer/installers/installer_{name}", [obj, cont, inter], LIBS=raylib_libs)
|
||||
# keep installers small
|
||||
assert f[0].get_size() < 1900*1e3, f[0].get_size()
|
||||
obj = raylib_env.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=defines)
|
||||
installer = raylib_env.Program(f"installer/installers/installer_{name}", [obj, cont, inter], LIBS=raylib_libs)
|
||||
assert installer[0].get_size() < 1900*1e3, installer[0].get_size()
|
||||
|
||||
@@ -32,7 +32,6 @@ THEME_KEY_CONFIG = {
|
||||
COLOR_PRESETS = ["Stock", "#FFFFFF", "#178644", "#3B82F6", "#E63956", "#8B5CF6", "#F59E0B"]
|
||||
CAMERA_VIEWS = ["Auto", "Driver", "Standard", "Wide"]
|
||||
|
||||
# Mirrors starpilot/ui/qt/offroad/developer_panel.cc:200-218.
|
||||
# Keys are the int values stored in DeveloperSidebarMetric{1..7}; values are the
|
||||
# human-readable labels shown in both the row value and the picker dialog.
|
||||
DEVELOPER_SIDEBAR_METRIC_OPTIONS: dict[int, str] = {
|
||||
|
||||
@@ -355,7 +355,7 @@ class _SettingsPage(StarPilotPanel):
|
||||
def _show_labeled_select(self, title, key, options, current_value):
|
||||
"""Integer-based multi-option selector with label/value pairs (puts int).
|
||||
|
||||
Mirrors Qt's ButtonParamControl: resolve by index so no KeyError is possible.
|
||||
Resolve by index so no KeyError is possible.
|
||||
"""
|
||||
option_labels = [tr(label) for _, label in options]
|
||||
option_values = [value for value, _ in options]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "common/swaglog.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "selfdrive/ui/qt/qt_window.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/qt/window.h"
|
||||
|
||||
// Qt 5.12.8's qErrnoWarning() emits QtCriticalMsg then calls abort() directly,
|
||||
// bypassing the fatal-message path. Intercept critical+fatal Wayland messages
|
||||
// before the unconditional abort() fires and clean-exit so the manager restarts
|
||||
// us quickly instead of going through the slow abort/crash-handler path.
|
||||
void waylandAwareMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
||||
if (type == QtCriticalMsg || type == QtFatalMsg) {
|
||||
QByteArray bytes = msg.toUtf8();
|
||||
if (bytes.contains("ayland") || bytes.contains("wl_display")) {
|
||||
swagLogMessageHandler(type, context, msg);
|
||||
LOGE("UI WAYLAND EXIT: %s", bytes.constData());
|
||||
_exit(0); // clean exit; manager restarts us
|
||||
}
|
||||
}
|
||||
swagLogMessageHandler(type, context, msg);
|
||||
// Non-Wayland fatal: let Qt abort normally; crash_handler will capture it.
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
setpriority(PRIO_PROCESS, 0, -20);
|
||||
|
||||
qInstallMessageHandler(waylandAwareMessageHandler);
|
||||
initApp(argc, argv);
|
||||
|
||||
QTranslator translator;
|
||||
QString translation_file = QString::fromStdString(Params().get("LanguageSetting"));
|
||||
if (!translator.load(QString(":/%1").arg(translation_file)) && translation_file.length()) {
|
||||
qCritical() << "Failed to load translation file:" << translation_file;
|
||||
}
|
||||
|
||||
QApplication a(argc, argv);
|
||||
a.installTranslator(&translator);
|
||||
|
||||
MainWindow w;
|
||||
setMainWindow(&w);
|
||||
a.installEventFilter(&w);
|
||||
|
||||
// Pin the UI to the little cores (0-3) AFTER startup. The realtime control
|
||||
// loop (card/controlsd) runs SCHED_FIFO on core 4; this keeps the steady-state
|
||||
// UI off it so a UI stall can't preempt the control loop. Deliberately done
|
||||
// after MainWindow init so startup — and crucially restart recovery — can use
|
||||
// all cores; pinning before init starved the restarting UI on the contended
|
||||
// little cores and stretched recovery from ~30s to minutes. The per-second
|
||||
// reaffine in UIState::update keeps it pinned thereafter.
|
||||
if (!Hardware::PC()) {
|
||||
util::set_core_affinity({0, 1, 2, 3});
|
||||
}
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
@@ -105,7 +105,7 @@ class BigButton(Widget):
|
||||
LABEL_HORIZONTAL_PADDING = 40
|
||||
LABEL_VERTICAL_PADDING = 23 # visually matches 30 in figma
|
||||
|
||||
"""A lightweight stand-in for the Qt BigButton, drawn & updated each frame."""
|
||||
"""A lightweight large action button, drawn and updated each frame."""
|
||||
|
||||
def __init__(self, text: str, value: str = "", icon: Union[rl.Texture, None] = None, scroll: bool = False):
|
||||
super().__init__()
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'ui.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ui.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'ui.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_UIState_t {
|
||||
QByteArrayData data[11];
|
||||
char stringdata0[96];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_UIState_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_UIState_t qt_meta_stringdata_UIState = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 7), // "UIState"
|
||||
QT_MOC_LITERAL(1, 8, 8), // "uiUpdate"
|
||||
QT_MOC_LITERAL(2, 17, 0), // ""
|
||||
QT_MOC_LITERAL(3, 18, 1), // "s"
|
||||
QT_MOC_LITERAL(4, 20, 16), // "StarPilotUIState"
|
||||
QT_MOC_LITERAL(5, 37, 2), // "fs"
|
||||
QT_MOC_LITERAL(6, 40, 17), // "offroadTransition"
|
||||
QT_MOC_LITERAL(7, 58, 7), // "offroad"
|
||||
QT_MOC_LITERAL(8, 66, 14), // "engagedChanged"
|
||||
QT_MOC_LITERAL(9, 81, 7), // "engaged"
|
||||
QT_MOC_LITERAL(10, 89, 6) // "update"
|
||||
|
||||
},
|
||||
"UIState\0uiUpdate\0\0s\0StarPilotUIState\0"
|
||||
"fs\0offroadTransition\0offroad\0"
|
||||
"engagedChanged\0engaged\0update"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_UIState[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
4, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
3, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 34, 2, 0x06 /* Public */,
|
||||
6, 1, 39, 2, 0x06 /* Public */,
|
||||
8, 1, 42, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
10, 0, 45, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, 0x80000000 | 0, 0x80000000 | 4, 3, 5,
|
||||
QMetaType::Void, QMetaType::Bool, 7,
|
||||
QMetaType::Void, QMetaType::Bool, 9,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void UIState::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<UIState *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->uiUpdate((*reinterpret_cast< const UIState(*)>(_a[1])),(*reinterpret_cast< const StarPilotUIState(*)>(_a[2]))); break;
|
||||
case 1: _t->offroadTransition((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 2: _t->engagedChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 3: _t->update(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (UIState::*)(const UIState & , const StarPilotUIState & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&UIState::uiUpdate)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (UIState::*)(bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&UIState::offroadTransition)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (UIState::*)(bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&UIState::engagedChanged)) {
|
||||
*result = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject UIState::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_UIState.data,
|
||||
qt_meta_data_UIState,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *UIState::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *UIState::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_UIState.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int UIState::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 4)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 4;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 4)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 4;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void UIState::uiUpdate(const UIState & _t1, const StarPilotUIState & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void UIState::offroadTransition(bool _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 2
|
||||
void UIState::engagedChanged(bool _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 2, _a);
|
||||
}
|
||||
struct qt_meta_stringdata_Device_t {
|
||||
QByteArrayData data[13];
|
||||
char stringdata0[134];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_Device_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_Device_t qt_meta_stringdata_Device = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 6), // "Device"
|
||||
QT_MOC_LITERAL(1, 7, 19), // "displayPowerChanged"
|
||||
QT_MOC_LITERAL(2, 27, 0), // ""
|
||||
QT_MOC_LITERAL(3, 28, 2), // "on"
|
||||
QT_MOC_LITERAL(4, 31, 18), // "interactiveTimeout"
|
||||
QT_MOC_LITERAL(5, 50, 23), // "resetInteractiveTimeout"
|
||||
QT_MOC_LITERAL(6, 74, 7), // "timeout"
|
||||
QT_MOC_LITERAL(7, 82, 14), // "timeout_onroad"
|
||||
QT_MOC_LITERAL(8, 97, 6), // "update"
|
||||
QT_MOC_LITERAL(9, 104, 7), // "UIState"
|
||||
QT_MOC_LITERAL(10, 112, 1), // "s"
|
||||
QT_MOC_LITERAL(11, 114, 16), // "StarPilotUIState"
|
||||
QT_MOC_LITERAL(12, 131, 2) // "fs"
|
||||
|
||||
},
|
||||
"Device\0displayPowerChanged\0\0on\0"
|
||||
"interactiveTimeout\0resetInteractiveTimeout\0"
|
||||
"timeout\0timeout_onroad\0update\0UIState\0"
|
||||
"s\0StarPilotUIState\0fs"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_Device[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
6, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 1, 44, 2, 0x06 /* Public */,
|
||||
4, 0, 47, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
5, 2, 48, 2, 0x0a /* Public */,
|
||||
5, 1, 53, 2, 0x2a /* Public | MethodCloned */,
|
||||
5, 0, 56, 2, 0x2a /* Public | MethodCloned */,
|
||||
8, 2, 57, 2, 0x0a /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Bool, 3,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Int, QMetaType::Int, 6, 7,
|
||||
QMetaType::Void, QMetaType::Int, 6,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void, 0x80000000 | 9, 0x80000000 | 11, 10, 12,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void Device::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<Device *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->displayPowerChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 1: _t->interactiveTimeout(); break;
|
||||
case 2: _t->resetInteractiveTimeout((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
|
||||
case 3: _t->resetInteractiveTimeout((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 4: _t->resetInteractiveTimeout(); break;
|
||||
case 5: _t->update((*reinterpret_cast< const UIState(*)>(_a[1])),(*reinterpret_cast< const StarPilotUIState(*)>(_a[2]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (Device::*)(bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&Device::displayPowerChanged)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (Device::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&Device::interactiveTimeout)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject Device::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_Device.data,
|
||||
qt_meta_data_Device,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *Device::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *Device::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_Device.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int Device::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 6)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 6;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 6)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 6;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void Device::displayPowerChanged(bool _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void Device::interactiveTimeout()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -130,7 +130,6 @@ def render_adjacent_lanes(renderer) -> None:
|
||||
def render_path_edges(renderer) -> None:
|
||||
"""Draw colored edge strips along the driving path.
|
||||
|
||||
Qt reference: paintPathEdges in starpilot_annotated_camera.cc:732-769
|
||||
|
||||
Path edges are the area between track_edge_vertices (outer) and track_vertices (inner).
|
||||
Color selection on Python UIs:
|
||||
|
||||
@@ -19,7 +19,7 @@ def _hsla_to_color(h: float, s: float, l: float, a: float) -> rl.Color:
|
||||
|
||||
|
||||
class RainbowPath:
|
||||
"""Rainbow path renderer ported from the FrogPilot/StarPilot Qt C++ UI implementation."""
|
||||
"""Rainbow path renderer for the StarPilot onroad UI."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._hue_offset: float = 0.0
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
#include "selfdrive/ui/qt/api.h"
|
||||
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
namespace CommaApi {
|
||||
|
||||
RSA *get_rsa_private_key() {
|
||||
static std::unique_ptr<RSA, decltype(&RSA_free)> rsa_private(nullptr, RSA_free);
|
||||
if (!rsa_private) {
|
||||
FILE *fp = fopen(Path::rsa_file().c_str(), "rb");
|
||||
if (!fp) {
|
||||
qDebug() << "No RSA private key found, please run manager.py or registration.py";
|
||||
return nullptr;
|
||||
}
|
||||
rsa_private.reset(PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL));
|
||||
fclose(fp);
|
||||
}
|
||||
return rsa_private.get();
|
||||
}
|
||||
|
||||
QByteArray rsa_sign(const QByteArray &data) {
|
||||
RSA *rsa_private = get_rsa_private_key();
|
||||
if (!rsa_private) return {};
|
||||
|
||||
QByteArray sig(RSA_size(rsa_private), Qt::Uninitialized);
|
||||
unsigned int sig_len;
|
||||
int ret = RSA_sign(NID_sha256, (unsigned char*)data.data(), data.size(), (unsigned char*)sig.data(), &sig_len, rsa_private);
|
||||
assert(ret == 1);
|
||||
assert(sig.size() == sig_len);
|
||||
return sig;
|
||||
}
|
||||
|
||||
QString create_jwt(const QJsonObject &payloads, int expiry) {
|
||||
QJsonObject header = {{"alg", "RS256"}};
|
||||
|
||||
auto t = QDateTime::currentSecsSinceEpoch();
|
||||
QJsonObject payload = {{"identity", getDongleId().value_or("")}, {"nbf", t}, {"iat", t}, {"exp", t + expiry}};
|
||||
for (auto it = payloads.begin(); it != payloads.end(); ++it) {
|
||||
payload.insert(it.key(), it.value());
|
||||
}
|
||||
|
||||
auto b64_opts = QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals;
|
||||
QString jwt = QJsonDocument(header).toJson(QJsonDocument::Compact).toBase64(b64_opts) + '.' +
|
||||
QJsonDocument(payload).toJson(QJsonDocument::Compact).toBase64(b64_opts);
|
||||
|
||||
auto hash = QCryptographicHash::hash(jwt.toUtf8(), QCryptographicHash::Sha256);
|
||||
return jwt + "." + rsa_sign(hash).toBase64(b64_opts);
|
||||
}
|
||||
|
||||
} // namespace CommaApi
|
||||
|
||||
HttpRequest::HttpRequest(QObject *parent, bool create_jwt, int timeout) : create_jwt(create_jwt), QObject(parent) {
|
||||
networkTimer = new QTimer(this);
|
||||
networkTimer->setSingleShot(true);
|
||||
networkTimer->setInterval(timeout);
|
||||
connect(networkTimer, &QTimer::timeout, this, &HttpRequest::requestTimeout);
|
||||
}
|
||||
|
||||
bool HttpRequest::active() const {
|
||||
return reply != nullptr;
|
||||
}
|
||||
|
||||
bool HttpRequest::timeout() const {
|
||||
return reply && reply->error() == QNetworkReply::OperationCanceledError;
|
||||
}
|
||||
|
||||
void HttpRequest::sendRequest(const QString &requestURL, const HttpRequest::Method method) {
|
||||
if (active()) {
|
||||
qDebug() << "HttpRequest is active";
|
||||
return;
|
||||
}
|
||||
QString token;
|
||||
if (create_jwt) {
|
||||
token = CommaApi::create_jwt();
|
||||
} else {
|
||||
QString token_json = QString::fromStdString(util::read_file(util::getenv("HOME") + "/.comma/auth.json"));
|
||||
QJsonDocument json_d = QJsonDocument::fromJson(token_json.toUtf8());
|
||||
token = json_d["access_token"].toString();
|
||||
}
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(requestURL));
|
||||
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
||||
|
||||
if (!token.isEmpty()) {
|
||||
request.setRawHeader(QByteArray("Authorization"), ("JWT " + token).toUtf8());
|
||||
}
|
||||
|
||||
if (method == HttpRequest::Method::GET) {
|
||||
reply = nam()->get(request);
|
||||
} else if (method == HttpRequest::Method::DELETE) {
|
||||
reply = nam()->deleteResource(request);
|
||||
}
|
||||
|
||||
networkTimer->start();
|
||||
connect(reply, &QNetworkReply::finished, this, &HttpRequest::requestFinished);
|
||||
}
|
||||
|
||||
void HttpRequest::requestTimeout() {
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
void HttpRequest::requestFinished() {
|
||||
networkTimer->stop();
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
emit requestDone(reply->readAll(), true, reply->error());
|
||||
} else {
|
||||
QString error;
|
||||
if (reply->error() == QNetworkReply::OperationCanceledError) {
|
||||
nam()->clearAccessCache();
|
||||
nam()->clearConnectionCache();
|
||||
error = "Request timed out";
|
||||
} else {
|
||||
error = reply->errorString();
|
||||
}
|
||||
emit requestDone(error, false, reply->error());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
}
|
||||
|
||||
QNetworkAccessManager *HttpRequest::nam() {
|
||||
static QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(qApp);
|
||||
return networkAccessManager;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkReply>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
|
||||
#include "common/util.h"
|
||||
|
||||
#include "starpilot/ui/qt/widgets/starpilot_controls.h"
|
||||
|
||||
namespace CommaApi {
|
||||
|
||||
const QString BASE_URL = util::getenv("API_HOST", useKonikServer() ? "https://api.konik.ai" : "https://api.commadotai.com").c_str();
|
||||
QByteArray rsa_sign(const QByteArray &data);
|
||||
QString create_jwt(const QJsonObject &payloads = {}, int expiry = 3600);
|
||||
|
||||
} // namespace CommaApi
|
||||
|
||||
/**
|
||||
* Makes a request to the request endpoint.
|
||||
*/
|
||||
|
||||
class HttpRequest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Method {GET, DELETE};
|
||||
|
||||
explicit HttpRequest(QObject* parent, bool create_jwt = true, int timeout = 20000);
|
||||
void sendRequest(const QString &requestURL, const Method method = Method::GET);
|
||||
bool active() const;
|
||||
bool timeout() const;
|
||||
|
||||
signals:
|
||||
void requestDone(const QString &response, bool success, QNetworkReply::NetworkError error);
|
||||
|
||||
protected:
|
||||
QNetworkReply *reply = nullptr;
|
||||
|
||||
private:
|
||||
static QNetworkAccessManager *nam();
|
||||
QTimer *networkTimer = nullptr;
|
||||
bool create_jwt;
|
||||
|
||||
private slots:
|
||||
void requestTimeout();
|
||||
void requestFinished();
|
||||
};
|
||||
@@ -1,161 +0,0 @@
|
||||
#include "selfdrive/ui/qt/body.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStackedLayout>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/timing.h"
|
||||
|
||||
RecordButton::RecordButton(QWidget *parent) : QPushButton(parent) {
|
||||
setCheckable(true);
|
||||
setChecked(false);
|
||||
setFixedSize(148, 148);
|
||||
|
||||
QObject::connect(this, &QPushButton::toggled, [=]() {
|
||||
setEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
void RecordButton::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QPoint center(width() / 2, height() / 2);
|
||||
|
||||
QColor bg(isChecked() ? "#FFFFFF" : "#737373");
|
||||
QColor accent(isChecked() ? "#FF0000" : "#FFFFFF");
|
||||
if (!isEnabled()) {
|
||||
bg = QColor("#404040");
|
||||
accent = QColor("#FFFFFF");
|
||||
}
|
||||
|
||||
if (isDown()) {
|
||||
accent.setAlphaF(0.7);
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(bg);
|
||||
p.drawEllipse(center, 74, 74);
|
||||
|
||||
p.setPen(QPen(accent, 6));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawEllipse(center, 42, 42);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(accent);
|
||||
p.drawEllipse(center, 22, 22);
|
||||
}
|
||||
|
||||
|
||||
BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QWidget(parent) {
|
||||
QStackedLayout *layout = new QStackedLayout(this);
|
||||
layout->setStackingMode(QStackedLayout::StackAll);
|
||||
|
||||
QWidget *w = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout(w);
|
||||
vlayout->setMargin(45);
|
||||
layout->addWidget(w);
|
||||
|
||||
// face
|
||||
face = new QLabel();
|
||||
face->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(face);
|
||||
awake = new QMovie("../assets/body/awake.gif", {}, this);
|
||||
awake->setCacheMode(QMovie::CacheAll);
|
||||
sleep = new QMovie("../assets/body/sleep.gif", {}, this);
|
||||
sleep->setCacheMode(QMovie::CacheAll);
|
||||
|
||||
// record button
|
||||
btn = new RecordButton(this);
|
||||
vlayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||
QObject::connect(btn, &QPushButton::clicked, [=](bool checked) {
|
||||
btn->setEnabled(false);
|
||||
Params().putBool("DisableLogging", !checked);
|
||||
last_button = nanos_since_boot();
|
||||
});
|
||||
w->raise();
|
||||
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState);
|
||||
}
|
||||
|
||||
void BodyWindow::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
p.fillRect(rect(), QColor(0, 0, 0));
|
||||
|
||||
// battery outline + detail
|
||||
p.translate(width() - 136, 16);
|
||||
const QColor gray = QColor("#737373");
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(QPen(gray, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
p.drawRoundedRect(2, 2, 78, 36, 8, 8);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(gray);
|
||||
p.drawRoundedRect(84, 12, 6, 16, 4, 4);
|
||||
p.drawRect(84, 12, 3, 16);
|
||||
|
||||
// battery level
|
||||
double fuel = std::clamp(fuel_filter.x(), 0.2f, 1.0f);
|
||||
const int m = 5; // manual margin since we can't do an inner border
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(fuel > 0.25 ? QColor("#32D74B") : QColor("#FF453A"));
|
||||
p.drawRoundedRect(2 + m, 2 + m, (78 - 2*m)*fuel, 36 - 2*m, 4, 4);
|
||||
|
||||
// charging status
|
||||
if (charging) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::white);
|
||||
const QPolygonF charger({
|
||||
QPointF(12.31, 0),
|
||||
QPointF(12.31, 16.92),
|
||||
QPointF(18.46, 16.92),
|
||||
QPointF(6.15, 40),
|
||||
QPointF(6.15, 23.08),
|
||||
QPointF(0, 23.08),
|
||||
});
|
||||
p.drawPolygon(charger.translated(98, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void BodyWindow::offroadTransition(bool offroad) {
|
||||
btn->setChecked(true);
|
||||
btn->setEnabled(true);
|
||||
fuel_filter.reset(1.0);
|
||||
}
|
||||
|
||||
void BodyWindow::updateState(const UIState &s) {
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SubMaster &sm = *(s.sm);
|
||||
auto cs = sm["carState"].getCarState();
|
||||
|
||||
charging = cs.getCharging();
|
||||
fuel_filter.update(cs.getFuelGauge());
|
||||
|
||||
// TODO: use carState.standstill when that's fixed
|
||||
const bool standstill = std::abs(cs.getVEgo()) < 0.01;
|
||||
QMovie *m = standstill ? sleep : awake;
|
||||
if (m != face->movie()) {
|
||||
face->setMovie(m);
|
||||
face->movie()->start();
|
||||
}
|
||||
|
||||
// update record button state
|
||||
if (sm.updated("managerState") && (sm.rcv_time("managerState") - last_button)*1e-9 > 0.5) {
|
||||
for (auto proc : sm["managerState"].getManagerState().getProcesses()) {
|
||||
if (proc.getName() == "loggerd") {
|
||||
btn->setEnabled(true);
|
||||
btn->setChecked(proc.getRunning());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMovie>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class RecordButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RecordButton(QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
};
|
||||
|
||||
class BodyWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BodyWindow(QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
bool charging = false;
|
||||
uint64_t last_button = 0;
|
||||
FirstOrderFilter fuel_filter;
|
||||
QLabel *face;
|
||||
QMovie *awake, *sleep;
|
||||
RecordButton *btn;
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
private slots:
|
||||
void updateState(const UIState &s);
|
||||
void offroadTransition(bool onroad);
|
||||
};
|
||||
@@ -1,344 +0,0 @@
|
||||
#include "selfdrive/ui/qt/home.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QStackedWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/qt/widgets/prime.h"
|
||||
|
||||
#include "starpilot/ui/qt/widgets/drive_stats.h"
|
||||
#include "starpilot/ui/qt/widgets/drive_summary.h"
|
||||
|
||||
// HomeWindow: the container for the offroad and onroad UIs
|
||||
|
||||
HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
|
||||
QHBoxLayout *main_layout = new QHBoxLayout(this);
|
||||
main_layout->setMargin(0);
|
||||
main_layout->setSpacing(0);
|
||||
|
||||
sidebar = new Sidebar(this);
|
||||
main_layout->addWidget(sidebar);
|
||||
QObject::connect(sidebar, &Sidebar::openSettings, this, &HomeWindow::openSettings);
|
||||
|
||||
slayout = new QStackedLayout();
|
||||
main_layout->addLayout(slayout);
|
||||
|
||||
home = new OffroadHome(this);
|
||||
QObject::connect(home, &OffroadHome::openSettings, this, &HomeWindow::openSettings);
|
||||
slayout->addWidget(home);
|
||||
|
||||
onroad = new OnroadWindow(this);
|
||||
slayout->addWidget(onroad);
|
||||
|
||||
body = new BodyWindow(this);
|
||||
slayout->addWidget(body);
|
||||
|
||||
driver_view = new DriverViewWindow(this);
|
||||
connect(driver_view, &DriverViewWindow::done, [=] {
|
||||
showDriverView(false);
|
||||
});
|
||||
slayout->addWidget(driver_view);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &HomeWindow::updateState);
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, this, &HomeWindow::offroadTransition);
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, sidebar, &Sidebar::offroadTransition);
|
||||
|
||||
developer_sidebar = new DeveloperSidebar(this);
|
||||
main_layout->addWidget(developer_sidebar);
|
||||
developer_sidebar->setVisible(false);
|
||||
}
|
||||
|
||||
void HomeWindow::showSidebar(bool show) {
|
||||
sidebar->setVisible(show);
|
||||
}
|
||||
|
||||
void HomeWindow::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
const SubMaster &sm = *(s.sm);
|
||||
|
||||
// switch to the generic robot UI
|
||||
if (onroad->isVisible() && !body->isEnabled() && sm["carParams"].getCarParams().getNotCar()) {
|
||||
body->setEnabled(true);
|
||||
slayout->setCurrentWidget(body);
|
||||
}
|
||||
|
||||
const StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
const QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
|
||||
if (s.scene.started) {
|
||||
if (starpilot_scene.driver_camera_timer >= UI_FREQ / 2) {
|
||||
showDriverView(true, true);
|
||||
} else {
|
||||
if (driver_view->isVisible()) {
|
||||
sidebar->setVisible(params.getBool("Sidebar") || starpilot_toggles.value("debug_mode").toBool());
|
||||
slayout->setCurrentWidget(onroad);
|
||||
}
|
||||
|
||||
developer_sidebar->setVisible(starpilot_toggles.value("developer_sidebar").toBool());
|
||||
|
||||
starpilotUIState()->starpilot_scene.sidebars_open = developer_sidebar->isVisible() && sidebar->isVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HomeWindow::offroadTransition(bool offroad) {
|
||||
StarPilotUIState &fs = *starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
|
||||
body->setEnabled(false);
|
||||
sidebar->setVisible(offroad || params.getBool("SidebarOpen") || starpilot_toggles.value("debug_mode").toBool());
|
||||
if (offroad) {
|
||||
slayout->setCurrentWidget(home);
|
||||
|
||||
developer_sidebar->setVisible(false);
|
||||
} else {
|
||||
slayout->setCurrentWidget(onroad);
|
||||
}
|
||||
}
|
||||
|
||||
void HomeWindow::showDriverView(bool show, bool started) {
|
||||
if (show) {
|
||||
if (!started) {
|
||||
emit closeSettings();
|
||||
}
|
||||
slayout->setCurrentWidget(driver_view);
|
||||
} else {
|
||||
slayout->setCurrentWidget(home);
|
||||
}
|
||||
sidebar->setVisible(show == false);
|
||||
|
||||
developer_sidebar->setVisible(false);
|
||||
}
|
||||
|
||||
void HomeWindow::mousePressEvent(QMouseEvent* e) {
|
||||
// Handle sidebar collapsing
|
||||
if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) {
|
||||
sidebar->setVisible(!sidebar->isVisible());
|
||||
|
||||
params.putBool("SidebarOpen", sidebar->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
void HomeWindow::mouseDoubleClickEvent(QMouseEvent* e) {
|
||||
HomeWindow::mousePressEvent(e);
|
||||
const SubMaster &sm = *(uiState()->sm);
|
||||
if (sm["carParams"].getCarParams().getNotCar()) {
|
||||
if (onroad->isVisible()) {
|
||||
slayout->setCurrentWidget(body);
|
||||
} else if (body->isVisible()) {
|
||||
slayout->setCurrentWidget(onroad);
|
||||
}
|
||||
showSidebar(false);
|
||||
}
|
||||
}
|
||||
|
||||
// OffroadHome: the offroad home page
|
||||
|
||||
OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
|
||||
QVBoxLayout* main_layout = new QVBoxLayout(this);
|
||||
main_layout->setContentsMargins(40, 40, 40, 40);
|
||||
|
||||
// top header
|
||||
QHBoxLayout* header_layout = new QHBoxLayout();
|
||||
header_layout->setContentsMargins(0, 0, 0, 0);
|
||||
header_layout->setSpacing(16);
|
||||
|
||||
date = new ElidedLabel();
|
||||
header_layout->addWidget(date, 0, Qt::AlignHCenter | Qt::AlignLeft);
|
||||
|
||||
update_notif = new QPushButton(tr("UPDATE"));
|
||||
update_notif->setVisible(false);
|
||||
update_notif->setStyleSheet("background-color: #364DEF;");
|
||||
QObject::connect(update_notif, &QPushButton::clicked, [=]() { center_layout->setCurrentIndex(1); });
|
||||
header_layout->addWidget(update_notif, 0, Qt::AlignHCenter | Qt::AlignLeft);
|
||||
|
||||
alert_notif = new QPushButton();
|
||||
alert_notif->setVisible(false);
|
||||
alert_notif->setStyleSheet("background-color: #E22C2C;");
|
||||
QObject::connect(alert_notif, &QPushButton::clicked, [=] { center_layout->setCurrentIndex(2); });
|
||||
header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignLeft);
|
||||
|
||||
version = new ElidedLabel();
|
||||
header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight);
|
||||
|
||||
main_layout->addLayout(header_layout);
|
||||
|
||||
// main content
|
||||
main_layout->addSpacing(25);
|
||||
center_layout = new QStackedLayout();
|
||||
|
||||
QWidget *home_widget = new QWidget(this);
|
||||
{
|
||||
QHBoxLayout *home_layout = new QHBoxLayout(home_widget);
|
||||
home_layout->setContentsMargins(0, 0, 0, 0);
|
||||
home_layout->setSpacing(30);
|
||||
|
||||
// left: stock prime card in simple mode, StarPilot drive stats otherwise
|
||||
left_widget = new QStackedWidget(this);
|
||||
|
||||
stock_left_widget = new QStackedWidget(this);
|
||||
QVBoxLayout *left_prime_layout = new QVBoxLayout();
|
||||
left_prime_layout->setContentsMargins(0, 0, 0, 0);
|
||||
QWidget *prime_user = new PrimeUserWidget();
|
||||
prime_user->setStyleSheet(R"(
|
||||
border-radius: 10px;
|
||||
background-color: #333333;
|
||||
)");
|
||||
left_prime_layout->addWidget(prime_user);
|
||||
left_prime_layout->addStretch();
|
||||
stock_left_widget->addWidget(new LayoutWidget(left_prime_layout));
|
||||
stock_left_widget->addWidget(new PrimeAdWidget);
|
||||
stock_left_widget->setStyleSheet("border-radius: 10px;");
|
||||
QObject::connect(uiState()->prime_state, &PrimeState::changed, this, [this]() {
|
||||
stock_left_widget->setCurrentIndex(uiState()->prime_state->isSubscribed() ? 0 : 1);
|
||||
});
|
||||
left_widget->addWidget(stock_left_widget);
|
||||
|
||||
QWidget *custom_left_widget = new QWidget(this);
|
||||
custom_left_stack = new QStackedLayout(custom_left_widget);
|
||||
custom_left_stack->setContentsMargins(0, 0, 0, 0);
|
||||
custom_left_stack->addWidget(new DriveStats());
|
||||
StarPilotDriveSummary *drive_summary = new StarPilotDriveSummary(this);
|
||||
custom_left_stack->addWidget(drive_summary);
|
||||
left_widget->addWidget(custom_left_widget);
|
||||
left_widget->setCurrentIndex(params.getBool("SimpleMode") ? 0 : 1);
|
||||
|
||||
QObject::connect(drive_summary, &StarPilotDriveSummary::panelClosed, [this]() {
|
||||
custom_left_stack->setCurrentIndex(0);
|
||||
});
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, [this](bool offroad) {
|
||||
static bool previouslyOnroad = false;
|
||||
if (offroad && previouslyOnroad && !params.getBool("SimpleMode")) {
|
||||
custom_left_stack->setCurrentIndex(1);
|
||||
}
|
||||
previouslyOnroad = !offroad;
|
||||
});
|
||||
|
||||
home_layout->addWidget(left_widget, 1);
|
||||
|
||||
// right: ExperimentalModeButton, SetupWidget, Random Events Summary
|
||||
right_widget = new QStackedWidget(this);
|
||||
right_widget->setFixedWidth(750);
|
||||
|
||||
QWidget *default_right = new QWidget(this);
|
||||
QVBoxLayout *right_column = new QVBoxLayout(default_right);
|
||||
right_column->setContentsMargins(0, 0, 0, 0);
|
||||
right_column->setSpacing(30);
|
||||
|
||||
ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this);
|
||||
QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings);
|
||||
right_column->addWidget(experimental_mode, 1);
|
||||
|
||||
SetupWidget *setup_widget = new SetupWidget;
|
||||
QObject::connect(setup_widget, &SetupWidget::openSettings, this, &OffroadHome::openSettings);
|
||||
right_column->addWidget(setup_widget, 1);
|
||||
|
||||
right_widget->addWidget(default_right);
|
||||
|
||||
StarPilotDriveSummary *random_events_summary = new StarPilotDriveSummary(this, true);
|
||||
right_widget->addWidget(random_events_summary);
|
||||
right_widget->setCurrentIndex(0);
|
||||
|
||||
QObject::connect(random_events_summary, &StarPilotDriveSummary::panelClosed, [=]() {
|
||||
right_widget->setCurrentIndex(0);
|
||||
});
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, [this](bool offroad) {
|
||||
static bool previouslyOnroad = false;
|
||||
if (offroad && previouslyOnroad && !params.getBool("SimpleMode") &&
|
||||
starpilotUIState()->starpilot_scene.starpilot_toggles.value("random_events").toBool()) {
|
||||
right_widget->setCurrentIndex(1);
|
||||
}
|
||||
previouslyOnroad = !offroad;
|
||||
});
|
||||
|
||||
home_layout->addWidget(right_widget, 0);
|
||||
}
|
||||
center_layout->addWidget(home_widget);
|
||||
|
||||
// add update & alerts widgets
|
||||
update_widget = new UpdateAlert();
|
||||
QObject::connect(update_widget, &UpdateAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); });
|
||||
center_layout->addWidget(update_widget);
|
||||
alerts_widget = new OffroadAlert();
|
||||
QObject::connect(alerts_widget, &OffroadAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); });
|
||||
center_layout->addWidget(alerts_widget);
|
||||
|
||||
main_layout->addLayout(center_layout, 1);
|
||||
|
||||
// set up refresh timer
|
||||
timer = new QTimer(this);
|
||||
timer->callOnTimeout(this, &OffroadHome::refresh);
|
||||
|
||||
setStyleSheet(R"(
|
||||
* {
|
||||
color: white;
|
||||
}
|
||||
OffroadHome {
|
||||
background-color: black;
|
||||
}
|
||||
OffroadHome > QPushButton {
|
||||
padding: 15px 30px;
|
||||
border-radius: 5px;
|
||||
font-size: 40px;
|
||||
font-weight: 500;
|
||||
}
|
||||
OffroadHome > QLabel {
|
||||
font-size: 55px;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
void OffroadHome::showEvent(QShowEvent *event) {
|
||||
refresh();
|
||||
timer->start(10 * 1000);
|
||||
}
|
||||
|
||||
void OffroadHome::hideEvent(QHideEvent *event) {
|
||||
timer->stop();
|
||||
}
|
||||
|
||||
void OffroadHome::refresh() {
|
||||
bool updateAvailable = update_widget->refresh();
|
||||
int alerts = alerts_widget->refresh();
|
||||
|
||||
// pop-up new notification
|
||||
int idx = center_layout->currentIndex();
|
||||
if (!updateAvailable && !alerts) {
|
||||
idx = 0;
|
||||
} else if (updateAvailable && (!update_notif->isVisible() || (!alerts && idx == 2))) {
|
||||
idx = 1;
|
||||
} else if (alerts && (!alert_notif->isVisible() || (!updateAvailable && idx == 1))) {
|
||||
idx = 2;
|
||||
}
|
||||
center_layout->setCurrentIndex(idx);
|
||||
|
||||
update_notif->setVisible(updateAvailable);
|
||||
alert_notif->setVisible(alerts);
|
||||
if (alerts) {
|
||||
alert_notif->setText(QString::number(alerts) + (alerts > 1 ? tr(" ALERTS") : tr(" ALERT")));
|
||||
}
|
||||
|
||||
StarPilotUIState &fs = *starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
const bool simple_mode = params.getBool("SimpleMode");
|
||||
|
||||
stock_left_widget->setCurrentIndex(uiState()->prime_state->isSubscribed() ? 0 : 1);
|
||||
left_widget->setCurrentIndex(simple_mode ? 0 : 1);
|
||||
if (simple_mode) {
|
||||
custom_left_stack->setCurrentIndex(0);
|
||||
right_widget->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
date->setText(QLocale(uiState()->language.mid(5)).toString(QDateTime::currentDateTime(), "dddd, MMMM d"));
|
||||
date->setVisible(util::system_time_valid() && !simple_mode);
|
||||
|
||||
if (simple_mode) {
|
||||
version->setText(getBrand() + " " + formatStarPilotDisplayVersionDescription(QString::fromStdString(params.get("UpdaterCurrentDescription"))));
|
||||
} else {
|
||||
version->setText(getBrand() + " - " + getStarPilotDisplayVersion() + " - " + cleanModelName(starpilot_toggles.value("model_name").toString()));
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStackedLayout>
|
||||
#include <QStackedWidget>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "selfdrive/ui/qt/offroad/driverview.h"
|
||||
#include "selfdrive/ui/qt/body.h"
|
||||
#include "selfdrive/ui/qt/onroad/onroad_home.h"
|
||||
#include "selfdrive/ui/qt/sidebar.h"
|
||||
#include "selfdrive/ui/qt/widgets/controls.h"
|
||||
#include "selfdrive/ui/qt/widgets/offroad_alerts.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
#include "starpilot/ui/qt/widgets/developer_sidebar.h"
|
||||
|
||||
class OffroadHome : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OffroadHome(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void openSettings(int index = 0, const QString ¶m = "");
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void hideEvent(QHideEvent *event) override;
|
||||
void refresh();
|
||||
|
||||
Params params;
|
||||
|
||||
QTimer* timer;
|
||||
ElidedLabel* version;
|
||||
QStackedLayout* center_layout;
|
||||
UpdateAlert *update_widget;
|
||||
OffroadAlert* alerts_widget;
|
||||
QPushButton* alert_notif;
|
||||
QPushButton* update_notif;
|
||||
|
||||
ElidedLabel* date;
|
||||
QStackedWidget *left_widget;
|
||||
QStackedWidget *stock_left_widget;
|
||||
QStackedLayout *custom_left_stack;
|
||||
QStackedWidget *right_widget;
|
||||
};
|
||||
|
||||
class HomeWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HomeWindow(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void openSettings(int index = 0, const QString ¶m = "");
|
||||
void closeSettings();
|
||||
|
||||
public slots:
|
||||
void offroadTransition(bool offroad);
|
||||
void showDriverView(bool show, bool started=false);
|
||||
void showSidebar(bool show);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* e) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* e) override;
|
||||
|
||||
private:
|
||||
Sidebar *sidebar;
|
||||
OffroadHome *home;
|
||||
OnroadWindow *onroad;
|
||||
BodyWindow *body;
|
||||
DriverViewWindow *driver_view;
|
||||
QStackedLayout *slayout;
|
||||
|
||||
DeveloperSidebar *developer_sidebar;
|
||||
|
||||
Params params;
|
||||
|
||||
private slots:
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
};
|
||||
@@ -1,151 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'api.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "api.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'api.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_HttpRequest_t {
|
||||
QByteArrayData data[9];
|
||||
char stringdata0[107];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_HttpRequest_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_HttpRequest_t qt_meta_stringdata_HttpRequest = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11), // "HttpRequest"
|
||||
QT_MOC_LITERAL(1, 12, 11), // "requestDone"
|
||||
QT_MOC_LITERAL(2, 24, 0), // ""
|
||||
QT_MOC_LITERAL(3, 25, 8), // "response"
|
||||
QT_MOC_LITERAL(4, 34, 7), // "success"
|
||||
QT_MOC_LITERAL(5, 42, 27), // "QNetworkReply::NetworkError"
|
||||
QT_MOC_LITERAL(6, 70, 5), // "error"
|
||||
QT_MOC_LITERAL(7, 76, 14), // "requestTimeout"
|
||||
QT_MOC_LITERAL(8, 91, 15) // "requestFinished"
|
||||
|
||||
},
|
||||
"HttpRequest\0requestDone\0\0response\0"
|
||||
"success\0QNetworkReply::NetworkError\0"
|
||||
"error\0requestTimeout\0requestFinished"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_HttpRequest[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 3, 29, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
7, 0, 36, 2, 0x08 /* Private */,
|
||||
8, 0, 37, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::QString, QMetaType::Bool, 0x80000000 | 5, 3, 4, 6,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void HttpRequest::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<HttpRequest *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->requestDone((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2])),(*reinterpret_cast< QNetworkReply::NetworkError(*)>(_a[3]))); break;
|
||||
case 1: _t->requestTimeout(); break;
|
||||
case 2: _t->requestFinished(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (HttpRequest::*)(const QString & , bool , QNetworkReply::NetworkError );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&HttpRequest::requestDone)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject HttpRequest::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_HttpRequest.data,
|
||||
qt_meta_data_HttpRequest,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *HttpRequest::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *HttpRequest::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_HttpRequest.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int HttpRequest::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 3)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 3;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 3)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 3;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void HttpRequest::requestDone(const QString & _t1, bool _t2, QNetworkReply::NetworkError _t3)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)), const_cast<void*>(reinterpret_cast<const void*>(&_t3)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,195 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'body.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "body.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'body.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_RecordButton_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[13];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_RecordButton_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_RecordButton_t qt_meta_stringdata_RecordButton = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12) // "RecordButton"
|
||||
|
||||
},
|
||||
"RecordButton"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_RecordButton[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void RecordButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject RecordButton::staticMetaObject = { {
|
||||
&QPushButton::staticMetaObject,
|
||||
qt_meta_stringdata_RecordButton.data,
|
||||
qt_meta_data_RecordButton,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *RecordButton::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *RecordButton::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_RecordButton.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QPushButton::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int RecordButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QPushButton::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
struct qt_meta_stringdata_BodyWindow_t {
|
||||
QByteArrayData data[7];
|
||||
char stringdata0[59];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_BodyWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_BodyWindow_t qt_meta_stringdata_BodyWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 10), // "BodyWindow"
|
||||
QT_MOC_LITERAL(1, 11, 11), // "updateState"
|
||||
QT_MOC_LITERAL(2, 23, 0), // ""
|
||||
QT_MOC_LITERAL(3, 24, 7), // "UIState"
|
||||
QT_MOC_LITERAL(4, 32, 1), // "s"
|
||||
QT_MOC_LITERAL(5, 34, 17), // "offroadTransition"
|
||||
QT_MOC_LITERAL(6, 52, 6) // "onroad"
|
||||
|
||||
},
|
||||
"BodyWindow\0updateState\0\0UIState\0s\0"
|
||||
"offroadTransition\0onroad"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_BodyWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
2, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
1, 1, 24, 2, 0x08 /* Private */,
|
||||
5, 1, 27, 2, 0x08 /* Private */,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, 0x80000000 | 3, 4,
|
||||
QMetaType::Void, QMetaType::Bool, 6,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void BodyWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<BodyWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->updateState((*reinterpret_cast< const UIState(*)>(_a[1]))); break;
|
||||
case 1: _t->offroadTransition((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject BodyWindow::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_BodyWindow.data,
|
||||
qt_meta_data_BodyWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *BodyWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *BodyWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_BodyWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int BodyWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 2)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 2;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 2)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 2;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,309 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'home.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "home.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'home.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_OffroadHome_t {
|
||||
QByteArrayData data[5];
|
||||
char stringdata0[38];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_OffroadHome_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_OffroadHome_t qt_meta_stringdata_OffroadHome = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11), // "OffroadHome"
|
||||
QT_MOC_LITERAL(1, 12, 12), // "openSettings"
|
||||
QT_MOC_LITERAL(2, 25, 0), // ""
|
||||
QT_MOC_LITERAL(3, 26, 5), // "index"
|
||||
QT_MOC_LITERAL(4, 32, 5) // "param"
|
||||
|
||||
},
|
||||
"OffroadHome\0openSettings\0\0index\0param"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_OffroadHome[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
3, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 29, 2, 0x06 /* Public */,
|
||||
1, 1, 34, 2, 0x26 /* Public | MethodCloned */,
|
||||
1, 0, 37, 2, 0x26 /* Public | MethodCloned */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Int, QMetaType::QString, 3, 4,
|
||||
QMetaType::Void, QMetaType::Int, 3,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void OffroadHome::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<OffroadHome *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->openSettings((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
|
||||
case 1: _t->openSettings((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 2: _t->openSettings(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (OffroadHome::*)(int , const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&OffroadHome::openSettings)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject OffroadHome::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_OffroadHome.data,
|
||||
qt_meta_data_OffroadHome,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *OffroadHome::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *OffroadHome::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_OffroadHome.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int OffroadHome::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 3)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 3;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 3)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 3;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void OffroadHome::openSettings(int _t1, const QString & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
struct qt_meta_stringdata_HomeWindow_t {
|
||||
QByteArrayData data[17];
|
||||
char stringdata0[159];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_HomeWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_HomeWindow_t qt_meta_stringdata_HomeWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 10), // "HomeWindow"
|
||||
QT_MOC_LITERAL(1, 11, 12), // "openSettings"
|
||||
QT_MOC_LITERAL(2, 24, 0), // ""
|
||||
QT_MOC_LITERAL(3, 25, 5), // "index"
|
||||
QT_MOC_LITERAL(4, 31, 5), // "param"
|
||||
QT_MOC_LITERAL(5, 37, 13), // "closeSettings"
|
||||
QT_MOC_LITERAL(6, 51, 17), // "offroadTransition"
|
||||
QT_MOC_LITERAL(7, 69, 7), // "offroad"
|
||||
QT_MOC_LITERAL(8, 77, 14), // "showDriverView"
|
||||
QT_MOC_LITERAL(9, 92, 4), // "show"
|
||||
QT_MOC_LITERAL(10, 97, 7), // "started"
|
||||
QT_MOC_LITERAL(11, 105, 11), // "showSidebar"
|
||||
QT_MOC_LITERAL(12, 117, 11), // "updateState"
|
||||
QT_MOC_LITERAL(13, 129, 7), // "UIState"
|
||||
QT_MOC_LITERAL(14, 137, 1), // "s"
|
||||
QT_MOC_LITERAL(15, 139, 16), // "StarPilotUIState"
|
||||
QT_MOC_LITERAL(16, 156, 2) // "fs"
|
||||
|
||||
},
|
||||
"HomeWindow\0openSettings\0\0index\0param\0"
|
||||
"closeSettings\0offroadTransition\0offroad\0"
|
||||
"showDriverView\0show\0started\0showSidebar\0"
|
||||
"updateState\0UIState\0s\0StarPilotUIState\0"
|
||||
"fs"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_HomeWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
9, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
4, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 59, 2, 0x06 /* Public */,
|
||||
1, 1, 64, 2, 0x26 /* Public | MethodCloned */,
|
||||
1, 0, 67, 2, 0x26 /* Public | MethodCloned */,
|
||||
5, 0, 68, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
6, 1, 69, 2, 0x0a /* Public */,
|
||||
8, 2, 72, 2, 0x0a /* Public */,
|
||||
8, 1, 77, 2, 0x2a /* Public | MethodCloned */,
|
||||
11, 1, 80, 2, 0x0a /* Public */,
|
||||
12, 2, 83, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Int, QMetaType::QString, 3, 4,
|
||||
QMetaType::Void, QMetaType::Int, 3,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Bool, 7,
|
||||
QMetaType::Void, QMetaType::Bool, QMetaType::Bool, 9, 10,
|
||||
QMetaType::Void, QMetaType::Bool, 9,
|
||||
QMetaType::Void, QMetaType::Bool, 9,
|
||||
QMetaType::Void, 0x80000000 | 13, 0x80000000 | 15, 14, 16,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void HomeWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<HomeWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->openSettings((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
|
||||
case 1: _t->openSettings((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 2: _t->openSettings(); break;
|
||||
case 3: _t->closeSettings(); break;
|
||||
case 4: _t->offroadTransition((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 5: _t->showDriverView((*reinterpret_cast< bool(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2]))); break;
|
||||
case 6: _t->showDriverView((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 7: _t->showSidebar((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 8: _t->updateState((*reinterpret_cast< const UIState(*)>(_a[1])),(*reinterpret_cast< const StarPilotUIState(*)>(_a[2]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (HomeWindow::*)(int , const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&HomeWindow::openSettings)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (HomeWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&HomeWindow::closeSettings)) {
|
||||
*result = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject HomeWindow::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_HomeWindow.data,
|
||||
qt_meta_data_HomeWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *HomeWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *HomeWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_HomeWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int HomeWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 9)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 9)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 9;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void HomeWindow::openSettings(int _t1, const QString & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 3
|
||||
void HomeWindow::closeSettings()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 3, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,136 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'prime_state.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "prime_state.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'prime_state.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_PrimeState_t {
|
||||
QByteArrayData data[5];
|
||||
char stringdata0[48];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_PrimeState_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_PrimeState_t qt_meta_stringdata_PrimeState = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 10), // "PrimeState"
|
||||
QT_MOC_LITERAL(1, 11, 7), // "changed"
|
||||
QT_MOC_LITERAL(2, 19, 0), // ""
|
||||
QT_MOC_LITERAL(3, 20, 16), // "PrimeState::Type"
|
||||
QT_MOC_LITERAL(4, 37, 10) // "prime_type"
|
||||
|
||||
},
|
||||
"PrimeState\0changed\0\0PrimeState::Type\0"
|
||||
"prime_type"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_PrimeState[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 1, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, 0x80000000 | 3, 4,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void PrimeState::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<PrimeState *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->changed((*reinterpret_cast< PrimeState::Type(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (PrimeState::*)(PrimeState::Type );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&PrimeState::changed)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject PrimeState::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_PrimeState.data,
|
||||
qt_meta_data_PrimeState,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *PrimeState::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *PrimeState::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_PrimeState.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int PrimeState::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void PrimeState::changed(PrimeState::Type _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,323 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'sidebar.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "sidebar.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'sidebar.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_Sidebar_t {
|
||||
QByteArrayData data[23];
|
||||
char stringdata0[236];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_Sidebar_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_Sidebar_t qt_meta_stringdata_Sidebar = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 7), // "Sidebar"
|
||||
QT_MOC_LITERAL(1, 8, 12), // "openSettings"
|
||||
QT_MOC_LITERAL(2, 21, 0), // ""
|
||||
QT_MOC_LITERAL(3, 22, 5), // "index"
|
||||
QT_MOC_LITERAL(4, 28, 5), // "param"
|
||||
QT_MOC_LITERAL(5, 34, 12), // "valueChanged"
|
||||
QT_MOC_LITERAL(6, 47, 17), // "offroadTransition"
|
||||
QT_MOC_LITERAL(7, 65, 7), // "offroad"
|
||||
QT_MOC_LITERAL(8, 73, 11), // "updateState"
|
||||
QT_MOC_LITERAL(9, 85, 7), // "UIState"
|
||||
QT_MOC_LITERAL(10, 93, 1), // "s"
|
||||
QT_MOC_LITERAL(11, 95, 16), // "StarPilotUIState"
|
||||
QT_MOC_LITERAL(12, 112, 2), // "fs"
|
||||
QT_MOC_LITERAL(13, 115, 13), // "connectStatus"
|
||||
QT_MOC_LITERAL(14, 129, 10), // "ItemStatus"
|
||||
QT_MOC_LITERAL(15, 140, 11), // "pandaStatus"
|
||||
QT_MOC_LITERAL(16, 152, 10), // "tempStatus"
|
||||
QT_MOC_LITERAL(17, 163, 7), // "netType"
|
||||
QT_MOC_LITERAL(18, 171, 11), // "netStrength"
|
||||
QT_MOC_LITERAL(19, 183, 14), // "recordingAudio"
|
||||
QT_MOC_LITERAL(20, 198, 10), // "chipStatus"
|
||||
QT_MOC_LITERAL(21, 209, 12), // "memoryStatus"
|
||||
QT_MOC_LITERAL(22, 222, 13) // "storageStatus"
|
||||
|
||||
},
|
||||
"Sidebar\0openSettings\0\0index\0param\0"
|
||||
"valueChanged\0offroadTransition\0offroad\0"
|
||||
"updateState\0UIState\0s\0StarPilotUIState\0"
|
||||
"fs\0connectStatus\0ItemStatus\0pandaStatus\0"
|
||||
"tempStatus\0netType\0netStrength\0"
|
||||
"recordingAudio\0chipStatus\0memoryStatus\0"
|
||||
"storageStatus"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_Sidebar[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
6, 14, // methods
|
||||
9, 62, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
4, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 44, 2, 0x06 /* Public */,
|
||||
1, 1, 49, 2, 0x26 /* Public | MethodCloned */,
|
||||
1, 0, 52, 2, 0x26 /* Public | MethodCloned */,
|
||||
5, 0, 53, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
6, 1, 54, 2, 0x0a /* Public */,
|
||||
8, 2, 57, 2, 0x0a /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Int, QMetaType::QString, 3, 4,
|
||||
QMetaType::Void, QMetaType::Int, 3,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Bool, 7,
|
||||
QMetaType::Void, 0x80000000 | 9, 0x80000000 | 11, 10, 12,
|
||||
|
||||
// properties: name, type, flags
|
||||
13, 0x80000000 | 14, 0x0049500b,
|
||||
15, 0x80000000 | 14, 0x0049500b,
|
||||
16, 0x80000000 | 14, 0x0049500b,
|
||||
17, QMetaType::QString, 0x00495003,
|
||||
18, QMetaType::Int, 0x00495003,
|
||||
19, QMetaType::Bool, 0x00495003,
|
||||
20, 0x80000000 | 14, 0x0049500b,
|
||||
21, 0x80000000 | 14, 0x0049500b,
|
||||
22, 0x80000000 | 14, 0x0049500b,
|
||||
|
||||
// properties: notify_signal_id
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void Sidebar::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<Sidebar *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->openSettings((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
|
||||
case 1: _t->openSettings((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 2: _t->openSettings(); break;
|
||||
case 3: _t->valueChanged(); break;
|
||||
case 4: _t->offroadTransition((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 5: _t->updateState((*reinterpret_cast< const UIState(*)>(_a[1])),(*reinterpret_cast< const StarPilotUIState(*)>(_a[2]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (Sidebar::*)(int , const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&Sidebar::openSettings)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (Sidebar::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&Sidebar::valueChanged)) {
|
||||
*result = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (_c == QMetaObject::RegisterPropertyMetaType) {
|
||||
switch (_id) {
|
||||
default: *reinterpret_cast<int*>(_a[0]) = -1; break;
|
||||
case 8:
|
||||
case 7:
|
||||
case 6:
|
||||
case 2:
|
||||
case 1:
|
||||
case 0:
|
||||
*reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< ItemStatus >(); break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_PROPERTIES
|
||||
else if (_c == QMetaObject::ReadProperty) {
|
||||
auto *_t = static_cast<Sidebar *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
void *_v = _a[0];
|
||||
switch (_id) {
|
||||
case 0: *reinterpret_cast< ItemStatus*>(_v) = _t->connect_status; break;
|
||||
case 1: *reinterpret_cast< ItemStatus*>(_v) = _t->panda_status; break;
|
||||
case 2: *reinterpret_cast< ItemStatus*>(_v) = _t->temp_status; break;
|
||||
case 3: *reinterpret_cast< QString*>(_v) = _t->net_type; break;
|
||||
case 4: *reinterpret_cast< int*>(_v) = _t->net_strength; break;
|
||||
case 5: *reinterpret_cast< bool*>(_v) = _t->recording_audio; break;
|
||||
case 6: *reinterpret_cast< ItemStatus*>(_v) = _t->chip_status; break;
|
||||
case 7: *reinterpret_cast< ItemStatus*>(_v) = _t->memory_status; break;
|
||||
case 8: *reinterpret_cast< ItemStatus*>(_v) = _t->storage_status; break;
|
||||
default: break;
|
||||
}
|
||||
} else if (_c == QMetaObject::WriteProperty) {
|
||||
auto *_t = static_cast<Sidebar *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
void *_v = _a[0];
|
||||
switch (_id) {
|
||||
case 0:
|
||||
if (_t->connect_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->connect_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (_t->panda_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->panda_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (_t->temp_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->temp_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (_t->net_type != *reinterpret_cast< QString*>(_v)) {
|
||||
_t->net_type = *reinterpret_cast< QString*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (_t->net_strength != *reinterpret_cast< int*>(_v)) {
|
||||
_t->net_strength = *reinterpret_cast< int*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (_t->recording_audio != *reinterpret_cast< bool*>(_v)) {
|
||||
_t->recording_audio = *reinterpret_cast< bool*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (_t->chip_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->chip_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (_t->memory_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->memory_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (_t->storage_status != *reinterpret_cast< ItemStatus*>(_v)) {
|
||||
_t->storage_status = *reinterpret_cast< ItemStatus*>(_v);
|
||||
Q_EMIT _t->valueChanged();
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
} else if (_c == QMetaObject::ResetProperty) {
|
||||
}
|
||||
#endif // QT_NO_PROPERTIES
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject Sidebar::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_Sidebar.data,
|
||||
qt_meta_data_Sidebar,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *Sidebar::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *Sidebar::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_Sidebar.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int Sidebar::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 6)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 6;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 6)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 6;
|
||||
}
|
||||
#ifndef QT_NO_PROPERTIES
|
||||
else if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty
|
||||
|| _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::QueryPropertyDesignable) {
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::QueryPropertyScriptable) {
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::QueryPropertyStored) {
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::QueryPropertyEditable) {
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::QueryPropertyUser) {
|
||||
_id -= 9;
|
||||
}
|
||||
#endif // QT_NO_PROPERTIES
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void Sidebar::openSettings(int _t1, const QString & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 3
|
||||
void Sidebar::valueChanged()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 3, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,136 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'util.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "util.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'util.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_ParamWatcher_t {
|
||||
QByteArrayData data[5];
|
||||
char stringdata0[50];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_ParamWatcher_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_ParamWatcher_t qt_meta_stringdata_ParamWatcher = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12), // "ParamWatcher"
|
||||
QT_MOC_LITERAL(1, 13, 12), // "paramChanged"
|
||||
QT_MOC_LITERAL(2, 26, 0), // ""
|
||||
QT_MOC_LITERAL(3, 27, 10), // "param_name"
|
||||
QT_MOC_LITERAL(4, 38, 11) // "param_value"
|
||||
|
||||
},
|
||||
"ParamWatcher\0paramChanged\0\0param_name\0"
|
||||
"param_value"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_ParamWatcher[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::QString, QMetaType::QString, 3, 4,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void ParamWatcher::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<ParamWatcher *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->paramChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (ParamWatcher::*)(const QString & , const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ParamWatcher::paramChanged)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject ParamWatcher::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_ParamWatcher.data,
|
||||
qt_meta_data_ParamWatcher,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *ParamWatcher::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *ParamWatcher::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_ParamWatcher.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int ParamWatcher::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void ParamWatcher::paramChanged(const QString & _t1, const QString & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'window.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "window.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'window.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_MainWindow_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[11];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_MainWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 10) // "MainWindow"
|
||||
|
||||
},
|
||||
"MainWindow"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_MainWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject MainWindow::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_MainWindow.data,
|
||||
qt_meta_data_MainWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *MainWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *MainWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_MainWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,519 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'networking.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "networking.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'networking.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_WifiItem_t {
|
||||
QByteArrayData data[6];
|
||||
char stringdata0[51];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_WifiItem_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_WifiItem_t qt_meta_stringdata_WifiItem = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 8), // "WifiItem"
|
||||
QT_MOC_LITERAL(1, 9, 16), // "connectToNetwork"
|
||||
QT_MOC_LITERAL(2, 26, 0), // ""
|
||||
QT_MOC_LITERAL(3, 27, 7), // "Network"
|
||||
QT_MOC_LITERAL(4, 35, 1), // "n"
|
||||
QT_MOC_LITERAL(5, 37, 13) // "forgotNetwork"
|
||||
|
||||
},
|
||||
"WifiItem\0connectToNetwork\0\0Network\0n\0"
|
||||
"forgotNetwork"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_WifiItem[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
2, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 1, 24, 2, 0x06 /* Public */,
|
||||
5, 1, 27, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, 0x80000000 | 3, 4,
|
||||
QMetaType::Void, 0x80000000 | 3, 4,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void WifiItem::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<WifiItem *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->connectToNetwork((*reinterpret_cast< const Network(*)>(_a[1]))); break;
|
||||
case 1: _t->forgotNetwork((*reinterpret_cast< const Network(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (WifiItem::*)(const Network );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&WifiItem::connectToNetwork)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (WifiItem::*)(const Network );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&WifiItem::forgotNetwork)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject WifiItem::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_WifiItem.data,
|
||||
qt_meta_data_WifiItem,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *WifiItem::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *WifiItem::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_WifiItem.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int WifiItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 2)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 2;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 2)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 2;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void WifiItem::connectToNetwork(const Network _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void WifiItem::forgotNetwork(const Network _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, _a);
|
||||
}
|
||||
struct qt_meta_stringdata_WifiUI_t {
|
||||
QByteArrayData data[6];
|
||||
char stringdata0[43];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_WifiUI_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_WifiUI_t qt_meta_stringdata_WifiUI = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 6), // "WifiUI"
|
||||
QT_MOC_LITERAL(1, 7, 16), // "connectToNetwork"
|
||||
QT_MOC_LITERAL(2, 24, 0), // ""
|
||||
QT_MOC_LITERAL(3, 25, 7), // "Network"
|
||||
QT_MOC_LITERAL(4, 33, 1), // "n"
|
||||
QT_MOC_LITERAL(5, 35, 7) // "refresh"
|
||||
|
||||
},
|
||||
"WifiUI\0connectToNetwork\0\0Network\0n\0"
|
||||
"refresh"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_WifiUI[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
2, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 1, 24, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
5, 0, 27, 2, 0x0a /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, 0x80000000 | 3, 4,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void WifiUI::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<WifiUI *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->connectToNetwork((*reinterpret_cast< const Network(*)>(_a[1]))); break;
|
||||
case 1: _t->refresh(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (WifiUI::*)(const Network );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&WifiUI::connectToNetwork)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject WifiUI::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_WifiUI.data,
|
||||
qt_meta_data_WifiUI,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *WifiUI::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *WifiUI::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_WifiUI.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int WifiUI::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 2)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 2;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 2)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 2;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void WifiUI::connectToNetwork(const Network _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
struct qt_meta_stringdata_AdvancedNetworking_t {
|
||||
QByteArrayData data[7];
|
||||
char stringdata0[75];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_AdvancedNetworking_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_AdvancedNetworking_t qt_meta_stringdata_AdvancedNetworking = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 18), // "AdvancedNetworking"
|
||||
QT_MOC_LITERAL(1, 19, 9), // "backPress"
|
||||
QT_MOC_LITERAL(2, 29, 0), // ""
|
||||
QT_MOC_LITERAL(3, 30, 17), // "requestWifiScreen"
|
||||
QT_MOC_LITERAL(4, 48, 15), // "toggleTethering"
|
||||
QT_MOC_LITERAL(5, 64, 2), // "id"
|
||||
QT_MOC_LITERAL(6, 67, 7) // "refresh"
|
||||
|
||||
},
|
||||
"AdvancedNetworking\0backPress\0\0"
|
||||
"requestWifiScreen\0toggleTethering\0id\0"
|
||||
"refresh"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_AdvancedNetworking[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
4, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 34, 2, 0x06 /* Public */,
|
||||
3, 0, 35, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
4, 1, 36, 2, 0x0a /* Public */,
|
||||
6, 0, 39, 2, 0x0a /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Int, 5,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void AdvancedNetworking::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<AdvancedNetworking *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->backPress(); break;
|
||||
case 1: _t->requestWifiScreen(); break;
|
||||
case 2: _t->toggleTethering((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 3: _t->refresh(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (AdvancedNetworking::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&AdvancedNetworking::backPress)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (AdvancedNetworking::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&AdvancedNetworking::requestWifiScreen)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject AdvancedNetworking::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_AdvancedNetworking.data,
|
||||
qt_meta_data_AdvancedNetworking,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *AdvancedNetworking::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *AdvancedNetworking::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_AdvancedNetworking.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int AdvancedNetworking::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 4)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 4;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 4)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 4;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void AdvancedNetworking::backPress()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void AdvancedNetworking::requestWifiScreen()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_Networking_t {
|
||||
QByteArrayData data[8];
|
||||
char stringdata0[66];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_Networking_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_Networking_t qt_meta_stringdata_Networking = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 10), // "Networking"
|
||||
QT_MOC_LITERAL(1, 11, 7), // "refresh"
|
||||
QT_MOC_LITERAL(2, 19, 0), // ""
|
||||
QT_MOC_LITERAL(3, 20, 16), // "connectToNetwork"
|
||||
QT_MOC_LITERAL(4, 37, 7), // "Network"
|
||||
QT_MOC_LITERAL(5, 45, 1), // "n"
|
||||
QT_MOC_LITERAL(6, 47, 13), // "wrongPassword"
|
||||
QT_MOC_LITERAL(7, 61, 4) // "ssid"
|
||||
|
||||
},
|
||||
"Networking\0refresh\0\0connectToNetwork\0"
|
||||
"Network\0n\0wrongPassword\0ssid"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_Networking[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
1, 0, 29, 2, 0x0a /* Public */,
|
||||
3, 1, 30, 2, 0x08 /* Private */,
|
||||
6, 1, 33, 2, 0x08 /* Private */,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void, 0x80000000 | 4, 5,
|
||||
QMetaType::Void, QMetaType::QString, 7,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void Networking::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<Networking *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->refresh(); break;
|
||||
case 1: _t->connectToNetwork((*reinterpret_cast< const Network(*)>(_a[1]))); break;
|
||||
case 2: _t->wrongPassword((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject Networking::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_Networking.data,
|
||||
qt_meta_data_Networking,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *Networking::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *Networking::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_Networking.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int Networking::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 3)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 3;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 3)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 3;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,201 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'wifi_manager.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "wifi_manager.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'wifi_manager.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_WifiManager_t {
|
||||
QByteArrayData data[22];
|
||||
char stringdata0[276];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_WifiManager_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_WifiManager_t qt_meta_stringdata_WifiManager = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11), // "WifiManager"
|
||||
QT_MOC_LITERAL(1, 12, 13), // "wrongPassword"
|
||||
QT_MOC_LITERAL(2, 26, 0), // ""
|
||||
QT_MOC_LITERAL(3, 27, 4), // "ssid"
|
||||
QT_MOC_LITERAL(4, 32, 13), // "refreshSignal"
|
||||
QT_MOC_LITERAL(5, 46, 11), // "stateChange"
|
||||
QT_MOC_LITERAL(6, 58, 9), // "new_state"
|
||||
QT_MOC_LITERAL(7, 68, 14), // "previous_state"
|
||||
QT_MOC_LITERAL(8, 83, 13), // "change_reason"
|
||||
QT_MOC_LITERAL(9, 97, 14), // "propertyChange"
|
||||
QT_MOC_LITERAL(10, 112, 9), // "interface"
|
||||
QT_MOC_LITERAL(11, 122, 5), // "props"
|
||||
QT_MOC_LITERAL(12, 128, 17), // "invalidated_props"
|
||||
QT_MOC_LITERAL(13, 146, 11), // "deviceAdded"
|
||||
QT_MOC_LITERAL(14, 158, 15), // "QDBusObjectPath"
|
||||
QT_MOC_LITERAL(15, 174, 4), // "path"
|
||||
QT_MOC_LITERAL(16, 179, 17), // "connectionRemoved"
|
||||
QT_MOC_LITERAL(17, 197, 13), // "newConnection"
|
||||
QT_MOC_LITERAL(18, 211, 15), // "refreshFinished"
|
||||
QT_MOC_LITERAL(19, 227, 24), // "QDBusPendingCallWatcher*"
|
||||
QT_MOC_LITERAL(20, 252, 4), // "call"
|
||||
QT_MOC_LITERAL(21, 257, 18) // "tetheringActivated"
|
||||
|
||||
},
|
||||
"WifiManager\0wrongPassword\0\0ssid\0"
|
||||
"refreshSignal\0stateChange\0new_state\0"
|
||||
"previous_state\0change_reason\0"
|
||||
"propertyChange\0interface\0props\0"
|
||||
"invalidated_props\0deviceAdded\0"
|
||||
"QDBusObjectPath\0path\0connectionRemoved\0"
|
||||
"newConnection\0refreshFinished\0"
|
||||
"QDBusPendingCallWatcher*\0call\0"
|
||||
"tetheringActivated"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_WifiManager[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
9, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 1, 59, 2, 0x06 /* Public */,
|
||||
4, 0, 62, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
5, 3, 63, 2, 0x08 /* Private */,
|
||||
9, 3, 70, 2, 0x08 /* Private */,
|
||||
13, 1, 77, 2, 0x08 /* Private */,
|
||||
16, 1, 80, 2, 0x08 /* Private */,
|
||||
17, 1, 83, 2, 0x08 /* Private */,
|
||||
18, 1, 86, 2, 0x08 /* Private */,
|
||||
21, 1, 89, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::QString, 3,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::UInt, QMetaType::UInt, QMetaType::UInt, 6, 7, 8,
|
||||
QMetaType::Void, QMetaType::QString, QMetaType::QVariantMap, QMetaType::QStringList, 10, 11, 12,
|
||||
QMetaType::Void, 0x80000000 | 14, 15,
|
||||
QMetaType::Void, 0x80000000 | 14, 15,
|
||||
QMetaType::Void, 0x80000000 | 14, 15,
|
||||
QMetaType::Void, 0x80000000 | 19, 20,
|
||||
QMetaType::Void, 0x80000000 | 19, 20,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void WifiManager::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<WifiManager *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->wrongPassword((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
case 1: _t->refreshSignal(); break;
|
||||
case 2: _t->stateChange((*reinterpret_cast< uint(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2])),(*reinterpret_cast< uint(*)>(_a[3]))); break;
|
||||
case 3: _t->propertyChange((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QVariantMap(*)>(_a[2])),(*reinterpret_cast< const QStringList(*)>(_a[3]))); break;
|
||||
case 4: _t->deviceAdded((*reinterpret_cast< const QDBusObjectPath(*)>(_a[1]))); break;
|
||||
case 5: _t->connectionRemoved((*reinterpret_cast< const QDBusObjectPath(*)>(_a[1]))); break;
|
||||
case 6: _t->newConnection((*reinterpret_cast< const QDBusObjectPath(*)>(_a[1]))); break;
|
||||
case 7: _t->refreshFinished((*reinterpret_cast< QDBusPendingCallWatcher*(*)>(_a[1]))); break;
|
||||
case 8: _t->tetheringActivated((*reinterpret_cast< QDBusPendingCallWatcher*(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (WifiManager::*)(const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&WifiManager::wrongPassword)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (WifiManager::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&WifiManager::refreshSignal)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject WifiManager::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_WifiManager.data,
|
||||
qt_meta_data_WifiManager,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *WifiManager::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *WifiManager::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_WifiManager.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int WifiManager::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 9)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 9;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 9)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 9;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void WifiManager::wrongPassword(const QString & _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void WifiManager::refreshSignal()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,420 +0,0 @@
|
||||
#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
|
||||
std::vector<QString> tetheringSelection{tr("Off"), tr("Always"), tr("Only Onroad"), tr("Until Reboot")};
|
||||
tetheringToggle = new ButtonParamControl("TetheringEnabled", tr("Enable Tethering"),
|
||||
tr("Share your device's internet connection with other devices, either all the time or only while driving."),
|
||||
"", tetheringSelection);
|
||||
if (params.getInt("TetheringEnabled") == 3) {
|
||||
params.remove("TetheringEnabled");
|
||||
tetheringToggle->setCheckedButton(0);
|
||||
}
|
||||
list->addItem(tetheringToggle);
|
||||
QObject::connect(tetheringToggle, &MultiButtonControl::buttonClicked, 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// Cellular metered toggle (prime lite or none)
|
||||
const bool metered = params.getBool("GsmMetered");
|
||||
cellularMeteredToggle = new ToggleControl(tr("Cellular Metered"), tr("Prevent large data uploads when on a metered cellular connection"), "", metered);
|
||||
QObject::connect(cellularMeteredToggle, &SshToggle::toggleFlipped, [=](bool state) {
|
||||
params.putBool("GsmMetered", state);
|
||||
wifi->updateGsmSettings(params.getBool("GsmRoaming"), QString::fromStdString(params.get("GsmApn")), state);
|
||||
});
|
||||
list->addItem(cellularMeteredToggle);
|
||||
|
||||
// Wi-Fi metered toggle
|
||||
std::vector<QString> metered_button_texts{tr("default"), tr("metered"), tr("unmetered")};
|
||||
wifiMeteredToggle = new MultiButtonControl(tr("Wi-Fi Network Metered"), tr("Prevent large data uploads when on a metered Wi-Fi connection"), "", metered_button_texts);
|
||||
QObject::connect(wifiMeteredToggle, &MultiButtonControl::buttonClicked, [=](int id) {
|
||||
wifiMeteredToggle->setEnabled(false);
|
||||
MeteredType metered = MeteredType::UNKNOWN;
|
||||
if (id == NM_METERED_YES) {
|
||||
metered = MeteredType::YES;
|
||||
} else if (id == NM_METERED_NO) {
|
||||
metered = MeteredType::NO;
|
||||
}
|
||||
auto pending_call = wifi->setCurrentNetworkMetered(metered);
|
||||
if (pending_call) {
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(*pending_call);
|
||||
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() {
|
||||
refresh();
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
});
|
||||
list->addItem(wifiMeteredToggle);
|
||||
|
||||
// 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);
|
||||
cellularMeteredToggle->setVisible(visible);
|
||||
}
|
||||
|
||||
void AdvancedNetworking::refresh() {
|
||||
ipLabel->setText(wifi->ipv4_address);
|
||||
tetheringToggle->setEnabled(true);
|
||||
|
||||
if (wifi->isTetheringEnabled() || wifi->ipv4_address == "") {
|
||||
wifiMeteredToggle->setEnabled(false);
|
||||
wifiMeteredToggle->setCheckedButton(0);
|
||||
} else if (wifi->ipv4_address != "") {
|
||||
MeteredType metered = wifi->currentNetworkMetered();
|
||||
wifiMeteredToggle->setEnabled(true);
|
||||
wifiMeteredToggle->setCheckedButton(static_cast<int>(metered));
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void AdvancedNetworking::toggleTethering(int id) {
|
||||
wifi->setTetheringEnabled(id == 1 || id == 2 && uiState()->scene.started || id == 3);
|
||||
tetheringToggle->setEnabled(false);
|
||||
if (id != 0) {
|
||||
wifiMeteredToggle->setEnabled(false);
|
||||
wifiMeteredToggle->setCheckedButton(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 + "/icons/wifi_strength_" + s + ".svg");
|
||||
strengths.push_back(pix.scaledToHeight(68, Qt::SmoothTransformation));
|
||||
}
|
||||
lock = QPixmap(ASSET_PATH + "icons/lock_closed.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation);
|
||||
checkmark = QPixmap(ASSET_PATH + "icons/checkmark.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation);
|
||||
circled_slash = QPixmap(ASSET_PATH + "icons/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);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "selfdrive/ui/qt/network/wifi_manager.h"
|
||||
#include "selfdrive/ui/qt/prime_state.h"
|
||||
#include "selfdrive/ui/qt/widgets/input.h"
|
||||
#include "selfdrive/ui/qt/widgets/ssh_keys.h"
|
||||
#include "selfdrive/ui/qt/widgets/toggle.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class WifiItem : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WifiItem(const QString &connecting_text, const QString &forget_text, QWidget* parent = nullptr);
|
||||
void setItem(const Network& n, const QPixmap &icon, bool show_forget_btn, const QPixmap &strength);
|
||||
|
||||
signals:
|
||||
// Cannot pass Network by reference. it may change after the signal is sent.
|
||||
void connectToNetwork(const Network n);
|
||||
void forgotNetwork(const Network n);
|
||||
|
||||
protected:
|
||||
ElidedLabel* ssidLabel;
|
||||
QPushButton* connecting;
|
||||
QPushButton* forgetBtn;
|
||||
QLabel* iconLabel;
|
||||
QLabel* strengthLabel;
|
||||
Network network;
|
||||
};
|
||||
|
||||
class WifiUI : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WifiUI(QWidget *parent = 0, WifiManager* wifi = 0);
|
||||
|
||||
private:
|
||||
WifiItem *getItem(int n);
|
||||
|
||||
WifiManager *wifi = nullptr;
|
||||
QLabel *scanningLabel = nullptr;
|
||||
QPixmap lock;
|
||||
QPixmap checkmark;
|
||||
QPixmap circled_slash;
|
||||
QVector<QPixmap> strengths;
|
||||
ListWidget *wifi_list_widget = nullptr;
|
||||
std::vector<WifiItem*> wifi_items;
|
||||
|
||||
signals:
|
||||
void connectToNetwork(const Network n);
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
class AdvancedNetworking : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdvancedNetworking(QWidget* parent = 0, WifiManager* wifi = 0);
|
||||
void setGsmVisible(bool visible);
|
||||
|
||||
private:
|
||||
LabelControl* ipLabel;
|
||||
ButtonParamControl* tetheringToggle;
|
||||
ToggleControl* roamingToggle;
|
||||
ButtonControl* editApnButton;
|
||||
ButtonControl* hiddenNetworkButton;
|
||||
ToggleControl* cellularMeteredToggle;
|
||||
MultiButtonControl* wifiMeteredToggle;
|
||||
WifiManager* wifi = nullptr;
|
||||
Params params;
|
||||
|
||||
signals:
|
||||
void backPress();
|
||||
void requestWifiScreen();
|
||||
|
||||
public slots:
|
||||
void toggleTethering(int id);
|
||||
void refresh();
|
||||
};
|
||||
|
||||
class Networking : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Networking(QWidget* parent = 0, bool show_advanced = true);
|
||||
void setPrimeType(PrimeState::Type type);
|
||||
WifiManager* wifi = nullptr;
|
||||
|
||||
private:
|
||||
QStackedLayout* main_layout = nullptr;
|
||||
QWidget* wifiScreen = nullptr;
|
||||
AdvancedNetworking* an = nullptr;
|
||||
WifiUI* wifiWidget;
|
||||
|
||||
void showEvent(QShowEvent* event) override;
|
||||
void hideEvent(QHideEvent* event) override;
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
|
||||
private slots:
|
||||
void connectToNetwork(const Network n);
|
||||
void wrongPassword(const QString &ssid);
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* We are using a NetworkManager DBUS API : https://developer.gnome.org/NetworkManager/1.26/spec.html
|
||||
* */
|
||||
|
||||
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags
|
||||
const int NM_802_11_AP_FLAGS_NONE = 0x00000000;
|
||||
const int NM_802_11_AP_FLAGS_PRIVACY = 0x00000001;
|
||||
const int NM_802_11_AP_FLAGS_WPS = 0x00000002;
|
||||
|
||||
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags
|
||||
const int NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001;
|
||||
const int NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002;
|
||||
const int NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010;
|
||||
const int NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020;
|
||||
const int NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100;
|
||||
const int NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200;
|
||||
|
||||
const QString NM_DBUS_PATH = "/org/freedesktop/NetworkManager";
|
||||
const QString NM_DBUS_PATH_SETTINGS = "/org/freedesktop/NetworkManager/Settings";
|
||||
|
||||
const QString NM_DBUS_INTERFACE = "org.freedesktop.NetworkManager";
|
||||
const QString NM_DBUS_INTERFACE_PROPERTIES = "org.freedesktop.DBus.Properties";
|
||||
const QString NM_DBUS_INTERFACE_SETTINGS = "org.freedesktop.NetworkManager.Settings";
|
||||
const QString NM_DBUS_INTERFACE_SETTINGS_CONNECTION = "org.freedesktop.NetworkManager.Settings.Connection";
|
||||
const QString NM_DBUS_INTERFACE_DEVICE = "org.freedesktop.NetworkManager.Device";
|
||||
const QString NM_DBUS_INTERFACE_DEVICE_WIRELESS = "org.freedesktop.NetworkManager.Device.Wireless";
|
||||
const QString NM_DBUS_INTERFACE_ACCESS_POINT = "org.freedesktop.NetworkManager.AccessPoint";
|
||||
const QString NM_DBUS_INTERFACE_ACTIVE_CONNECTION = "org.freedesktop.NetworkManager.Connection.Active";
|
||||
const QString NM_DBUS_INTERFACE_IP4_CONFIG = "org.freedesktop.NetworkManager.IP4Config";
|
||||
|
||||
const QString NM_DBUS_SERVICE = "org.freedesktop.NetworkManager";
|
||||
|
||||
const int NM_DEVICE_STATE_UNKNOWN = 0;
|
||||
const int NM_DEVICE_STATE_ACTIVATED = 100;
|
||||
const int NM_DEVICE_STATE_NEED_AUTH = 60;
|
||||
const int NM_DEVICE_TYPE_WIFI = 2;
|
||||
const int NM_DEVICE_TYPE_MODEM = 8;
|
||||
const int NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8;
|
||||
const int DBUS_TIMEOUT = 100;
|
||||
|
||||
// https://developer-old.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMMetered
|
||||
const int NM_METERED_UNKNOWN = 0;
|
||||
const int NM_METERED_YES = 1;
|
||||
const int NM_METERED_NO = 2;
|
||||
const int NM_METERED_GUESS_YES = 3;
|
||||
const int NM_METERED_GUESS_NO = 4;
|
||||
@@ -1,539 +0,0 @@
|
||||
#include "selfdrive/ui/qt/network/wifi_manager.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "common/swaglog.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
bool compare_by_strength(const Network &a, const Network &b) {
|
||||
return std::tuple(a.connected, strengthLevel(a.strength), b.ssid) >
|
||||
std::tuple(b.connected, strengthLevel(b.strength), a.ssid);
|
||||
}
|
||||
|
||||
template <typename T = QDBusMessage, typename... Args>
|
||||
T call(const QString &path, const QString &interface, const QString &method, Args &&...args) {
|
||||
QDBusInterface nm(NM_DBUS_SERVICE, path, interface, QDBusConnection::systemBus());
|
||||
nm.setTimeout(DBUS_TIMEOUT);
|
||||
|
||||
QDBusMessage response = nm.call(method, std::forward<Args>(args)...);
|
||||
if (response.type() == QDBusMessage::ErrorMessage) {
|
||||
qCritical() << "DBus call error:" << response.errorMessage();
|
||||
return T();
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<T, QDBusMessage>) {
|
||||
return response;
|
||||
} else if (response.arguments().count() >= 1) {
|
||||
QVariant vFirst = response.arguments().at(0).value<QDBusVariant>().variant();
|
||||
if (vFirst.canConvert<T>()) {
|
||||
return vFirst.value<T>();
|
||||
}
|
||||
QDebug critical = qCritical();
|
||||
critical << "Variant unpacking failure :" << method << ',';
|
||||
(critical << ... << args);
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
QDBusPendingCall asyncCall(const QString &path, const QString &interface, const QString &method, Args &&...args) {
|
||||
QDBusInterface nm = QDBusInterface(NM_DBUS_SERVICE, path, interface, QDBusConnection::systemBus());
|
||||
return nm.asyncCall(method, args...);
|
||||
}
|
||||
|
||||
bool emptyPath(const QString &path) {
|
||||
return path == "" || path == "/";
|
||||
}
|
||||
|
||||
WifiManager::WifiManager(QObject *parent) : QObject(parent) {
|
||||
qDBusRegisterMetaType<Connection>();
|
||||
qDBusRegisterMetaType<IpConfig>();
|
||||
|
||||
// Set tethering ssid as "weedle" + first 4 characters of a dongle id
|
||||
tethering_ssid = "weedle";
|
||||
if (auto dongle_id = getDongleId()) {
|
||||
tethering_ssid += "-" + dongle_id->left(4);
|
||||
}
|
||||
|
||||
adapter = getAdapter();
|
||||
if (!adapter.isEmpty()) {
|
||||
setup();
|
||||
} else {
|
||||
QDBusConnection::systemBus().connect(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceAdded", this, SLOT(deviceAdded(QDBusObjectPath)));
|
||||
}
|
||||
|
||||
timer.callOnTimeout(this, &WifiManager::requestScan);
|
||||
|
||||
initConnections();
|
||||
}
|
||||
|
||||
void WifiManager::setup() {
|
||||
auto bus = QDBusConnection::systemBus();
|
||||
bus.connect(NM_DBUS_SERVICE, adapter, NM_DBUS_INTERFACE_DEVICE, "StateChanged", this, SLOT(stateChange(unsigned int, unsigned int, unsigned int)));
|
||||
bus.connect(NM_DBUS_SERVICE, adapter, NM_DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", this, SLOT(propertyChange(QString, QVariantMap, QStringList)));
|
||||
|
||||
bus.connect(NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "ConnectionRemoved", this, SLOT(connectionRemoved(QDBusObjectPath)));
|
||||
bus.connect(NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "NewConnection", this, SLOT(newConnection(QDBusObjectPath)));
|
||||
|
||||
raw_adapter_state = call<uint>(adapter, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE, "State");
|
||||
activeAp = call<QDBusObjectPath>(adapter, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE_WIRELESS, "ActiveAccessPoint").path();
|
||||
|
||||
requestScan();
|
||||
}
|
||||
|
||||
void WifiManager::start() {
|
||||
timer.start(5000);
|
||||
refreshNetworks();
|
||||
}
|
||||
|
||||
void WifiManager::stop() {
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
void WifiManager::refreshNetworks() {
|
||||
if (adapter.isEmpty() || !timer.isActive()) return;
|
||||
|
||||
QDBusPendingCall pending_call = asyncCall(adapter, NM_DBUS_INTERFACE_DEVICE_WIRELESS, "GetAllAccessPoints");
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending_call);
|
||||
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &WifiManager::refreshFinished);
|
||||
}
|
||||
|
||||
void WifiManager::refreshFinished(QDBusPendingCallWatcher *watcher) {
|
||||
ipv4_address = getIp4Address();
|
||||
seenNetworks.clear();
|
||||
|
||||
const QDBusReply<QList<QDBusObjectPath>> watcher_reply = *watcher;
|
||||
if (!watcher_reply.isValid()) {
|
||||
qCritical() << "Failed to refresh";
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const QDBusObjectPath &path : watcher_reply.value()) {
|
||||
QDBusReply<QVariantMap> reply = call(path.path(), NM_DBUS_INTERFACE_PROPERTIES, "GetAll", NM_DBUS_INTERFACE_ACCESS_POINT);
|
||||
if (!reply.isValid()) {
|
||||
qCritical() << "Failed to retrieve properties for path:" << path.path();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto properties = reply.value();
|
||||
const QByteArray ssid = properties["Ssid"].toByteArray();
|
||||
if (ssid.isEmpty()) continue;
|
||||
|
||||
// May be multiple access points for each SSID.
|
||||
// Use first for ssid and security type, then update connected status and strength using all
|
||||
if (!seenNetworks.contains(ssid)) {
|
||||
seenNetworks[ssid] = {ssid, 0U, ConnectedType::DISCONNECTED, getSecurityType(properties)};
|
||||
}
|
||||
|
||||
if (path.path() == activeAp) {
|
||||
seenNetworks[ssid].connected = (ssid == connecting_to_network) ? ConnectedType::CONNECTING : ConnectedType::CONNECTED;
|
||||
}
|
||||
|
||||
uint32_t strength = properties["Strength"].toUInt();
|
||||
if (seenNetworks[ssid].strength < strength) {
|
||||
seenNetworks[ssid].strength = strength;
|
||||
}
|
||||
}
|
||||
|
||||
emit refreshSignal();
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
QString WifiManager::getIp4Address() {
|
||||
if (raw_adapter_state != NM_DEVICE_STATE_ACTIVATED) return "";
|
||||
|
||||
for (const auto &p : getActiveConnections()) {
|
||||
QString type = call<QString>(p.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type");
|
||||
if (type == "802-11-wireless") {
|
||||
auto ip4config = call<QDBusObjectPath>(p.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Ip4Config");
|
||||
const auto &arr = call<QDBusArgument>(ip4config.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_IP4_CONFIG, "AddressData");
|
||||
QVariantMap path;
|
||||
arr.beginArray();
|
||||
while (!arr.atEnd()) {
|
||||
arr >> path;
|
||||
arr.endArray();
|
||||
return path.value("address").value<QString>();
|
||||
}
|
||||
arr.endArray();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
SecurityType WifiManager::getSecurityType(const QVariantMap &properties) {
|
||||
int sflag = properties["Flags"].toUInt();
|
||||
int wpaflag = properties["WpaFlags"].toUInt();
|
||||
int rsnflag = properties["RsnFlags"].toUInt();
|
||||
int wpa_props = wpaflag | rsnflag;
|
||||
|
||||
// obtained by looking at flags of networks in the office as reported by an Android phone
|
||||
const int supports_wpa = NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK;
|
||||
|
||||
if ((sflag == NM_802_11_AP_FLAGS_NONE) || ((sflag & NM_802_11_AP_FLAGS_WPS) && !(wpa_props & supports_wpa))) {
|
||||
return SecurityType::OPEN;
|
||||
} else if ((sflag & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_props & supports_wpa) && !(wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
|
||||
return SecurityType::WPA;
|
||||
} else {
|
||||
LOGW("Unsupported network! sflag: %d, wpaflag: %d, rsnflag: %d", sflag, wpaflag, rsnflag);
|
||||
return SecurityType::UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::connect(const Network &n, const bool is_hidden, const QString &password, const QString &username) {
|
||||
setCurrentConnecting(n.ssid);
|
||||
forgetConnection(n.ssid); // Clear all connections that may already exist to the network we are connecting
|
||||
Connection connection;
|
||||
connection["connection"]["type"] = "802-11-wireless";
|
||||
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
|
||||
connection["connection"]["id"] = "openpilot connection " + QString::fromStdString(n.ssid.toStdString());
|
||||
connection["connection"]["autoconnect-retries"] = 0;
|
||||
|
||||
connection["802-11-wireless"]["ssid"] = n.ssid;
|
||||
connection["802-11-wireless"]["hidden"] = is_hidden;
|
||||
connection["802-11-wireless"]["mode"] = "infrastructure";
|
||||
|
||||
if (n.security_type == SecurityType::WPA) {
|
||||
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
|
||||
connection["802-11-wireless-security"]["auth-alg"] = "open";
|
||||
connection["802-11-wireless-security"]["psk"] = password;
|
||||
}
|
||||
|
||||
connection["ipv4"]["method"] = "auto";
|
||||
connection["ipv4"]["dns-priority"] = 600;
|
||||
connection["ipv6"]["method"] = "ignore";
|
||||
|
||||
asyncCall(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "AddConnection", QVariant::fromValue(connection));
|
||||
}
|
||||
|
||||
void WifiManager::deactivateConnectionBySsid(const QString &ssid) {
|
||||
for (QDBusObjectPath active_connection : getActiveConnections()) {
|
||||
auto pth = call<QDBusObjectPath>(active_connection.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "SpecificObject");
|
||||
if (!emptyPath(pth.path())) {
|
||||
QString Ssid = get_property(pth.path(), "Ssid");
|
||||
if (Ssid == ssid) {
|
||||
deactivateConnection(active_connection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::deactivateConnection(const QDBusObjectPath &path) {
|
||||
asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeactivateConnection", QVariant::fromValue(path));
|
||||
}
|
||||
|
||||
QVector<QDBusObjectPath> WifiManager::getActiveConnections() {
|
||||
auto result = call<QDBusArgument>(NM_DBUS_PATH, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE, "ActiveConnections");
|
||||
return qdbus_cast<QVector<QDBusObjectPath>>(result);
|
||||
}
|
||||
|
||||
bool WifiManager::isKnownConnection(const QString &ssid) {
|
||||
return !getConnectionPath(ssid).path().isEmpty();
|
||||
}
|
||||
|
||||
void WifiManager::forgetConnection(const QString &ssid) {
|
||||
const QDBusObjectPath &path = getConnectionPath(ssid);
|
||||
if (!path.path().isEmpty()) {
|
||||
call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Delete");
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::setCurrentConnecting(const QString &ssid) {
|
||||
connecting_to_network = ssid;
|
||||
for (auto &network : seenNetworks) {
|
||||
network.connected = (network.ssid == ssid) ? ConnectedType::CONNECTING : ConnectedType::DISCONNECTED;
|
||||
}
|
||||
emit refreshSignal();
|
||||
}
|
||||
|
||||
uint WifiManager::getAdapterType(const QDBusObjectPath &path) {
|
||||
return call<uint>(path.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE, "DeviceType");
|
||||
}
|
||||
|
||||
void WifiManager::requestScan() {
|
||||
if (!adapter.isEmpty()) {
|
||||
asyncCall(adapter, NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", QVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray WifiManager::get_property(const QString &network_path , const QString &property) {
|
||||
return call<QByteArray>(network_path, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACCESS_POINT, property);
|
||||
}
|
||||
|
||||
QString WifiManager::getAdapter(const uint adapter_type) {
|
||||
QDBusReply<QList<QDBusObjectPath>> response = call(NM_DBUS_PATH, NM_DBUS_INTERFACE, "GetDevices");
|
||||
for (const QDBusObjectPath &path : response.value()) {
|
||||
if (getAdapterType(path) == adapter_type) {
|
||||
return path.path();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void WifiManager::stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason) {
|
||||
raw_adapter_state = new_state;
|
||||
if (new_state == NM_DEVICE_STATE_NEED_AUTH && change_reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT && !connecting_to_network.isEmpty()) {
|
||||
forgetConnection(connecting_to_network);
|
||||
emit wrongPassword(connecting_to_network);
|
||||
} else if (new_state == NM_DEVICE_STATE_ACTIVATED) {
|
||||
connecting_to_network = "";
|
||||
refreshNetworks();
|
||||
}
|
||||
}
|
||||
|
||||
// https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.Device.Wireless.html
|
||||
void WifiManager::propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props) {
|
||||
if (interface == NM_DBUS_INTERFACE_DEVICE_WIRELESS && props.contains("LastScan")) {
|
||||
refreshNetworks();
|
||||
} else if (interface == NM_DBUS_INTERFACE_DEVICE_WIRELESS && props.contains("ActiveAccessPoint")) {
|
||||
activeAp = props.value("ActiveAccessPoint").value<QDBusObjectPath>().path();
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::deviceAdded(const QDBusObjectPath &path) {
|
||||
if (getAdapterType(path) == NM_DEVICE_TYPE_WIFI && emptyPath(adapter)) {
|
||||
adapter = path.path();
|
||||
setup();
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::connectionRemoved(const QDBusObjectPath &path) {
|
||||
knownConnections.remove(path);
|
||||
}
|
||||
|
||||
void WifiManager::newConnection(const QDBusObjectPath &path) {
|
||||
Connection settings = getConnectionSettings(path);
|
||||
if (settings.value("connection").value("type") == "802-11-wireless") {
|
||||
knownConnections[path] = settings.value("802-11-wireless").value("ssid").toString();
|
||||
if (knownConnections[path] != tethering_ssid) {
|
||||
activateWifiConnection(knownConnections[path]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDBusObjectPath WifiManager::getConnectionPath(const QString &ssid) {
|
||||
return knownConnections.key(ssid);
|
||||
}
|
||||
|
||||
Connection WifiManager::getConnectionSettings(const QDBusObjectPath &path) {
|
||||
return QDBusReply<Connection>(call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSettings")).value();
|
||||
}
|
||||
|
||||
void WifiManager::initConnections() {
|
||||
const QDBusReply<QList<QDBusObjectPath>> response = call(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "ListConnections");
|
||||
for (const QDBusObjectPath &path : response.value()) {
|
||||
const Connection settings = getConnectionSettings(path);
|
||||
if (settings.value("connection").value("type") == "802-11-wireless") {
|
||||
knownConnections[path] = settings.value("802-11-wireless").value("ssid").toString();
|
||||
} else if (settings.value("connection").value("id") == "lte") {
|
||||
lteConnectionPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isKnownConnection(tethering_ssid)) {
|
||||
addTetheringConnection();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<QDBusPendingCall> WifiManager::activateWifiConnection(const QString &ssid) {
|
||||
const QDBusObjectPath &path = getConnectionPath(ssid);
|
||||
if (!path.path().isEmpty()) {
|
||||
setCurrentConnecting(ssid);
|
||||
return asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "ActivateConnection", QVariant::fromValue(path), QVariant::fromValue(QDBusObjectPath(adapter)), QVariant::fromValue(QDBusObjectPath("/")));
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void WifiManager::activateModemConnection(const QDBusObjectPath &path) {
|
||||
QString modem = getAdapter(NM_DEVICE_TYPE_MODEM);
|
||||
if (!path.path().isEmpty() && !modem.isEmpty()) {
|
||||
asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "ActivateConnection", QVariant::fromValue(path), QVariant::fromValue(QDBusObjectPath(modem)), QVariant::fromValue(QDBusObjectPath("/")));
|
||||
}
|
||||
}
|
||||
|
||||
// function matches tici/hardware.py
|
||||
// FIXME: it can mistakenly show CELL when connected to WIFI
|
||||
NetworkType WifiManager::currentNetworkType() {
|
||||
auto primary_conn = call<QDBusObjectPath>(NM_DBUS_PATH, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE, "PrimaryConnection");
|
||||
auto primary_type = call<QString>(primary_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type");
|
||||
|
||||
if (primary_type == "802-3-ethernet") {
|
||||
return NetworkType::ETHERNET;
|
||||
} else if (primary_type == "802-11-wireless" && !isTetheringEnabled()) {
|
||||
return NetworkType::WIFI;
|
||||
} else {
|
||||
for (const QDBusObjectPath &conn : getActiveConnections()) {
|
||||
auto type = call<QString>(conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type");
|
||||
if (type == "gsm") {
|
||||
return NetworkType::CELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NetworkType::NONE;
|
||||
}
|
||||
|
||||
MeteredType WifiManager::currentNetworkMetered() {
|
||||
MeteredType metered = MeteredType::UNKNOWN;
|
||||
for (const auto &active_conn : getActiveConnections()) {
|
||||
QString type = call<QString>(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type");
|
||||
if (type == "802-11-wireless") {
|
||||
QDBusObjectPath conn = call<QDBusObjectPath>(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Connection");
|
||||
if (!conn.path().isEmpty()) {
|
||||
Connection settings = getConnectionSettings(conn);
|
||||
int metered_prop = settings.value("connection").value("metered").toInt();
|
||||
if (metered_prop == NM_METERED_YES) {
|
||||
metered = MeteredType::YES;
|
||||
} else if (metered_prop == NM_METERED_NO) {
|
||||
metered = MeteredType::NO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return metered;
|
||||
}
|
||||
|
||||
std::optional<QDBusPendingCall> WifiManager::setCurrentNetworkMetered(MeteredType metered) {
|
||||
for (const auto &active_conn : getActiveConnections()) {
|
||||
QString type = call<QString>(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type");
|
||||
if (type == "802-11-wireless") {
|
||||
if (!isTetheringEnabled()) {
|
||||
QDBusObjectPath conn = call<QDBusObjectPath>(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Connection");
|
||||
if (!conn.path().isEmpty()) {
|
||||
Connection settings = getConnectionSettings(conn);
|
||||
settings["connection"]["metered"] = static_cast<int>(metered);
|
||||
return asyncCall(conn.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update", QVariant::fromValue(settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void WifiManager::updateGsmSettings(bool roaming, QString apn, bool metered) {
|
||||
if (!lteConnectionPath.path().isEmpty()) {
|
||||
bool changes = false;
|
||||
bool auto_config = apn.isEmpty();
|
||||
Connection settings = getConnectionSettings(lteConnectionPath);
|
||||
if (settings.value("gsm").value("auto-config").toBool() != auto_config) {
|
||||
qWarning() << "Changing gsm.auto-config to" << auto_config;
|
||||
settings["gsm"]["auto-config"] = auto_config;
|
||||
changes = true;
|
||||
}
|
||||
|
||||
if (settings.value("gsm").value("apn").toString() != apn) {
|
||||
qWarning() << "Changing gsm.apn to" << apn;
|
||||
settings["gsm"]["apn"] = apn;
|
||||
changes = true;
|
||||
}
|
||||
|
||||
if (settings.value("gsm").value("home-only").toBool() == roaming) {
|
||||
qWarning() << "Changing gsm.home-only to" << !roaming;
|
||||
settings["gsm"]["home-only"] = !roaming;
|
||||
changes = true;
|
||||
}
|
||||
|
||||
int meteredInt = metered ? NM_METERED_UNKNOWN : NM_METERED_NO;
|
||||
if (settings.value("connection").value("metered").toInt() != meteredInt) {
|
||||
qWarning() << "Changing connection.metered to" << meteredInt;
|
||||
settings["connection"]["metered"] = meteredInt;
|
||||
changes = true;
|
||||
}
|
||||
|
||||
if (changes) {
|
||||
QDBusPendingCall pending_call = asyncCall(lteConnectionPath.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "UpdateUnsaved", QVariant::fromValue(settings)); // update is temporary
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending_call);
|
||||
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher]() {
|
||||
deactivateConnection(lteConnectionPath);
|
||||
activateModemConnection(lteConnectionPath);
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for tethering
|
||||
void WifiManager::addTetheringConnection() {
|
||||
Connection connection;
|
||||
connection["connection"]["id"] = "Hotspot";
|
||||
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
|
||||
connection["connection"]["type"] = "802-11-wireless";
|
||||
connection["connection"]["interface-name"] = "wlan0";
|
||||
connection["connection"]["autoconnect"] = false;
|
||||
|
||||
connection["802-11-wireless"]["band"] = "bg";
|
||||
connection["802-11-wireless"]["mode"] = "ap";
|
||||
connection["802-11-wireless"]["ssid"] = tethering_ssid.toUtf8();
|
||||
|
||||
connection["802-11-wireless-security"]["group"] = QStringList("ccmp");
|
||||
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
|
||||
connection["802-11-wireless-security"]["pairwise"] = QStringList("ccmp");
|
||||
connection["802-11-wireless-security"]["proto"] = QStringList("rsn");
|
||||
connection["802-11-wireless-security"]["psk"] = defaultTetheringPassword;
|
||||
|
||||
connection["ipv4"]["method"] = "shared";
|
||||
QVariantMap address;
|
||||
address["address"] = "192.168.43.1";
|
||||
address["prefix"] = 24u;
|
||||
connection["ipv4"]["address-data"] = QVariant::fromValue(IpConfig() << address);
|
||||
connection["ipv4"]["gateway"] = "192.168.43.1";
|
||||
connection["ipv4"]["never-default"] = true;
|
||||
connection["ipv6"]["method"] = "ignore";
|
||||
|
||||
asyncCall(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "AddConnection", QVariant::fromValue(connection));
|
||||
}
|
||||
|
||||
void WifiManager::tetheringActivated(QDBusPendingCallWatcher *call) {
|
||||
if (!ipv4_forward) {
|
||||
QTimer::singleShot(5000, this, [=] {
|
||||
qWarning() << "net.ipv4.ip_forward = 0";
|
||||
std::system("sudo sysctl net.ipv4.ip_forward=0");
|
||||
});
|
||||
}
|
||||
call->deleteLater();
|
||||
tethering_on = true;
|
||||
}
|
||||
|
||||
void WifiManager::setTetheringEnabled(bool enabled) {
|
||||
if (enabled) {
|
||||
auto pending_call = activateWifiConnection(tethering_ssid);
|
||||
|
||||
if (pending_call) {
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(*pending_call);
|
||||
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &WifiManager::tetheringActivated);
|
||||
}
|
||||
|
||||
} else {
|
||||
deactivateConnectionBySsid(tethering_ssid);
|
||||
tethering_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WifiManager::isTetheringEnabled() {
|
||||
if (!emptyPath(activeAp)) {
|
||||
return get_property(activeAp, "Ssid") == tethering_ssid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WifiManager::getTetheringPassword() {
|
||||
const QDBusObjectPath &path = getConnectionPath(tethering_ssid);
|
||||
if (!path.path().isEmpty()) {
|
||||
QDBusReply<QMap<QString, QVariantMap>> response = call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSecrets", "802-11-wireless-security");
|
||||
return response.value().value("802-11-wireless-security").value("psk").toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void WifiManager::changeTetheringPassword(const QString &newPassword) {
|
||||
const QDBusObjectPath &path = getConnectionPath(tethering_ssid);
|
||||
if (!path.path().isEmpty()) {
|
||||
Connection settings = getConnectionSettings(path);
|
||||
settings["802-11-wireless-security"]["psk"] = newPassword;
|
||||
call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update", QVariant::fromValue(settings));
|
||||
if (isTetheringEnabled()) {
|
||||
activateWifiConnection(tethering_ssid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <QtDBus>
|
||||
#include <QTimer>
|
||||
|
||||
#include "selfdrive/ui/qt/network/networkmanager.h"
|
||||
|
||||
enum class SecurityType {
|
||||
OPEN,
|
||||
WPA,
|
||||
UNSUPPORTED
|
||||
};
|
||||
enum class ConnectedType {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
};
|
||||
enum class NetworkType {
|
||||
NONE,
|
||||
WIFI,
|
||||
CELL,
|
||||
ETHERNET
|
||||
};
|
||||
enum class MeteredType {
|
||||
UNKNOWN,
|
||||
YES,
|
||||
NO
|
||||
};
|
||||
|
||||
typedef QMap<QString, QVariantMap> Connection;
|
||||
typedef QVector<QVariantMap> IpConfig;
|
||||
|
||||
struct Network {
|
||||
QByteArray ssid;
|
||||
unsigned int strength;
|
||||
ConnectedType connected;
|
||||
SecurityType security_type;
|
||||
};
|
||||
bool compare_by_strength(const Network &a, const Network &b);
|
||||
inline int strengthLevel(unsigned int strength) { return std::clamp((int)round(strength / 33.), 0, 3); }
|
||||
|
||||
class WifiManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QMap<QString, Network> seenNetworks;
|
||||
QMap<QDBusObjectPath, QString> knownConnections;
|
||||
QString ipv4_address;
|
||||
bool tethering_on = false;
|
||||
bool ipv4_forward = false;
|
||||
|
||||
explicit WifiManager(QObject* parent);
|
||||
void start();
|
||||
void stop();
|
||||
void requestScan();
|
||||
void forgetConnection(const QString &ssid);
|
||||
bool isKnownConnection(const QString &ssid);
|
||||
std::optional<QDBusPendingCall> activateWifiConnection(const QString &ssid);
|
||||
NetworkType currentNetworkType();
|
||||
MeteredType currentNetworkMetered();
|
||||
std::optional<QDBusPendingCall> setCurrentNetworkMetered(MeteredType metered);
|
||||
void updateGsmSettings(bool roaming, QString apn, bool metered);
|
||||
void connect(const Network &ssid, const bool is_hidden = false, const QString &password = {}, const QString &username = {});
|
||||
|
||||
// Tethering functions
|
||||
void setTetheringEnabled(bool enabled);
|
||||
bool isTetheringEnabled();
|
||||
void changeTetheringPassword(const QString &newPassword);
|
||||
QString getTetheringPassword();
|
||||
|
||||
QString getIp4Address();
|
||||
|
||||
private:
|
||||
QString adapter; // Path to network manager wifi-device
|
||||
QTimer timer;
|
||||
unsigned int raw_adapter_state = NM_DEVICE_STATE_UNKNOWN; // Connection status https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMDeviceState
|
||||
QString connecting_to_network;
|
||||
QString tethering_ssid;
|
||||
const QString defaultTetheringPassword = "swagswagcomma";
|
||||
QString activeAp;
|
||||
QDBusObjectPath lteConnectionPath;
|
||||
|
||||
QString getAdapter(const uint = NM_DEVICE_TYPE_WIFI);
|
||||
uint getAdapterType(const QDBusObjectPath &path);
|
||||
void deactivateConnectionBySsid(const QString &ssid);
|
||||
void deactivateConnection(const QDBusObjectPath &path);
|
||||
QVector<QDBusObjectPath> getActiveConnections();
|
||||
QByteArray get_property(const QString &network_path, const QString &property);
|
||||
SecurityType getSecurityType(const QVariantMap &properties);
|
||||
QDBusObjectPath getConnectionPath(const QString &ssid);
|
||||
Connection getConnectionSettings(const QDBusObjectPath &path);
|
||||
void initConnections();
|
||||
void setup();
|
||||
void refreshNetworks();
|
||||
void activateModemConnection(const QDBusObjectPath &path);
|
||||
void addTetheringConnection();
|
||||
void setCurrentConnecting(const QString &ssid);
|
||||
|
||||
signals:
|
||||
void wrongPassword(const QString &ssid);
|
||||
void refreshSignal();
|
||||
|
||||
private slots:
|
||||
void stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason);
|
||||
void propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props);
|
||||
void deviceAdded(const QDBusObjectPath &path);
|
||||
void connectionRemoved(const QDBusObjectPath &path);
|
||||
void newConnection(const QDBusObjectPath &path);
|
||||
void refreshFinished(QDBusPendingCallWatcher *call);
|
||||
void tetheringActivated(QDBusPendingCallWatcher *call);
|
||||
};
|
||||
@@ -1,401 +0,0 @@
|
||||
#include "selfdrive/ui/qt/offroad/developer_panel.h"
|
||||
#include "selfdrive/ui/qt/widgets/ssh_keys.h"
|
||||
#include "selfdrive/ui/qt/widgets/controls.h"
|
||||
|
||||
DeveloperPanel::DeveloperPanel(SettingsWindow *parent) : QFrame(parent) {
|
||||
mainLayout = new QStackedLayout(this);
|
||||
|
||||
mainWidget = new QWidget(this);
|
||||
QVBoxLayout *mainListLayout = new QVBoxLayout(mainWidget);
|
||||
|
||||
mainListLayout->setContentsMargins(50, 25, 50, 25);
|
||||
mainListLayout->setSpacing(20);
|
||||
|
||||
StarPilotListWidget *mainList = new StarPilotListWidget(mainWidget);
|
||||
mainListLayout->addWidget(mainList);
|
||||
|
||||
adbToggle = new ParamControl("AdbEnabled", tr("Enable ADB"),
|
||||
tr("ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info."), "");
|
||||
mainList->addItem(adbToggle);
|
||||
|
||||
auto *usePrebuiltToggle = new ParamControl("UsePrebuilt", tr("Use Prebuilt Binaries"),
|
||||
tr("When enabled (default), the device skips source compilation on boot if a prebuilt artifact exists. Disable this if you plan to edit code and rebuild on-device."), "");
|
||||
mainList->addItem(usePrebuiltToggle);
|
||||
|
||||
auto *showAllToggles = new ParamControl("ShowAllToggles", tr("Show All Toggles"),
|
||||
tr("<b>Show every toggle</b> in Settings and StarPilot, even when it would normally be hidden by tuning level, car support, or related feature gating."), "");
|
||||
QObject::connect(showAllToggles, &ParamControl::toggleFlipped, [this](bool) {
|
||||
updateToggles(offroad);
|
||||
emit showAllTogglesChanged();
|
||||
});
|
||||
mainList->addItem(showAllToggles);
|
||||
|
||||
// SSH keys
|
||||
mainList->addItem(new SshToggle());
|
||||
mainList->addItem(new SshControl());
|
||||
|
||||
joystickToggle = new ParamControl("JoystickDebugMode", tr("Joystick Debug Mode"), "", "");
|
||||
QObject::connect(joystickToggle, &ParamControl::toggleFlipped, [=](bool state) {
|
||||
params.putBool("LongitudinalManeuverMode", false);
|
||||
longManeuverToggle->refresh();
|
||||
});
|
||||
mainList->addItem(joystickToggle);
|
||||
|
||||
longManeuverToggle = new ParamControl("LongitudinalManeuverMode", tr("Longitudinal Maneuver Mode"), "", "");
|
||||
QObject::connect(longManeuverToggle, &ParamControl::toggleFlipped, [=](bool state) {
|
||||
params.putBool("JoystickDebugMode", false);
|
||||
joystickToggle->refresh();
|
||||
});
|
||||
mainList->addItem(longManeuverToggle);
|
||||
|
||||
experimentalLongitudinalToggle = new ParamControl(
|
||||
"AlphaLongitudinalEnabled",
|
||||
tr("openpilot Longitudinal Control (Alpha)"),
|
||||
QString("<b>%1</b><br><br>%2")
|
||||
.arg(tr("WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB)."))
|
||||
.arg(tr("On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. "
|
||||
"Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha.")),
|
||||
""
|
||||
);
|
||||
experimentalLongitudinalToggle->setConfirmation(true, false);
|
||||
QObject::connect(experimentalLongitudinalToggle, &ParamControl::toggleFlipped, [=]() {
|
||||
updateToggles(offroad);
|
||||
});
|
||||
mainList->addItem(experimentalLongitudinalToggle);
|
||||
|
||||
// Joystick and longitudinal maneuvers should be hidden on release branches
|
||||
is_release = false;
|
||||
|
||||
// Toggles should be not available to change in onroad state
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, this, &DeveloperPanel::updateToggles);
|
||||
|
||||
QJsonObject shownDescriptions = QJsonDocument::fromJson(QString::fromStdString(params.get("ShownToggleDescriptions")).toUtf8()).object();
|
||||
QString className = this->metaObject()->className();
|
||||
|
||||
if (!shownDescriptions.value(className).toBool(false)) {
|
||||
forceOpenDescriptions = true;
|
||||
}
|
||||
|
||||
std::vector<std::string> keys = params.allKeys();
|
||||
for (const std::string &key : keys) {
|
||||
starpilotToggleLevels[QString::fromStdString(key)] = params.getTuningLevel(key);
|
||||
}
|
||||
|
||||
developerUIToggle = new StarPilotManageControl("DeveloperUI", tr("Developer UI"), tr("<b>Detailed information about openpilot's internal operations.</b>"), "");
|
||||
QObject::connect(developerUIToggle, &StarPilotManageControl::manageButtonClicked, [this]() {
|
||||
mainLayout->setCurrentWidget(developerUIPanel);
|
||||
emit openSubPanel();
|
||||
});
|
||||
mainList->insertItem(0, developerUIToggle);
|
||||
|
||||
mainLayout->addWidget(mainWidget);
|
||||
|
||||
StarPilotListWidget *developerUIList = new StarPilotListWidget(this);
|
||||
developerUIList->setContentsMargins(50, 25, 50, 25);
|
||||
developerUIPanel = new ScrollView(developerUIList, this);
|
||||
mainLayout->addWidget(developerUIPanel);
|
||||
|
||||
StarPilotListWidget *developerMetricList = new StarPilotListWidget(this);
|
||||
developerMetricList->setContentsMargins(50, 25, 50, 25);
|
||||
developerMetricPanel = new ScrollView(developerMetricList, this);
|
||||
mainLayout->addWidget(developerMetricPanel);
|
||||
|
||||
StarPilotListWidget *developerSidebarList = new StarPilotListWidget(this);
|
||||
developerSidebarList->setContentsMargins(50, 25, 50, 25);
|
||||
developerSidebarPanel = new ScrollView(developerSidebarList, this);
|
||||
mainLayout->addWidget(developerSidebarPanel);
|
||||
|
||||
StarPilotListWidget *developerWidgetList = new StarPilotListWidget(this);
|
||||
developerWidgetList->setContentsMargins(50, 25, 50, 25);
|
||||
developerWidgetPanel = new ScrollView(developerWidgetList, this);
|
||||
mainLayout->addWidget(developerWidgetPanel);
|
||||
|
||||
std::vector<std::tuple<QString, QString, QString, QString>> developerToggles {
|
||||
{"DeveloperMetrics", tr("Developer Metrics"), tr("<b>Performance data, sensor readings, and system metrics</b> for debugging and optimizing openpilot."), ""},
|
||||
{"AdjacentPathMetrics", tr("Adjacent Lane Metrics"), tr("<b>Show the width of the adjacent lanes.</b>"), ""},
|
||||
{"BorderMetrics", tr("Border Metrics"), tr("<b>Show statuses along the border of the driving screen.</b><br><br><b>Blind Spot</b>: The border turns red when a vehicle is in a blind spot<br><b>Steering Torque</b>: The border goes from green to red according to how much steering torque is being used<br><b>Turn Signal</b>: The border flashes yellow when a turn signal is on"), ""},
|
||||
{"FPSCounter", tr("FPS Display"), tr("<b>Show the frames per second (FPS)</b> at the bottom of the driving screen."), ""},
|
||||
{"LeadInfo", tr("Lead Info"), tr("<b>Show each tracked vehicle's distance and speed</b> below its marker."), ""},
|
||||
{"NumericalTemp", tr("Numerical Temperature Gauge"), tr("<b>Show a numerical temperature in the sidebar</b> instead of the status labels."), ""},
|
||||
{"SidebarMetrics", tr("Sidebar Metrics"), tr("<b>Display system information</b> (CPU, GPU, RAM usage, IP address, device storage) in the sidebar."), ""},
|
||||
{"UseSI", tr("Use International System of Units"), tr("<b>Display measurements using the \"International System of Units\" (SI)</b> standard."), ""},
|
||||
|
||||
{"DeveloperSidebar", tr("Developer Sidebar"), tr("<b>Display debugging info and metrics</b> in a dedicated sidebar on the right side of the screen."), ""},
|
||||
{"DeveloperSidebarMetric1", tr("Metric #1"), tr("<b>Select the metric shown in the first \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric2", tr("Metric #2"), tr("<b>Select the metric shown in the second \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric3", tr("Metric #3"), tr("<b>Select the metric shown in the third \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric4", tr("Metric #4"), tr("<b>Select the metric shown in the fourth \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric5", tr("Metric #5"), tr("<b>Select the metric shown in the fifth \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric6", tr("Metric #6"), tr("<b>Select the metric shown in the sixth \"Developer Sidebar\" widget.</b>"), ""},
|
||||
{"DeveloperSidebarMetric7", tr("Metric #7"), tr("<b>Select the metric shown in the seventh \"Developer Sidebar\" widget.</b>"), ""},
|
||||
|
||||
{"DeveloperWidgets", tr("Developer Widgets"), tr("<b>Overlays for debugging visuals, internal states, and model predictions</b> on the driving screen."), ""},
|
||||
{"AdjacentLeadsUI", tr("Adjacent Leads Tracking"), tr("<b>Display adjacent leads detected by the car's radar</b> to the left and right of the current driving path."), ""},
|
||||
{"ShowStoppingPoint", tr("Model Stopping Point"), tr("<b>Show a stop-sign marker where the model intends to stop.</b>"), ""},
|
||||
{"RadarTracksUI", tr("Radar Tracks"), tr("<b>Display all radar points</b> produced by the car's radar."), ""},
|
||||
};
|
||||
|
||||
for (const auto &[param, title, desc, icon] : developerToggles) {
|
||||
AbstractControl *developerToggle;
|
||||
|
||||
if (param == "DeveloperMetrics") {
|
||||
StarPilotManageControl *developerMetricsToggle = new StarPilotManageControl(param, title, desc, icon);
|
||||
QObject::connect(developerMetricsToggle, &StarPilotManageControl::manageButtonClicked, [this]() {
|
||||
mainLayout->setCurrentWidget(developerMetricPanel);
|
||||
emit openSubSubPanel();
|
||||
});
|
||||
developerToggle = developerMetricsToggle;
|
||||
} else if (param == "BorderMetrics") {
|
||||
std::vector<QString> borderToggles{"BlindSpotMetrics", "ShowSteering", "SignalMetrics"};
|
||||
std::vector<QString> borderToggleNames{tr("Blind Spot"), tr("Steering Torque"), tr("Turn Signal")};
|
||||
borderMetricsButton = new StarPilotButtonToggleControl(param, title, desc, icon, borderToggles, borderToggleNames);
|
||||
developerToggle = borderMetricsButton;
|
||||
} else if (param == "NumericalTemp") {
|
||||
std::vector<QString> temperatureToggles{"Fahrenheit"};
|
||||
std::vector<QString> temperatureToggleNames{tr("Fahrenheit")};
|
||||
developerToggle = new StarPilotButtonToggleControl(param, title, desc, icon, temperatureToggles, temperatureToggleNames);
|
||||
} else if (param == "SidebarMetrics") {
|
||||
sidebarMetricsToggles = {"ShowCPU", "ShowGPU", "ShowIP", "ShowMemoryUsage", "ShowStorageLeft", "ShowStorageUsed"};
|
||||
std::vector<QString> sidebarMetricsToggleNames{tr("CPU"), tr("GPU"), tr("IP"), tr("RAM"), tr("SSD Left"), tr("SSD Used")};
|
||||
sidebarMetricsToggle = new StarPilotButtonsControl(title, desc, icon, sidebarMetricsToggleNames, true, false, 150);
|
||||
for (int i = 0; i < sidebarMetricsToggles.size(); ++i) {
|
||||
if (params.getBool(sidebarMetricsToggles[i].toStdString())) {
|
||||
sidebarMetricsToggle->setCheckedButton(i);
|
||||
}
|
||||
}
|
||||
QObject::connect(sidebarMetricsToggle, &StarPilotButtonsControl::buttonClicked, [this](int id) {
|
||||
params.putBool(sidebarMetricsToggles[id].toStdString(), !params.getBool(sidebarMetricsToggles[id].toStdString()));
|
||||
|
||||
if (id == 0) {
|
||||
params.putBool("ShowGPU", false);
|
||||
} else if (id == 1) {
|
||||
params.putBool("ShowCPU", false);
|
||||
} else if (id == 3) {
|
||||
params.putBool("ShowStorageLeft", false);
|
||||
params.putBool("ShowStorageUsed", false);
|
||||
} else if (id == 4) {
|
||||
params.putBool("ShowMemoryUsage", false);
|
||||
params.putBool("ShowStorageUsed", false);
|
||||
} else if (id == 5) {
|
||||
params.putBool("ShowMemoryUsage", false);
|
||||
params.putBool("ShowStorageLeft", false);
|
||||
}
|
||||
|
||||
sidebarMetricsToggle->clearCheckedButtons();
|
||||
for (int i = 0; i < sidebarMetricsToggles.size(); ++i) {
|
||||
if (params.getBool(sidebarMetricsToggles[i].toStdString())) {
|
||||
sidebarMetricsToggle->setCheckedButton(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
developerToggle = sidebarMetricsToggle;
|
||||
} else if (param == "DeveloperSidebar") {
|
||||
StarPilotManageControl *developerSidebarToggle = new StarPilotManageControl(param, title, desc, icon);
|
||||
QObject::connect(developerSidebarToggle, &StarPilotManageControl::manageButtonClicked, [this]() {
|
||||
mainLayout->setCurrentWidget(developerSidebarPanel);
|
||||
emit openSubSubPanel();
|
||||
});
|
||||
developerToggle = developerSidebarToggle;
|
||||
} else if (developerSidebarKeys.contains(param)) {
|
||||
QMap<int, QString> developerSidebarMetricOptions {
|
||||
{0, tr("None")},
|
||||
{1, tr("Acceleration: Current")},
|
||||
{2, tr("Acceleration: Max")},
|
||||
{3, tr("Auto Tune: Actuator Delay")},
|
||||
{4, tr("Auto Tune: Friction")},
|
||||
{5, tr("Auto Tune: Lateral Acceleration")},
|
||||
{6, tr("Auto Tune: Steer Ratio")},
|
||||
{7, tr("Auto Tune: Stiffness Factor")},
|
||||
{8, tr("Engagement %: Lateral")},
|
||||
{9, tr("Engagement %: Longitudinal")},
|
||||
{10, tr("Lateral Control: Steering Angle")},
|
||||
{11, tr("Lateral Control: Torque % Used")},
|
||||
{12, tr("Longitudinal Control: Actuator Acceleration Output")},
|
||||
{13, tr("Longitudinal MPC: Danger Factor")},
|
||||
{14, tr("Longitudinal MPC Jerk: Acceleration")},
|
||||
{15, tr("Longitudinal MPC Jerk: Danger Zone")},
|
||||
{16, tr("Longitudinal MPC Jerk: Speed Control")},
|
||||
{17, tr("Model Name")},
|
||||
};
|
||||
|
||||
ButtonControl *metricToggle = new ButtonControl(title, tr("SELECT"), desc);
|
||||
QObject::connect(metricToggle, &ButtonControl::clicked, [metricToggle, key = param, developerSidebarMetricOptions, this]() mutable {
|
||||
QString current = developerSidebarMetricOptions.value(params.getInt(key.toStdString()), tr("None"));
|
||||
QString selection = MultiOptionDialog::getSelection(tr("Select a metric to display"), developerSidebarMetricOptions.values(), current, this);
|
||||
|
||||
if (!selection.isEmpty()) {
|
||||
int selectedMetric = developerSidebarMetricOptions.key(selection);
|
||||
|
||||
params.putInt(key.toStdString(), selectedMetric);
|
||||
|
||||
metricToggle->setValue(selection);
|
||||
}
|
||||
});
|
||||
metricToggle->setValue(developerSidebarMetricOptions.value(params.getInt(param.toStdString()), tr("None")));
|
||||
developerToggle = metricToggle;
|
||||
} else if (param == "DeveloperWidgets") {
|
||||
StarPilotManageControl *developerWidgetsToggle = new StarPilotManageControl(param, title, desc, icon);
|
||||
QObject::connect(developerWidgetsToggle, &StarPilotManageControl::manageButtonClicked, [this]() {
|
||||
mainLayout->setCurrentWidget(developerWidgetPanel);
|
||||
emit openSubSubPanel();
|
||||
});
|
||||
developerToggle = developerWidgetsToggle;
|
||||
} else if (param == "ShowStoppingPoint") {
|
||||
std::vector<QString> stoppingPointToggles{"ShowStoppingPointMetrics"};
|
||||
std::vector<QString> stoppingPointToggleNames{tr("Show Distance")};
|
||||
developerToggle = new StarPilotButtonToggleControl(param, title, desc, icon, stoppingPointToggles, stoppingPointToggleNames);
|
||||
} else {
|
||||
developerToggle = new ParamControl(param, title, desc, icon);
|
||||
}
|
||||
|
||||
toggles[param] = developerToggle;
|
||||
|
||||
if (developerMetricKeys.contains(param)) {
|
||||
developerMetricList->addItem(developerToggle);
|
||||
} else if (developerSidebarKeys.contains(param)) {
|
||||
developerSidebarList->addItem(developerToggle);
|
||||
} else if (developerWidgetKeys.contains(param)) {
|
||||
developerWidgetList->addItem(developerToggle);
|
||||
} else {
|
||||
developerUIList->addItem(developerToggle);
|
||||
|
||||
parentKeys.insert(param);
|
||||
}
|
||||
}
|
||||
|
||||
QObject::connect(parent, &SettingsWindow::closeSubPanel, [this]() {mainLayout->setCurrentWidget(mainWidget);});
|
||||
QObject::connect(parent, &SettingsWindow::closeSubSubPanel, [this]() {mainLayout->setCurrentWidget(developerUIPanel);});
|
||||
}
|
||||
|
||||
void DeveloperPanel::updateToggles(bool _offroad) {
|
||||
const bool showAllToggles = params.getBool("ShowAllToggles");
|
||||
|
||||
for (auto btn : findChildren<ParamControl *>()) {
|
||||
btn->setVisible(showAllToggles || !is_release);
|
||||
|
||||
/*
|
||||
* experimentalLongitudinalToggle should be toggelable when:
|
||||
* - visible, and
|
||||
* - during onroad & offroad states
|
||||
*/
|
||||
if (btn != experimentalLongitudinalToggle) {
|
||||
btn->setEnabled(_offroad);
|
||||
}
|
||||
|
||||
for (auto &[key, toggle] : toggles) {
|
||||
if (toggle == btn) {
|
||||
btn->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (developerUIToggle == btn) {
|
||||
btn->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// longManeuverToggle and experimentalLongitudinalToggle should not be toggleable if the car does not have longitudinal control
|
||||
auto cp_bytes = params.get("CarParamsPersistent");
|
||||
if (!cp_bytes.empty()) {
|
||||
AlignedBuffer aligned_buf;
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
|
||||
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
|
||||
|
||||
if ((!CP.getAlphaLongitudinalAvailable() || is_release) && !showAllToggles) {
|
||||
params.remove("AlphaLongitudinalEnabled");
|
||||
experimentalLongitudinalToggle->setEnabled(false);
|
||||
} else {
|
||||
experimentalLongitudinalToggle->setEnabled(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* experimentalLongitudinalToggle should be visible when:
|
||||
* - is not a release branch, and
|
||||
* - the car supports experimental longitudinal control (alpha)
|
||||
*/
|
||||
experimentalLongitudinalToggle->setVisible(showAllToggles || (CP.getAlphaLongitudinalAvailable() && !is_release));
|
||||
|
||||
longManeuverToggle->setEnabled((showAllToggles || hasLongitudinalControl(CP)) && _offroad);
|
||||
|
||||
hasOpenpilotLongitudinal = hasLongitudinalControl(CP);
|
||||
hasRadar = !CP.getRadarUnavailable();
|
||||
|
||||
borderMetricsButton->setVisibleButton(0, showAllToggles || CP.getEnableBsm());
|
||||
} else {
|
||||
longManeuverToggle->setEnabled(showAllToggles && _offroad);
|
||||
experimentalLongitudinalToggle->setEnabled(showAllToggles);
|
||||
experimentalLongitudinalToggle->setVisible(showAllToggles);
|
||||
}
|
||||
experimentalLongitudinalToggle->refresh();
|
||||
|
||||
offroad = _offroad;
|
||||
|
||||
tuningLevel = params.getInt("TuningLevel");
|
||||
|
||||
for (auto &[key, toggle] : toggles) {
|
||||
if (parentKeys.contains(key)) {
|
||||
toggle->setVisible(showAllToggles);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &[key, toggle] : toggles) {
|
||||
if (parentKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool setVisible = showAllToggles || tuningLevel >= starpilotToggleLevels[key].toDouble();
|
||||
|
||||
if (!showAllToggles) {
|
||||
if (key == "AdjacentLeadsUI") {
|
||||
setVisible &= hasRadar && !(params.getBool("AdvancedCustomUI") && params.getBool("HideLeadMarker"));
|
||||
}
|
||||
|
||||
else if (key == "RadarTracksUI") {
|
||||
setVisible &= hasRadar;
|
||||
}
|
||||
|
||||
else if (key == "ShowStoppingPoint") {
|
||||
setVisible &= hasOpenpilotLongitudinal;
|
||||
}
|
||||
}
|
||||
|
||||
toggle->setVisible(setVisible);
|
||||
|
||||
if (setVisible) {
|
||||
if (developerMetricKeys.contains(key)) {
|
||||
toggles["DeveloperMetrics"]->setVisible(true);
|
||||
} else if (developerSidebarKeys.contains(key)) {
|
||||
toggles["DeveloperSidebar"]->setVisible(true);
|
||||
} else if (developerUIKeys.contains(key)) {
|
||||
toggles["DeveloperUI"]->setVisible(true);
|
||||
} else if (developerWidgetKeys.contains(key)) {
|
||||
toggles["DeveloperWidgets"]->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
borderMetricsButton->setVisibleButton(0, showAllToggles || hasBSM);
|
||||
|
||||
developerUIToggle->setVisible(showAllToggles || tuningLevel >= starpilotToggleLevels["DeveloperUI"].toDouble());
|
||||
|
||||
openDescriptions(forceOpenDescriptions, toggles);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void DeveloperPanel::showEvent(QShowEvent *event) {
|
||||
updateToggles(offroad);
|
||||
|
||||
for (int i = 0; i < sidebarMetricsToggles.size(); ++i) {
|
||||
if (params.getBool(sidebarMetricsToggles[i].toStdString())) {
|
||||
sidebarMetricsToggle->setCheckedButton(i);
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject shownDescriptions = QJsonDocument::fromJson(QString::fromStdString(params.get("ShownToggleDescriptions")).toUtf8()).object();
|
||||
QString className = this->metaObject()->className();
|
||||
|
||||
if (!shownDescriptions.value(className).toBool(false)) {
|
||||
shownDescriptions.insert(className, true);
|
||||
params.put("ShownToggleDescriptions", QJsonDocument(shownDescriptions).toJson(QJsonDocument::Compact).toStdString());
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "selfdrive/ui/qt/offroad/settings.h"
|
||||
|
||||
#include "starpilot/ui/qt/offroad/starpilot_settings.h"
|
||||
|
||||
class DeveloperPanel : public QFrame {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeveloperPanel(SettingsWindow *parent);
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
signals:
|
||||
void openSubPanel();
|
||||
void openSubSubPanel();
|
||||
void showAllTogglesChanged();
|
||||
|
||||
private:
|
||||
Params params;
|
||||
ParamControl* adbToggle;
|
||||
ParamControl* joystickToggle;
|
||||
ParamControl* longManeuverToggle;
|
||||
ParamControl* experimentalLongitudinalToggle;
|
||||
bool is_release;
|
||||
bool offroad = false;
|
||||
|
||||
bool forceOpenDescriptions = false;
|
||||
bool hasBSM = true;
|
||||
bool hasOpenpilotLongitudinal = true;
|
||||
bool hasRadar = true;
|
||||
|
||||
int tuningLevel;
|
||||
|
||||
std::map<QString, AbstractControl*> toggles;
|
||||
|
||||
std::vector<QString> sidebarMetricsToggles;
|
||||
|
||||
StarPilotButtonsControl *sidebarMetricsToggle;
|
||||
|
||||
StarPilotButtonToggleControl *borderMetricsButton;
|
||||
|
||||
StarPilotManageControl *developerUIToggle;
|
||||
|
||||
QJsonObject starpilotToggleLevels;
|
||||
|
||||
QSet<QString> developerMetricKeys = {"AdjacentPathMetrics", "BorderMetrics", "FPSCounter", "LeadInfo", "NumericalTemp", "SidebarMetrics", "UseSI"};
|
||||
QSet<QString> developerSidebarKeys = {"DeveloperSidebarMetric1", "DeveloperSidebarMetric2", "DeveloperSidebarMetric3", "DeveloperSidebarMetric4", "DeveloperSidebarMetric5", "DeveloperSidebarMetric6", "DeveloperSidebarMetric7"};
|
||||
QSet<QString> developerUIKeys = {"DeveloperMetrics", "DeveloperSidebar", "DeveloperWidgets"};
|
||||
QSet<QString> developerWidgetKeys = {"AdjacentLeadsUI", "RadarTracksUI", "ShowStoppingPoint"};
|
||||
|
||||
QSet<QString> parentKeys;
|
||||
|
||||
QStackedLayout *mainLayout;
|
||||
|
||||
QWidget *mainWidget;
|
||||
|
||||
ScrollView *developerMetricPanel;
|
||||
ScrollView *developerSidebarPanel;
|
||||
ScrollView *developerUIPanel;
|
||||
ScrollView *developerWidgetPanel;
|
||||
|
||||
private slots:
|
||||
void updateToggles(bool _offroad);
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
#include "selfdrive/ui/qt/offroad/driverview.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QPainter>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
DriverViewWindow::DriverViewWindow(QWidget* parent) : CameraWidget("camerad", VISION_STREAM_DRIVER, parent) {
|
||||
QObject::connect(this, &CameraWidget::clicked, this, &DriverViewWindow::done);
|
||||
QObject::connect(device(), &Device::interactiveTimeout, this, [this]() {
|
||||
if (isVisible()) {
|
||||
emit done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void DriverViewWindow::showEvent(QShowEvent* event) {
|
||||
params.putBool("IsDriverViewEnabled", true);
|
||||
device()->resetInteractiveTimeout(60);
|
||||
CameraWidget::showEvent(event);
|
||||
}
|
||||
|
||||
void DriverViewWindow::hideEvent(QHideEvent* event) {
|
||||
params.putBool("IsDriverViewEnabled", false);
|
||||
stopVipcThread();
|
||||
CameraWidget::hideEvent(event);
|
||||
}
|
||||
|
||||
void DriverViewWindow::paintGL() {
|
||||
CameraWidget::paintGL();
|
||||
|
||||
std::lock_guard lk(frame_lock);
|
||||
QPainter p(this);
|
||||
// startup msg
|
||||
if (frames.empty()) {
|
||||
p.setPen(Qt::white);
|
||||
p.setRenderHint(QPainter::TextAntialiasing);
|
||||
p.setFont(InterFont(100, QFont::Bold));
|
||||
p.drawText(geometry(), Qt::AlignCenter, tr("camera starting"));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &sm = *(uiState()->sm);
|
||||
cereal::DriverStateV2::Reader driver_state = sm["driverStateV2"].getDriverStateV2();
|
||||
bool is_rhd = driver_state.getWheelOnRightProb() > 0.5;
|
||||
auto driver_data = is_rhd ? driver_state.getRightDriverData() : driver_state.getLeftDriverData();
|
||||
|
||||
bool face_detected = driver_data.getFaceProb() > 0.7;
|
||||
if (face_detected) {
|
||||
auto fxy_list = driver_data.getFacePosition();
|
||||
auto std_list = driver_data.getFaceOrientationStd();
|
||||
float face_x = fxy_list[0];
|
||||
float face_y = fxy_list[1];
|
||||
float face_std = std::max(std_list[0], std_list[1]);
|
||||
|
||||
float alpha = 0.7;
|
||||
if (face_std > 0.15) {
|
||||
alpha = std::max(0.7 - (face_std-0.15)*3.5, 0.0);
|
||||
}
|
||||
const int box_size = 220;
|
||||
// use approx instead of distort_points
|
||||
int fbox_x = 1080.0 - 1714.0 * face_x;
|
||||
int fbox_y = -135.0 + (504.0 + std::abs(face_x)*112.0) + (1205.0 - std::abs(face_x)*724.0) * face_y;
|
||||
p.setPen(QPen(QColor(255, 255, 255, alpha * 255), 10));
|
||||
p.drawRoundedRect(fbox_x - box_size / 2, fbox_y - box_size / 2, box_size, box_size, 35.0, 35.0);
|
||||
}
|
||||
|
||||
driver_monitor.updateState(*uiState());
|
||||
driver_monitor.draw(p, rect());
|
||||
}
|
||||
|
||||
mat4 DriverViewWindow::calcFrameMatrix() {
|
||||
const float driver_view_ratio = 2.0;
|
||||
const float yscale = stream_height * driver_view_ratio / stream_width;
|
||||
const float xscale = yscale * glHeight() / glWidth() * stream_width / stream_height;
|
||||
return mat4{{
|
||||
xscale, 0.0, 0.0, 0.0,
|
||||
0.0, yscale, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
}};
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "selfdrive/ui/qt/widgets/cameraview.h"
|
||||
#include "selfdrive/ui/qt/onroad/driver_monitoring.h"
|
||||
|
||||
class DriverViewWindow : public CameraWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverViewWindow(QWidget *parent);
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
protected:
|
||||
mat4 calcFrameMatrix() override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void hideEvent(QHideEvent *event) override;
|
||||
void paintGL() override;
|
||||
|
||||
Params params;
|
||||
DriverMonitorRenderer driver_monitor;
|
||||
};
|
||||
@@ -1,95 +0,0 @@
|
||||
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyle>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
ExperimentalModeButton::ExperimentalModeButton(QWidget *parent) : QPushButton(parent) {
|
||||
chill_pixmap = QPixmap("../assets/icons/couch.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
|
||||
experimental_pixmap = QPixmap("../assets/icons/experimental_grey.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
|
||||
|
||||
// go to toggles and expand whichever mode control is actually active
|
||||
connect(this, &QPushButton::clicked, [=]() {
|
||||
const QString toggle = params.getBool("ConditionalExperimental") ? "ConditionalExperimental" :
|
||||
params.getBool("ConditionalChill") ? "ConditionalChill" :
|
||||
"ExperimentalMode";
|
||||
emit openSettings(2, toggle);
|
||||
});
|
||||
|
||||
setFixedHeight(125);
|
||||
QHBoxLayout *main_layout = new QHBoxLayout;
|
||||
main_layout->setContentsMargins(horizontal_padding, 0, horizontal_padding, 0);
|
||||
|
||||
mode_label = new QLabel;
|
||||
mode_icon = new QLabel;
|
||||
mode_icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
|
||||
main_layout->addWidget(mode_label, 1, Qt::AlignLeft);
|
||||
main_layout->addWidget(mode_icon, 0, Qt::AlignRight);
|
||||
|
||||
setLayout(main_layout);
|
||||
|
||||
setStyleSheet(R"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
}
|
||||
|
||||
QLabel {
|
||||
font-size: 45px;
|
||||
font-weight: 300;
|
||||
text-align: left;
|
||||
font-family: JetBrainsMono;
|
||||
color: #000000;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
void ExperimentalModeButton::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(rect(), 10, 10);
|
||||
|
||||
// gradient
|
||||
bool pressed = isDown();
|
||||
QLinearGradient gradient(rect().left(), 0, rect().right(), 0);
|
||||
if (experimental_mode) {
|
||||
gradient.setColorAt(0, QColor(255, 155, 63, pressed ? 0xcc : 0xff));
|
||||
gradient.setColorAt(1, QColor(219, 56, 34, pressed ? 0xcc : 0xff));
|
||||
} else {
|
||||
gradient.setColorAt(0, QColor(20, 255, 171, pressed ? 0xcc : 0xff));
|
||||
gradient.setColorAt(1, QColor(35, 149, 255, pressed ? 0xcc : 0xff));
|
||||
}
|
||||
p.fillPath(path, gradient);
|
||||
|
||||
// vertical line
|
||||
p.setPen(QPen(QColor(0, 0, 0, 0x4d), 3, Qt::SolidLine));
|
||||
int line_x = rect().right() - img_width - (2 * horizontal_padding);
|
||||
p.drawLine(line_x, rect().bottom(), line_x, rect().top());
|
||||
}
|
||||
|
||||
void ExperimentalModeButton::showEvent(QShowEvent *event) {
|
||||
if (params.getBool("ConditionalExperimental")) {
|
||||
int status = params_memory.getInt("CEStatus");
|
||||
if ((status != 1 && status != 2) && params.getBool("PersistExperimentalState")) {
|
||||
status = params.getInt("PersistedCEStatus");
|
||||
}
|
||||
experimental_mode = !params.getBool("SafeMode") && status == 2;
|
||||
} else if (params.getBool("ConditionalChill")) {
|
||||
int status = params_memory.getInt("CCStatus");
|
||||
if ((status != 1 && status != 2) && params.getBool("PersistChillState")) {
|
||||
status = params.getInt("PersistedCCStatus");
|
||||
}
|
||||
experimental_mode = !params.getBool("SafeMode") && (status == 0 || status == 1);
|
||||
} else {
|
||||
experimental_mode = params.getBool("ExperimentalMode") && !params.getBool("SafeMode");
|
||||
}
|
||||
mode_icon->setPixmap(experimental_mode ? experimental_pixmap : chill_pixmap);
|
||||
mode_label->setText(experimental_mode ? tr("EXPERIMENTAL MODE ON") : tr("CHILL MODE ON"));
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common/params.h"
|
||||
|
||||
class ExperimentalModeButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExperimentalModeButton(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void openSettings(int index = 0, const QString &toggle = "");
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
Params params;
|
||||
Params params_memory{"", true};
|
||||
bool experimental_mode;
|
||||
int img_width = 100;
|
||||
int horizontal_padding = 30;
|
||||
QPixmap experimental_pixmap;
|
||||
QPixmap chill_pixmap;
|
||||
QLabel *mode_label;
|
||||
QLabel *mode_icon;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
@@ -1,177 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'developer_panel.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "developer_panel.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'developer_panel.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_DeveloperPanel_t {
|
||||
QByteArrayData data[7];
|
||||
char stringdata0[90];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_DeveloperPanel_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_DeveloperPanel_t qt_meta_stringdata_DeveloperPanel = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 14), // "DeveloperPanel"
|
||||
QT_MOC_LITERAL(1, 15, 12), // "openSubPanel"
|
||||
QT_MOC_LITERAL(2, 28, 0), // ""
|
||||
QT_MOC_LITERAL(3, 29, 15), // "openSubSubPanel"
|
||||
QT_MOC_LITERAL(4, 45, 21), // "showAllTogglesChanged"
|
||||
QT_MOC_LITERAL(5, 67, 13), // "updateToggles"
|
||||
QT_MOC_LITERAL(6, 81, 8) // "_offroad"
|
||||
|
||||
},
|
||||
"DeveloperPanel\0openSubPanel\0\0"
|
||||
"openSubSubPanel\0showAllTogglesChanged\0"
|
||||
"updateToggles\0_offroad"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_DeveloperPanel[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
4, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
3, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 34, 2, 0x06 /* Public */,
|
||||
3, 0, 35, 2, 0x06 /* Public */,
|
||||
4, 0, 36, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
5, 1, 37, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Bool, 6,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void DeveloperPanel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<DeveloperPanel *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->openSubPanel(); break;
|
||||
case 1: _t->openSubSubPanel(); break;
|
||||
case 2: _t->showAllTogglesChanged(); break;
|
||||
case 3: _t->updateToggles((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (DeveloperPanel::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DeveloperPanel::openSubPanel)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (DeveloperPanel::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DeveloperPanel::openSubSubPanel)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (DeveloperPanel::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DeveloperPanel::showAllTogglesChanged)) {
|
||||
*result = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject DeveloperPanel::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_DeveloperPanel.data,
|
||||
qt_meta_data_DeveloperPanel,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *DeveloperPanel::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *DeveloperPanel::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_DeveloperPanel.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int DeveloperPanel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 4)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 4;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 4)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 4;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void DeveloperPanel::openSubPanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void DeveloperPanel::openSubSubPanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 2
|
||||
void DeveloperPanel::showAllTogglesChanged()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 2, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,133 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'driverview.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "driverview.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'driverview.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_DriverViewWindow_t {
|
||||
QByteArrayData data[3];
|
||||
char stringdata0[23];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_DriverViewWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_DriverViewWindow_t qt_meta_stringdata_DriverViewWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 16), // "DriverViewWindow"
|
||||
QT_MOC_LITERAL(1, 17, 4), // "done"
|
||||
QT_MOC_LITERAL(2, 22, 0) // ""
|
||||
|
||||
},
|
||||
"DriverViewWindow\0done\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_DriverViewWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void DriverViewWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<DriverViewWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->done(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (DriverViewWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DriverViewWindow::done)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject DriverViewWindow::staticMetaObject = { {
|
||||
&CameraWidget::staticMetaObject,
|
||||
qt_meta_stringdata_DriverViewWindow.data,
|
||||
qt_meta_data_DriverViewWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *DriverViewWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *DriverViewWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_DriverViewWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return CameraWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int DriverViewWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = CameraWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void DriverViewWindow::done()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,142 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'experimental_mode.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "experimental_mode.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'experimental_mode.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_ExperimentalModeButton_t {
|
||||
QByteArrayData data[5];
|
||||
char stringdata0[50];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_ExperimentalModeButton_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_ExperimentalModeButton_t qt_meta_stringdata_ExperimentalModeButton = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 22), // "ExperimentalModeButton"
|
||||
QT_MOC_LITERAL(1, 23, 12), // "openSettings"
|
||||
QT_MOC_LITERAL(2, 36, 0), // ""
|
||||
QT_MOC_LITERAL(3, 37, 5), // "index"
|
||||
QT_MOC_LITERAL(4, 43, 6) // "toggle"
|
||||
|
||||
},
|
||||
"ExperimentalModeButton\0openSettings\0"
|
||||
"\0index\0toggle"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_ExperimentalModeButton[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
3, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 29, 2, 0x06 /* Public */,
|
||||
1, 1, 34, 2, 0x26 /* Public | MethodCloned */,
|
||||
1, 0, 37, 2, 0x26 /* Public | MethodCloned */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Int, QMetaType::QString, 3, 4,
|
||||
QMetaType::Void, QMetaType::Int, 3,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void ExperimentalModeButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<ExperimentalModeButton *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->openSettings((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break;
|
||||
case 1: _t->openSettings((*reinterpret_cast< int(*)>(_a[1]))); break;
|
||||
case 2: _t->openSettings(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (ExperimentalModeButton::*)(int , const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ExperimentalModeButton::openSettings)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject ExperimentalModeButton::staticMetaObject = { {
|
||||
&QPushButton::staticMetaObject,
|
||||
qt_meta_stringdata_ExperimentalModeButton.data,
|
||||
qt_meta_data_ExperimentalModeButton,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *ExperimentalModeButton::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *ExperimentalModeButton::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_ExperimentalModeButton.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QPushButton::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int ExperimentalModeButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QPushButton::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 3)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 3;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 3)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 3;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void ExperimentalModeButton::openSettings(int _t1, const QString & _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,477 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'onboarding.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "onboarding.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'onboarding.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_TrainingGuide_t {
|
||||
QByteArrayData data[3];
|
||||
char stringdata0[33];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_TrainingGuide_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_TrainingGuide_t qt_meta_stringdata_TrainingGuide = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 13), // "TrainingGuide"
|
||||
QT_MOC_LITERAL(1, 14, 17), // "completedTraining"
|
||||
QT_MOC_LITERAL(2, 32, 0) // ""
|
||||
|
||||
},
|
||||
"TrainingGuide\0completedTraining\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_TrainingGuide[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void TrainingGuide::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<TrainingGuide *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->completedTraining(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (TrainingGuide::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&TrainingGuide::completedTraining)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject TrainingGuide::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_TrainingGuide.data,
|
||||
qt_meta_data_TrainingGuide,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *TrainingGuide::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *TrainingGuide::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_TrainingGuide.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int TrainingGuide::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void TrainingGuide::completedTraining()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_TermsPage_t {
|
||||
QByteArrayData data[4];
|
||||
char stringdata0[39];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_TermsPage_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_TermsPage_t qt_meta_stringdata_TermsPage = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 9), // "TermsPage"
|
||||
QT_MOC_LITERAL(1, 10, 13), // "acceptedTerms"
|
||||
QT_MOC_LITERAL(2, 24, 0), // ""
|
||||
QT_MOC_LITERAL(3, 25, 13) // "declinedTerms"
|
||||
|
||||
},
|
||||
"TermsPage\0acceptedTerms\0\0declinedTerms"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_TermsPage[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
2, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 24, 2, 0x06 /* Public */,
|
||||
3, 0, 25, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void TermsPage::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<TermsPage *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->acceptedTerms(); break;
|
||||
case 1: _t->declinedTerms(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (TermsPage::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&TermsPage::acceptedTerms)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (TermsPage::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&TermsPage::declinedTerms)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject TermsPage::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_TermsPage.data,
|
||||
qt_meta_data_TermsPage,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *TermsPage::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *TermsPage::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_TermsPage.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int TermsPage::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 2)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 2;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 2)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 2;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void TermsPage::acceptedTerms()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void TermsPage::declinedTerms()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_DeclinePage_t {
|
||||
QByteArrayData data[3];
|
||||
char stringdata0[21];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_DeclinePage_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_DeclinePage_t qt_meta_stringdata_DeclinePage = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11), // "DeclinePage"
|
||||
QT_MOC_LITERAL(1, 12, 7), // "getBack"
|
||||
QT_MOC_LITERAL(2, 20, 0) // ""
|
||||
|
||||
},
|
||||
"DeclinePage\0getBack\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_DeclinePage[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void DeclinePage::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<DeclinePage *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->getBack(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (DeclinePage::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DeclinePage::getBack)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject DeclinePage::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_DeclinePage.data,
|
||||
qt_meta_data_DeclinePage,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *DeclinePage::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *DeclinePage::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_DeclinePage.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int DeclinePage::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void DeclinePage::getBack()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_OnboardingWindow_t {
|
||||
QByteArrayData data[3];
|
||||
char stringdata0[33];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_OnboardingWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_OnboardingWindow_t qt_meta_stringdata_OnboardingWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 16), // "OnboardingWindow"
|
||||
QT_MOC_LITERAL(1, 17, 14), // "onboardingDone"
|
||||
QT_MOC_LITERAL(2, 32, 0) // ""
|
||||
|
||||
},
|
||||
"OnboardingWindow\0onboardingDone\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_OnboardingWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 19, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void OnboardingWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<OnboardingWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->onboardingDone(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (OnboardingWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&OnboardingWindow::onboardingDone)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject OnboardingWindow::staticMetaObject = { {
|
||||
&QStackedWidget::staticMetaObject,
|
||||
qt_meta_stringdata_OnboardingWindow.data,
|
||||
qt_meta_data_OnboardingWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *OnboardingWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *OnboardingWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_OnboardingWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QStackedWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int OnboardingWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QStackedWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 1)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 1;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 1)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 1;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void OnboardingWindow::onboardingDone()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,756 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'settings.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "settings.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'settings.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_SettingsWindow_t {
|
||||
QByteArrayData data[16];
|
||||
char stringdata0[220];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_SettingsWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_SettingsWindow_t qt_meta_stringdata_SettingsWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 14), // "SettingsWindow"
|
||||
QT_MOC_LITERAL(1, 15, 13), // "closeSettings"
|
||||
QT_MOC_LITERAL(2, 29, 0), // ""
|
||||
QT_MOC_LITERAL(3, 30, 19), // "reviewTrainingGuide"
|
||||
QT_MOC_LITERAL(4, 50, 14), // "showDriverView"
|
||||
QT_MOC_LITERAL(5, 65, 23), // "expandToggleDescription"
|
||||
QT_MOC_LITERAL(6, 89, 5), // "param"
|
||||
QT_MOC_LITERAL(7, 95, 14), // "scrollToToggle"
|
||||
QT_MOC_LITERAL(8, 110, 10), // "closePanel"
|
||||
QT_MOC_LITERAL(9, 121, 13), // "closeSubPanel"
|
||||
QT_MOC_LITERAL(10, 135, 16), // "closeSubSubPanel"
|
||||
QT_MOC_LITERAL(11, 152, 19), // "closeSubSubSubPanel"
|
||||
QT_MOC_LITERAL(12, 172, 12), // "updateMetric"
|
||||
QT_MOC_LITERAL(13, 185, 8), // "isMetric"
|
||||
QT_MOC_LITERAL(14, 194, 7), // "bootRun"
|
||||
QT_MOC_LITERAL(15, 202, 17) // "updateTuningLevel"
|
||||
|
||||
},
|
||||
"SettingsWindow\0closeSettings\0\0"
|
||||
"reviewTrainingGuide\0showDriverView\0"
|
||||
"expandToggleDescription\0param\0"
|
||||
"scrollToToggle\0closePanel\0closeSubPanel\0"
|
||||
"closeSubSubPanel\0closeSubSubSubPanel\0"
|
||||
"updateMetric\0isMetric\0bootRun\0"
|
||||
"updateTuningLevel"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_SettingsWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
12, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
12, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 74, 2, 0x06 /* Public */,
|
||||
3, 0, 75, 2, 0x06 /* Public */,
|
||||
4, 0, 76, 2, 0x06 /* Public */,
|
||||
5, 1, 77, 2, 0x06 /* Public */,
|
||||
7, 1, 80, 2, 0x06 /* Public */,
|
||||
8, 0, 83, 2, 0x06 /* Public */,
|
||||
9, 0, 84, 2, 0x06 /* Public */,
|
||||
10, 0, 85, 2, 0x06 /* Public */,
|
||||
11, 0, 86, 2, 0x06 /* Public */,
|
||||
12, 2, 87, 2, 0x06 /* Public */,
|
||||
12, 1, 92, 2, 0x26 /* Public | MethodCloned */,
|
||||
15, 0, 95, 2, 0x06 /* Public */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void, QMetaType::QString, 6,
|
||||
QMetaType::Void, QMetaType::QString, 6,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void, QMetaType::Bool, QMetaType::Bool, 13, 14,
|
||||
QMetaType::Void, QMetaType::Bool, 13,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void SettingsWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<SettingsWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->closeSettings(); break;
|
||||
case 1: _t->reviewTrainingGuide(); break;
|
||||
case 2: _t->showDriverView(); break;
|
||||
case 3: _t->expandToggleDescription((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
case 4: _t->scrollToToggle((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
case 5: _t->closePanel(); break;
|
||||
case 6: _t->closeSubPanel(); break;
|
||||
case 7: _t->closeSubSubPanel(); break;
|
||||
case 8: _t->closeSubSubSubPanel(); break;
|
||||
case 9: _t->updateMetric((*reinterpret_cast< bool(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2]))); break;
|
||||
case 10: _t->updateMetric((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 11: _t->updateTuningLevel(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::closeSettings)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::reviewTrainingGuide)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::showDriverView)) {
|
||||
*result = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)(const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::expandToggleDescription)) {
|
||||
*result = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)(const QString & );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::scrollToToggle)) {
|
||||
*result = 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::closePanel)) {
|
||||
*result = 5;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::closeSubPanel)) {
|
||||
*result = 6;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::closeSubSubPanel)) {
|
||||
*result = 7;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::closeSubSubSubPanel)) {
|
||||
*result = 8;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)(bool , bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::updateMetric)) {
|
||||
*result = 9;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (SettingsWindow::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&SettingsWindow::updateTuningLevel)) {
|
||||
*result = 11;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject SettingsWindow::staticMetaObject = { {
|
||||
&QFrame::staticMetaObject,
|
||||
qt_meta_stringdata_SettingsWindow.data,
|
||||
qt_meta_data_SettingsWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *SettingsWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *SettingsWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_SettingsWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QFrame::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int SettingsWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QFrame::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 12)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 12;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 12)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 12;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void SettingsWindow::closeSettings()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void SettingsWindow::reviewTrainingGuide()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 2
|
||||
void SettingsWindow::showDriverView()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 2, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 3
|
||||
void SettingsWindow::expandToggleDescription(const QString & _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 3, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 4
|
||||
void SettingsWindow::scrollToToggle(const QString & _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 4, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 5
|
||||
void SettingsWindow::closePanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 5, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 6
|
||||
void SettingsWindow::closeSubPanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 6, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 7
|
||||
void SettingsWindow::closeSubSubPanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 7, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 8
|
||||
void SettingsWindow::closeSubSubSubPanel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 8, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 9
|
||||
void SettingsWindow::updateMetric(bool _t1, bool _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 9, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 11
|
||||
void SettingsWindow::updateTuningLevel()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 11, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_GalaxyQRPopup_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[14];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_GalaxyQRPopup_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_GalaxyQRPopup_t qt_meta_stringdata_GalaxyQRPopup = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 13) // "GalaxyQRPopup"
|
||||
|
||||
},
|
||||
"GalaxyQRPopup"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_GalaxyQRPopup[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void GalaxyQRPopup::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject GalaxyQRPopup::staticMetaObject = { {
|
||||
&DialogBase::staticMetaObject,
|
||||
qt_meta_stringdata_GalaxyQRPopup.data,
|
||||
qt_meta_data_GalaxyQRPopup,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *GalaxyQRPopup::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *GalaxyQRPopup::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_GalaxyQRPopup.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return DialogBase::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int GalaxyQRPopup::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = DialogBase::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
struct qt_meta_stringdata_DevicePanel_t {
|
||||
QByteArrayData data[7];
|
||||
char stringdata0[87];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_DevicePanel_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_DevicePanel_t qt_meta_stringdata_DevicePanel = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11), // "DevicePanel"
|
||||
QT_MOC_LITERAL(1, 12, 19), // "reviewTrainingGuide"
|
||||
QT_MOC_LITERAL(2, 32, 0), // ""
|
||||
QT_MOC_LITERAL(3, 33, 14), // "showDriverView"
|
||||
QT_MOC_LITERAL(4, 48, 8), // "poweroff"
|
||||
QT_MOC_LITERAL(5, 57, 6), // "reboot"
|
||||
QT_MOC_LITERAL(6, 64, 22) // "updateCalibDescription"
|
||||
|
||||
},
|
||||
"DevicePanel\0reviewTrainingGuide\0\0"
|
||||
"showDriverView\0poweroff\0reboot\0"
|
||||
"updateCalibDescription"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_DevicePanel[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
5, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 0, 39, 2, 0x06 /* Public */,
|
||||
3, 0, 40, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
4, 0, 41, 2, 0x08 /* Private */,
|
||||
5, 0, 42, 2, 0x08 /* Private */,
|
||||
6, 0, 43, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void DevicePanel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<DevicePanel *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->reviewTrainingGuide(); break;
|
||||
case 1: _t->showDriverView(); break;
|
||||
case 2: _t->poweroff(); break;
|
||||
case 3: _t->reboot(); break;
|
||||
case 4: _t->updateCalibDescription(); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (DevicePanel::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DevicePanel::reviewTrainingGuide)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (DevicePanel::*)();
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&DevicePanel::showDriverView)) {
|
||||
*result = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject DevicePanel::staticMetaObject = { {
|
||||
&ListWidget::staticMetaObject,
|
||||
qt_meta_stringdata_DevicePanel.data,
|
||||
qt_meta_data_DevicePanel,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *DevicePanel::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *DevicePanel::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_DevicePanel.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return ListWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int DevicePanel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = ListWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 5)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 5;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 5)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 5;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void DevicePanel::reviewTrainingGuide()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void DevicePanel::showDriverView()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
|
||||
}
|
||||
struct qt_meta_stringdata_TogglesPanel_t {
|
||||
QByteArrayData data[13];
|
||||
char stringdata0[135];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_TogglesPanel_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_TogglesPanel_t qt_meta_stringdata_TogglesPanel = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12), // "TogglesPanel"
|
||||
QT_MOC_LITERAL(1, 13, 12), // "updateMetric"
|
||||
QT_MOC_LITERAL(2, 26, 0), // ""
|
||||
QT_MOC_LITERAL(3, 27, 6), // "metric"
|
||||
QT_MOC_LITERAL(4, 34, 7), // "bootRun"
|
||||
QT_MOC_LITERAL(5, 42, 17), // "simpleModeChanged"
|
||||
QT_MOC_LITERAL(6, 60, 7), // "enabled"
|
||||
QT_MOC_LITERAL(7, 68, 23), // "expandToggleDescription"
|
||||
QT_MOC_LITERAL(8, 92, 5), // "param"
|
||||
QT_MOC_LITERAL(9, 98, 14), // "scrollToToggle"
|
||||
QT_MOC_LITERAL(10, 113, 11), // "updateState"
|
||||
QT_MOC_LITERAL(11, 125, 7), // "UIState"
|
||||
QT_MOC_LITERAL(12, 133, 1) // "s"
|
||||
|
||||
},
|
||||
"TogglesPanel\0updateMetric\0\0metric\0"
|
||||
"bootRun\0simpleModeChanged\0enabled\0"
|
||||
"expandToggleDescription\0param\0"
|
||||
"scrollToToggle\0updateState\0UIState\0s"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_TogglesPanel[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
6, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
3, // signalCount
|
||||
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 2, 44, 2, 0x06 /* Public */,
|
||||
1, 1, 49, 2, 0x26 /* Public | MethodCloned */,
|
||||
5, 1, 52, 2, 0x06 /* Public */,
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
7, 1, 55, 2, 0x0a /* Public */,
|
||||
9, 1, 58, 2, 0x0a /* Public */,
|
||||
10, 1, 61, 2, 0x08 /* Private */,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::Bool, QMetaType::Bool, 3, 4,
|
||||
QMetaType::Void, QMetaType::Bool, 3,
|
||||
QMetaType::Void, QMetaType::Bool, 6,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::QString, 8,
|
||||
QMetaType::Void, QMetaType::QString, 8,
|
||||
QMetaType::Void, 0x80000000 | 11, 12,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void TogglesPanel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<TogglesPanel *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->updateMetric((*reinterpret_cast< bool(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2]))); break;
|
||||
case 1: _t->updateMetric((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 2: _t->simpleModeChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 3: _t->expandToggleDescription((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
case 4: _t->scrollToToggle((*reinterpret_cast< const QString(*)>(_a[1]))); break;
|
||||
case 5: _t->updateState((*reinterpret_cast< const UIState(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
int *result = reinterpret_cast<int *>(_a[0]);
|
||||
{
|
||||
using _t = void (TogglesPanel::*)(bool , bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&TogglesPanel::updateMetric)) {
|
||||
*result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
using _t = void (TogglesPanel::*)(bool );
|
||||
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&TogglesPanel::simpleModeChanged)) {
|
||||
*result = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject TogglesPanel::staticMetaObject = { {
|
||||
&ListWidget::staticMetaObject,
|
||||
qt_meta_stringdata_TogglesPanel.data,
|
||||
qt_meta_data_TogglesPanel,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *TogglesPanel::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *TogglesPanel::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_TogglesPanel.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return ListWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int TogglesPanel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = ListWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 6)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 6;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 6)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 6;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void TogglesPanel::updateMetric(bool _t1, bool _t2)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||
}
|
||||
|
||||
// SIGNAL 2
|
||||
void TogglesPanel::simpleModeChanged(bool _t1)
|
||||
{
|
||||
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 2, _a);
|
||||
}
|
||||
struct qt_meta_stringdata_SoftwarePanel_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[14];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_SoftwarePanel_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_SoftwarePanel_t qt_meta_stringdata_SoftwarePanel = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 13) // "SoftwarePanel"
|
||||
|
||||
},
|
||||
"SoftwarePanel"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_SoftwarePanel[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void SoftwarePanel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject SoftwarePanel::staticMetaObject = { {
|
||||
&ListWidget::staticMetaObject,
|
||||
qt_meta_stringdata_SoftwarePanel.data,
|
||||
qt_meta_data_SoftwarePanel,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *SoftwarePanel::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *SoftwarePanel::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_SoftwarePanel.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return ListWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int SoftwarePanel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = ListWidget::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,211 +0,0 @@
|
||||
#include "selfdrive/ui/qt/offroad/onboarding.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QTransform>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/params.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/qt/widgets/input.h"
|
||||
|
||||
TrainingGuide::TrainingGuide(QWidget *parent) : QFrame(parent) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
}
|
||||
|
||||
void TrainingGuide::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (click_timer.elapsed() < 250) {
|
||||
return;
|
||||
}
|
||||
click_timer.restart();
|
||||
|
||||
auto contains = [this](QRect r, const QPoint &pt) {
|
||||
if (image.size() != image_raw_size) {
|
||||
QTransform transform;
|
||||
transform.translate((width()- image.width()) / 2.0, (height()- image.height()) / 2.0);
|
||||
transform.scale(image.width() / (float)image_raw_size.width(), image.height() / (float)image_raw_size.height());
|
||||
r= transform.mapRect(r);
|
||||
}
|
||||
return r.contains(pt);
|
||||
};
|
||||
|
||||
if (contains(boundingRect[currentIndex], e->pos())) {
|
||||
if (currentIndex == 9) {
|
||||
const QRect yes = QRect(707, 804, 531, 164);
|
||||
Params().putBool("RecordFront", contains(yes, e->pos()));
|
||||
}
|
||||
currentIndex += 1;
|
||||
} else if (currentIndex == (boundingRect.size() - 2) && contains(boundingRect.last(), e->pos())) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
|
||||
if (currentIndex >= (boundingRect.size() - 1)) {
|
||||
emit completedTraining();
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void TrainingGuide::showEvent(QShowEvent *event) {
|
||||
currentIndex = 0;
|
||||
click_timer.start();
|
||||
}
|
||||
|
||||
QImage TrainingGuide::loadImage(int id) {
|
||||
QImage img(img_path + QString("step%1.png").arg(id));
|
||||
image_raw_size = img.size();
|
||||
if (image_raw_size != rect().size()) {
|
||||
img = img.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
void TrainingGuide::paintEvent(QPaintEvent *event) {
|
||||
QPainter painter(this);
|
||||
|
||||
QRect bg(0, 0, painter.device()->width(), painter.device()->height());
|
||||
painter.fillRect(bg, QColor("#000000"));
|
||||
|
||||
image = loadImage(currentIndex);
|
||||
QRect rect(image.rect());
|
||||
rect.moveCenter(bg.center());
|
||||
painter.drawImage(rect.topLeft(), image);
|
||||
|
||||
// progress bar
|
||||
if (currentIndex > 0 && currentIndex < (boundingRect.size() - 2)) {
|
||||
const int h = 20;
|
||||
const int w = (currentIndex / (float)(boundingRect.size() - 2)) * width();
|
||||
painter.fillRect(QRect(0, height() - h, w, h), QColor("#465BEA"));
|
||||
}
|
||||
}
|
||||
|
||||
void TermsPage::showEvent(QShowEvent *event) {
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
main_layout->setContentsMargins(45, 35, 45, 45);
|
||||
main_layout->setSpacing(0);
|
||||
|
||||
QVBoxLayout *vlayout = new QVBoxLayout();
|
||||
vlayout->setContentsMargins(165, 165, 165, 0);
|
||||
main_layout->addLayout(vlayout);
|
||||
|
||||
QLabel *title = new QLabel(tr("Welcome to openpilot"));
|
||||
title->setStyleSheet("font-size: 90px; font-weight: 500;");
|
||||
vlayout->addWidget(title, 0, Qt::AlignTop | Qt::AlignLeft);
|
||||
|
||||
vlayout->addSpacing(90);
|
||||
QLabel *desc = new QLabel(tr("You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing."));
|
||||
desc->setWordWrap(true);
|
||||
desc->setStyleSheet("font-size: 80px; font-weight: 300;");
|
||||
vlayout->addWidget(desc, 0);
|
||||
|
||||
vlayout->addStretch();
|
||||
|
||||
QHBoxLayout* buttons = new QHBoxLayout;
|
||||
buttons->setMargin(0);
|
||||
buttons->setSpacing(45);
|
||||
main_layout->addLayout(buttons);
|
||||
|
||||
QPushButton *decline_btn = new QPushButton(tr("Decline"));
|
||||
buttons->addWidget(decline_btn);
|
||||
QObject::connect(decline_btn, &QPushButton::clicked, this, &TermsPage::declinedTerms);
|
||||
|
||||
accept_btn = new QPushButton(tr("Agree"));
|
||||
accept_btn->setStyleSheet(R"(
|
||||
QPushButton {
|
||||
background-color: #465BEA;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #3049F4;
|
||||
}
|
||||
)");
|
||||
buttons->addWidget(accept_btn);
|
||||
QObject::connect(accept_btn, &QPushButton::clicked, this, &TermsPage::acceptedTerms);
|
||||
}
|
||||
|
||||
void DeclinePage::showEvent(QShowEvent *event) {
|
||||
if (layout()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
main_layout->setMargin(45);
|
||||
main_layout->setSpacing(40);
|
||||
|
||||
QLabel *text = new QLabel(this);
|
||||
text->setText(tr("You must accept the Terms and Conditions in order to use openpilot."));
|
||||
text->setStyleSheet(R"(font-size: 80px; font-weight: 300; margin: 200px;)");
|
||||
text->setWordWrap(true);
|
||||
main_layout->addWidget(text, 0, Qt::AlignCenter);
|
||||
|
||||
QHBoxLayout* buttons = new QHBoxLayout;
|
||||
buttons->setSpacing(45);
|
||||
main_layout->addLayout(buttons);
|
||||
|
||||
QPushButton *back_btn = new QPushButton(tr("Back"));
|
||||
buttons->addWidget(back_btn);
|
||||
|
||||
QObject::connect(back_btn, &QPushButton::clicked, this, &DeclinePage::getBack);
|
||||
|
||||
QPushButton *uninstall_btn = new QPushButton(tr("Decline, uninstall %1").arg(getBrand()));
|
||||
uninstall_btn->setStyleSheet("background-color: #B73D3D");
|
||||
buttons->addWidget(uninstall_btn);
|
||||
QObject::connect(uninstall_btn, &QPushButton::clicked, [=]() {
|
||||
Params().putBool("DoUninstall", true);
|
||||
});
|
||||
}
|
||||
|
||||
void OnboardingWindow::updateActiveScreen() {
|
||||
if (!accepted_terms) {
|
||||
setCurrentIndex(0);
|
||||
} else if (!training_done) {
|
||||
setCurrentIndex(1);
|
||||
} else {
|
||||
emit onboardingDone();
|
||||
}
|
||||
}
|
||||
|
||||
OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) {
|
||||
std::string current_terms_version = params.get("TermsVersion");
|
||||
std::string current_training_version = params.get("TrainingVersion");
|
||||
accepted_terms = params.get("HasAcceptedTerms") == current_terms_version;
|
||||
training_done = params.get("CompletedTrainingVersion") == current_training_version;
|
||||
|
||||
TermsPage* terms = new TermsPage(this);
|
||||
addWidget(terms);
|
||||
connect(terms, &TermsPage::acceptedTerms, [=]() {
|
||||
params.put("HasAcceptedTerms", current_terms_version);
|
||||
accepted_terms = true;
|
||||
updateActiveScreen();
|
||||
});
|
||||
connect(terms, &TermsPage::declinedTerms, [=]() { setCurrentIndex(2); });
|
||||
|
||||
TrainingGuide* tr = new TrainingGuide(this);
|
||||
addWidget(tr);
|
||||
connect(tr, &TrainingGuide::completedTraining, [=]() {
|
||||
training_done = true;
|
||||
params.put("CompletedTrainingVersion", current_training_version);
|
||||
updateActiveScreen();
|
||||
});
|
||||
|
||||
DeclinePage* declinePage = new DeclinePage(this);
|
||||
addWidget(declinePage);
|
||||
connect(declinePage, &DeclinePage::getBack, [=]() { updateActiveScreen(); });
|
||||
|
||||
setStyleSheet(R"(
|
||||
* {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
QPushButton {
|
||||
height: 160px;
|
||||
font-size: 55px;
|
||||
font-weight: 400;
|
||||
border-radius: 10px;
|
||||
background-color: #4F4F4F;
|
||||
}
|
||||
)");
|
||||
updateActiveScreen();
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QImage>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QStackedWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "selfdrive/ui/qt/qt_window.h"
|
||||
|
||||
class TrainingGuide : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TrainingGuide(QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* e) override;
|
||||
QImage loadImage(int id);
|
||||
|
||||
QImage image;
|
||||
QSize image_raw_size;
|
||||
int currentIndex = 0;
|
||||
|
||||
// Bounding boxes for each training guide step
|
||||
const QRect continueBtn = {1840, 0, 320, 1080};
|
||||
QVector<QRect> boundingRect {
|
||||
QRect(112, 804, 618, 164),
|
||||
continueBtn,
|
||||
continueBtn,
|
||||
QRect(1641, 558, 210, 313),
|
||||
QRect(1662, 528, 184, 108),
|
||||
continueBtn,
|
||||
QRect(1814, 621, 211, 170),
|
||||
QRect(1350, 0, 497, 755),
|
||||
QRect(1540, 386, 468, 238),
|
||||
QRect(112, 804, 1126, 164),
|
||||
QRect(1598, 199, 316, 333),
|
||||
continueBtn,
|
||||
QRect(1364, 90, 796, 990),
|
||||
continueBtn,
|
||||
QRect(1593, 114, 318, 853),
|
||||
QRect(1379, 511, 391, 243),
|
||||
continueBtn,
|
||||
continueBtn,
|
||||
QRect(630, 804, 626, 164),
|
||||
QRect(108, 804, 426, 164),
|
||||
};
|
||||
|
||||
const QString img_path = "../assets/training/";
|
||||
QElapsedTimer click_timer;
|
||||
|
||||
signals:
|
||||
void completedTraining();
|
||||
};
|
||||
|
||||
|
||||
class TermsPage : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TermsPage(QWidget *parent = 0) : QFrame(parent) {}
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
QPushButton *accept_btn;
|
||||
|
||||
signals:
|
||||
void acceptedTerms();
|
||||
void declinedTerms();
|
||||
};
|
||||
|
||||
class DeclinePage : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeclinePage(QWidget *parent = 0) : QFrame(parent) {}
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
signals:
|
||||
void getBack();
|
||||
};
|
||||
|
||||
class OnboardingWindow : public QStackedWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OnboardingWindow(QWidget *parent = 0);
|
||||
inline void showTrainingGuide() { setCurrentIndex(1); }
|
||||
inline bool completed() const { return accepted_terms && training_done; }
|
||||
|
||||
private:
|
||||
void updateActiveScreen();
|
||||
|
||||
Params params;
|
||||
bool accepted_terms = false, training_done = false;
|
||||
|
||||
signals:
|
||||
void onboardingDone();
|
||||
};
|
||||
@@ -1,897 +0,0 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QRandomGenerator>
|
||||
#include <QrCode.hpp>
|
||||
|
||||
#include "common/watchdog.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "selfdrive/ui/qt/network/networking.h"
|
||||
#include "selfdrive/ui/qt/offroad/settings.h"
|
||||
#include "selfdrive/ui/qt/qt_window.h"
|
||||
#include "selfdrive/ui/qt/widgets/input.h"
|
||||
#include "selfdrive/ui/qt/widgets/prime.h"
|
||||
#include "selfdrive/ui/qt/widgets/scrollview.h"
|
||||
#include "selfdrive/ui/qt/offroad/developer_panel.h"
|
||||
|
||||
#include "starpilot/ui/qt/offroad/starpilot_settings.h"
|
||||
|
||||
TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
syncRhdToggle();
|
||||
|
||||
// param, title, desc, icon, restart needed
|
||||
std::vector<std::tuple<QString, QString, QString, QString, bool>> toggle_defs{
|
||||
{
|
||||
"OpenpilotEnabledToggle",
|
||||
tr("Enable openpilot"),
|
||||
tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature."),
|
||||
"../assets/icons/chffr_wheel.png",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"ExperimentalMode",
|
||||
tr("Experimental Mode"),
|
||||
"",
|
||||
"../assets/icons/experimental_white.svg",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"SafeMode",
|
||||
tr("Safe Mode"),
|
||||
tr("Temporarily force driving-affecting StarPilot settings back to safe defaults, stock tuning, and the branch default model until disabled."),
|
||||
"../assets/icons/warning.png",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"SimpleMode",
|
||||
tr("Simple Mode"),
|
||||
tr("Use a more stock-like Qt interface by hiding most branch-specific UI, theme, sound, and alert styling. This only changes presentation and does not change driving behavior."),
|
||||
"../assets/icons/settings.png",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"DisengageOnAccelerator",
|
||||
tr("Disengage on Accelerator Pedal"),
|
||||
tr("When enabled, pressing the accelerator pedal will disengage openpilot."),
|
||||
"../assets/icons/disengage_on_accelerator.svg",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"IsLdwEnabled",
|
||||
tr("Enable Lane Departure Warnings"),
|
||||
tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."),
|
||||
"../assets/icons/warning.png",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"AlwaysOnDM",
|
||||
tr("Always-On Driver Monitoring"),
|
||||
tr("Enable driver monitoring even when openpilot is not engaged."),
|
||||
"../assets/icons/monitoring.png",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"IsRHD",
|
||||
tr("Right Hand Driving"),
|
||||
tr("Use right-hand-drive driver monitoring. This follows the auto-detected side until changed manually."),
|
||||
"../assets/icons/monitoring.png",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"RecordFront",
|
||||
tr("Record and Upload Driver Camera"),
|
||||
tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."),
|
||||
"../assets/icons/monitoring.png",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"RecordAudio",
|
||||
tr("Record and Upload Microphone Audio"),
|
||||
tr("Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect."),
|
||||
"../assets/icons/microphone.png",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"IsMetric",
|
||||
tr("Use Metric System"),
|
||||
tr("Display speed in km/h instead of mph."),
|
||||
"../assets/icons/metric.png",
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
std::vector<QString> longi_button_texts{tr("Aggressive"), tr("Standard"), tr("Relaxed")};
|
||||
long_personality_setting = new ButtonParamControl("LongitudinalPersonality", tr("Driving Personality"),
|
||||
tr("Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. "
|
||||
"In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with "
|
||||
"your steering wheel distance button."),
|
||||
"../assets/icons/speed_limit.png",
|
||||
longi_button_texts);
|
||||
|
||||
// set up uiState update for personality setting
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &TogglesPanel::updateState);
|
||||
|
||||
for (auto &[param, title, desc, icon, needs_restart] : toggle_defs) {
|
||||
auto toggle = new ParamControl(param, title, desc, icon, this);
|
||||
|
||||
bool locked = params.getBool((param + "Lock").toStdString());
|
||||
toggle->setEnabled(!locked);
|
||||
|
||||
if (needs_restart && !locked) {
|
||||
toggle->setDescription(toggle->getDescription() + tr(" Changing this setting will restart openpilot if the car is powered on."));
|
||||
|
||||
QObject::connect(uiState(), &UIState::engagedChanged, [toggle](bool engaged) {
|
||||
toggle->setEnabled(!engaged);
|
||||
});
|
||||
|
||||
QObject::connect(toggle, &ParamControl::toggleFlipped, [=](bool state) {
|
||||
params.putBool("OnroadCycleRequested", true);
|
||||
});
|
||||
}
|
||||
|
||||
if (param == "SimpleMode") {
|
||||
QObject::connect(toggle, &ParamControl::toggleFlipped, this, [this](bool state) {
|
||||
updateToggles();
|
||||
emit simpleModeChanged(state);
|
||||
});
|
||||
}
|
||||
|
||||
if (param == "IsRHD") {
|
||||
QObject::connect(toggle, &ParamControl::toggleFlipped, this, [this](bool state) {
|
||||
params.putBool("IsRHD", state);
|
||||
params.putBool("IsRHDOverride", true);
|
||||
});
|
||||
}
|
||||
|
||||
addItem(toggle);
|
||||
toggles[param.toStdString()] = toggle;
|
||||
|
||||
// insert longitudinal personality after NDOG toggle
|
||||
if (param == "DisengageOnAccelerator") {
|
||||
addItem(long_personality_setting);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggles with confirmation dialogs
|
||||
toggles["ExperimentalMode"]->setActiveIcon("../assets/icons/experimental.svg");
|
||||
toggles["ExperimentalMode"]->setConfirmation(true, true);
|
||||
|
||||
connect(toggles["IsMetric"], &ToggleControl::toggleFlipped, [=](bool isMetric) {
|
||||
updateMetric(isMetric);
|
||||
});
|
||||
}
|
||||
|
||||
void TogglesPanel::syncRhdToggle() {
|
||||
if (!params.getBool("IsRHDOverride")) {
|
||||
params.putBool("IsRHD", params.getBool("IsRhdDetected"));
|
||||
}
|
||||
}
|
||||
|
||||
void TogglesPanel::updateState(const UIState &s) {
|
||||
const SubMaster &sm = *(s.sm);
|
||||
|
||||
if (sm.updated("selfdriveState")) {
|
||||
auto personality = sm["selfdriveState"].getSelfdriveState().getPersonality();
|
||||
if (personality != s.scene.personality && s.scene.started && isVisible()) {
|
||||
long_personality_setting->setCheckedButton(static_cast<int>(personality));
|
||||
}
|
||||
uiState()->scene.personality = personality;
|
||||
}
|
||||
}
|
||||
|
||||
void TogglesPanel::expandToggleDescription(const QString ¶m) {
|
||||
toggles[param.toStdString()]->showDescription();
|
||||
}
|
||||
|
||||
void TogglesPanel::scrollToToggle(const QString ¶m) {
|
||||
if (auto it = toggles.find(param.toStdString()); it != toggles.end()) {
|
||||
auto scroll_area = qobject_cast<QScrollArea*>(parent()->parent());
|
||||
if (scroll_area) {
|
||||
scroll_area->ensureWidgetVisible(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TogglesPanel::showEvent(QShowEvent *event) {
|
||||
updateToggles();
|
||||
}
|
||||
|
||||
void TogglesPanel::updateToggles() {
|
||||
syncRhdToggle();
|
||||
|
||||
const bool showAllToggles = params.getBool("ShowAllToggles");
|
||||
const bool safe_mode = params.getBool("SafeMode");
|
||||
const bool simple_mode = params.getBool("SimpleMode");
|
||||
if (safe_mode) {
|
||||
if (params.getBool("ExperimentalMode")) {
|
||||
params.putBool("ExperimentalMode", false);
|
||||
}
|
||||
if (params.getInt("LongitudinalPersonality") != static_cast<int>(cereal::LongitudinalPersonality::RELAXED)) {
|
||||
params.putInt("LongitudinalPersonality", static_cast<int>(cereal::LongitudinalPersonality::RELAXED));
|
||||
}
|
||||
}
|
||||
auto experimental_mode_toggle = toggles["ExperimentalMode"];
|
||||
const QString e2e_description = QString("%1<br>"
|
||||
"<h4>%2</h4><br>"
|
||||
"%3<br>"
|
||||
"<h4>%4</h4><br>"
|
||||
"%5<br>")
|
||||
.arg(tr("openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below:"))
|
||||
.arg(tr("End-to-End Longitudinal Control"))
|
||||
.arg(tr("Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. "
|
||||
"Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; "
|
||||
"mistakes should be expected."))
|
||||
.arg(tr("New Driving Visualization"))
|
||||
.arg(tr("The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner."));
|
||||
|
||||
const bool is_release = false;
|
||||
auto cp_bytes = params.get("CarParamsPersistent");
|
||||
if (!cp_bytes.empty()) {
|
||||
AlignedBuffer aligned_buf;
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
|
||||
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
|
||||
|
||||
if (hasLongitudinalControl(CP) || showAllToggles) {
|
||||
// normal description and toggle
|
||||
experimental_mode_toggle->setEnabled(!safe_mode);
|
||||
experimental_mode_toggle->setDescription(e2e_description);
|
||||
long_personality_setting->setEnabled(!safe_mode);
|
||||
if (safe_mode) {
|
||||
long_personality_setting->setCheckedButton(static_cast<int>(cereal::LongitudinalPersonality::RELAXED));
|
||||
}
|
||||
} else {
|
||||
// no long for now
|
||||
experimental_mode_toggle->setEnabled(false);
|
||||
long_personality_setting->setEnabled(false);
|
||||
params.remove("ExperimentalMode");
|
||||
|
||||
const QString unavailable = tr("Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control.");
|
||||
|
||||
QString long_desc = unavailable + " " + \
|
||||
tr("openpilot longitudinal control may come in a future update.");
|
||||
if (CP.getAlphaLongitudinalAvailable()) {
|
||||
if (is_release) {
|
||||
long_desc = unavailable + " " + tr("An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches.");
|
||||
} else {
|
||||
long_desc = tr("Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode.");
|
||||
}
|
||||
}
|
||||
experimental_mode_toggle->setDescription("<b>" + long_desc + "</b><br><br>" + e2e_description);
|
||||
}
|
||||
|
||||
experimental_mode_toggle->refresh();
|
||||
} else {
|
||||
experimental_mode_toggle->setDescription(e2e_description);
|
||||
}
|
||||
|
||||
if (safe_mode) {
|
||||
experimental_mode_toggle->setEnabled(false);
|
||||
long_personality_setting->setEnabled(false);
|
||||
long_personality_setting->setCheckedButton(static_cast<int>(cereal::LongitudinalPersonality::RELAXED));
|
||||
}
|
||||
|
||||
StarPilotUIState &fs = *starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
|
||||
auto disengage_on_accelerator_toggle = toggles["DisengageOnAccelerator"];
|
||||
disengage_on_accelerator_toggle->setVisible(showAllToggles || !starpilot_toggles.value("always_on_lateral").toBool());
|
||||
auto driver_camera_toggle = toggles["RecordFront"];
|
||||
driver_camera_toggle->setVisible(showAllToggles || !starpilot_toggles.value("no_logging").toBool());
|
||||
experimental_mode_toggle->setVisible(showAllToggles || !starpilot_toggles.value("conditional_experimental_mode").toBool());
|
||||
auto record_audio_toggle = toggles["RecordAudio"];
|
||||
record_audio_toggle->setVisible(showAllToggles || !starpilot_toggles.value("no_logging").toBool());
|
||||
toggles["IsRHD"]->refresh();
|
||||
|
||||
auto safe_mode_toggle = toggles["SafeMode"];
|
||||
if (safe_mode_toggle != nullptr) {
|
||||
safe_mode_toggle->setVisible(!simple_mode);
|
||||
}
|
||||
}
|
||||
|
||||
GalaxyQRPopup::GalaxyQRPopup(const QString &url, QWidget *parent) : DialogBase(parent) {
|
||||
setStyleSheet("GalaxyQRPopup { background-color: #1a1a30; }");
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setAlignment(Qt::AlignCenter);
|
||||
layout->setSpacing(30);
|
||||
layout->setContentsMargins(60, 40, 60, 40);
|
||||
|
||||
auto qr = qrcodegen::QrCode::encodeText(url.toUtf8().constData(), qrcodegen::QrCode::Ecc::LOW);
|
||||
const int qr_size = qr.getSize();
|
||||
const int quiet_zone_modules = 4;
|
||||
const int qr_display_size = 520;
|
||||
const int image_size = qr_size + 2 * quiet_zone_modules;
|
||||
QImage image(image_size, image_size, QImage::Format_RGB32);
|
||||
image.fill(qRgb(255, 255, 255));
|
||||
for (int y = 0; y < qr_size; ++y) {
|
||||
for (int x = 0; x < qr_size; ++x) {
|
||||
image.setPixel(x + quiet_zone_modules, y + quiet_zone_modules,
|
||||
qr.getModule(x, y) ? qRgb(0, 0, 0) : qRgb(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
QLabel *title = new QLabel(tr("Scan to open Galaxy"), this);
|
||||
title->setStyleSheet("font-size: 52px; font-weight: bold; color: white;");
|
||||
title->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(title);
|
||||
|
||||
QLabel *qr_label = new QLabel(this);
|
||||
qr_label->setPixmap(QPixmap::fromImage(
|
||||
image.scaled(qr_display_size, qr_display_size, Qt::KeepAspectRatio), Qt::MonoOnly));
|
||||
qr_label->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(qr_label);
|
||||
|
||||
QLabel *url_label = new QLabel(url, this);
|
||||
url_label->setStyleSheet("font-size: 36px; color: #8b6cc5;");
|
||||
url_label->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(url_label);
|
||||
|
||||
QLabel *hint = new QLabel(tr("Tap anywhere to dismiss"), this);
|
||||
hint->setStyleSheet("font-size: 28px; color: #7e7e98;");
|
||||
hint->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(hint);
|
||||
}
|
||||
|
||||
DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
setSpacing(50);
|
||||
addItem(new LabelControl(tr("Dongle ID"), getDongleId().value_or(tr("N/A"))));
|
||||
addItem(new LabelControl(tr("Serial"), params.get("HardwareSerial").c_str()));
|
||||
|
||||
pair_device = new ButtonControl(tr("Pair Device"), tr("PAIR"),
|
||||
useKonikServer() ? tr("Pair your device with Konik connect (stable.konik.ai).") : tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer."));
|
||||
connect(pair_device, &ButtonControl::clicked, [=]() {
|
||||
PairingPopup popup(this);
|
||||
popup.exec();
|
||||
});
|
||||
addItem(pair_device);
|
||||
|
||||
const std::string galaxy_dir = Hardware::PC() ? (Path::comma_home() + "/starpilot/data/galaxy") : "/data/galaxy";
|
||||
const std::string galaxy_auth_path = galaxy_dir + "/glxyauth";
|
||||
const std::string galaxy_session_path = galaxy_dir + "/glxysession";
|
||||
const std::string galaxy_slug_path = galaxy_dir + "/glxyslug";
|
||||
|
||||
auto showGalaxyQR = [=]() {
|
||||
std::string slug = util::read_file(galaxy_slug_path);
|
||||
if (slug.empty()) {
|
||||
ConfirmationDialog::alert(tr("Galaxy is not paired yet."), this);
|
||||
return;
|
||||
}
|
||||
|
||||
GalaxyQRPopup popup("https://galaxy.firestar.link/" + QString::fromStdString(slug), this);
|
||||
popup.exec();
|
||||
};
|
||||
|
||||
pair_galaxy = new ButtonControl(tr("Galaxy"), tr("PAIR"), tr("Pair your device with Galaxy for remote access to The Galaxy."));
|
||||
connect(pair_galaxy, &ButtonControl::clicked, [=]() {
|
||||
const std::string current_password = util::read_file(galaxy_auth_path);
|
||||
if (current_password.empty()) {
|
||||
QString new_password = InputDialog::getText(
|
||||
tr("Set Galaxy Password"), this,
|
||||
tr("Set a password to secure your Galaxy access. (Min 6 characters)"),
|
||||
false, 6);
|
||||
if (new_password.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string hash = QCryptographicHash::hash(new_password.toUtf8(), QCryptographicHash::Sha256).toHex().toStdString();
|
||||
util::create_directories(galaxy_dir, 0775);
|
||||
util::write_file(galaxy_auth_path.c_str(), hash.data(), hash.size(), O_WRONLY | O_CREAT | O_TRUNC);
|
||||
|
||||
QByteArray session_bytes(32, 0);
|
||||
QRandomGenerator::securelySeeded().fillRange(reinterpret_cast<quint32 *>(session_bytes.data()), 8);
|
||||
std::string session_token = session_bytes.toHex().toStdString();
|
||||
util::write_file(galaxy_session_path.c_str(), session_token.data(), session_token.size(), O_WRONLY | O_CREAT | O_TRUNC);
|
||||
|
||||
static constexpr char charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
std::string slug(16, '\0');
|
||||
auto *rng = QRandomGenerator::global();
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
slug[i] = charset[rng->bounded(62)];
|
||||
}
|
||||
util::write_file(galaxy_slug_path.c_str(), slug.data(), slug.size(), O_WRONLY | O_CREAT | O_TRUNC);
|
||||
|
||||
pair_galaxy->setText(tr("UNPAIR"));
|
||||
galaxy_qr_btn->setVisible(true);
|
||||
showGalaxyQR();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to unpair from Galaxy?"), tr("Unpair"), this)) {
|
||||
std::remove(galaxy_auth_path.c_str());
|
||||
std::remove(galaxy_session_path.c_str());
|
||||
std::remove(galaxy_slug_path.c_str());
|
||||
pair_galaxy->setText(tr("PAIR"));
|
||||
galaxy_qr_btn->setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
galaxy_qr_btn = new QPushButton(tr("QR"));
|
||||
galaxy_qr_btn->setFixedSize(250, 100);
|
||||
galaxy_qr_btn->setStyleSheet(R"(
|
||||
QPushButton { background-color: #393939; color: #E4E4E4; border-radius: 50px; font-size: 35px; font-weight: 500; }
|
||||
QPushButton:pressed { background-color: #4a4a4a; }
|
||||
)");
|
||||
galaxy_qr_btn->setVisible(false);
|
||||
connect(galaxy_qr_btn, &QPushButton::clicked, showGalaxyQR);
|
||||
if (QHBoxLayout *hlayout = pair_galaxy->findChild<QHBoxLayout *>()) {
|
||||
hlayout->insertWidget(3, galaxy_qr_btn);
|
||||
}
|
||||
|
||||
const bool galaxy_paired = !util::read_file(galaxy_auth_path).empty();
|
||||
pair_galaxy->setText(galaxy_paired ? tr("UNPAIR") : tr("PAIR"));
|
||||
galaxy_qr_btn->setVisible(galaxy_paired);
|
||||
addItem(pair_galaxy);
|
||||
|
||||
// offroad-only buttons
|
||||
|
||||
auto dcamBtn = new ButtonControl(tr("Driver Camera"), tr("PREVIEW"),
|
||||
tr("Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)"));
|
||||
connect(dcamBtn, &ButtonControl::clicked, [=]() { emit showDriverView(); });
|
||||
addItem(dcamBtn);
|
||||
|
||||
resetDmCalibBtn = new ButtonControl(
|
||||
tr("Reset Driver Monitoring"),
|
||||
tr("RESET"),
|
||||
tr("Clears the saved driver monitoring wheel-side calibration and any manual right-hand-driving override if the device thinks you're seated on the wrong side. "
|
||||
"Resetting will restart openpilot if the car is powered on.")
|
||||
);
|
||||
connect(resetDmCalibBtn, &ButtonControl::clicked, [&]() {
|
||||
if (!uiState()->engaged()) {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to reset driver monitoring calibration?"), tr("Reset"), this)) {
|
||||
if (!uiState()->engaged()) {
|
||||
params.remove("IsRhdDetected");
|
||||
params.remove("IsRHD");
|
||||
params.remove("IsRHDOverride");
|
||||
params.putBool("OnroadCycleRequested", true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConfirmationDialog::alert(tr("Disengage to Reset Driver Monitoring"), this);
|
||||
}
|
||||
});
|
||||
addItem(resetDmCalibBtn);
|
||||
|
||||
resetCalibBtn = new ButtonControl(tr("Reset Calibration"), tr("RESET"), "");
|
||||
connect(resetCalibBtn, &ButtonControl::showDescriptionEvent, this, &DevicePanel::updateCalibDescription);
|
||||
connect(resetCalibBtn, &ButtonControl::clicked, [&]() {
|
||||
if (!uiState()->engaged()) {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to reset calibration?"), tr("Reset"), this)) {
|
||||
// Check engaged again in case it changed while the dialog was open
|
||||
if (!uiState()->engaged()) {
|
||||
params.remove("CalibrationParams");
|
||||
params.remove("LiveTorqueParameters");
|
||||
params.remove("LiveParameters");
|
||||
params.remove("LiveParametersV2");
|
||||
params.remove("LiveDelay");
|
||||
params.putBool("OnroadCycleRequested", true);
|
||||
updateCalibDescription();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConfirmationDialog::alert(tr("Disengage to Reset Calibration"), this);
|
||||
}
|
||||
});
|
||||
addItem(resetCalibBtn);
|
||||
|
||||
auto retrainingBtn = new ButtonControl(tr("Review Training Guide"), tr("REVIEW"), tr("Review the rules, features, and limitations of openpilot"));
|
||||
connect(retrainingBtn, &ButtonControl::clicked, [=]() {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to review the training guide?"), tr("Review"), this)) {
|
||||
emit reviewTrainingGuide();
|
||||
}
|
||||
});
|
||||
addItem(retrainingBtn);
|
||||
|
||||
if (Hardware::TICI()) {
|
||||
auto regulatoryBtn = new ButtonControl(tr("Regulatory"), tr("VIEW"), "");
|
||||
connect(regulatoryBtn, &ButtonControl::clicked, [=]() {
|
||||
const std::string txt = util::read_file("../assets/offroad/fcc.html");
|
||||
ConfirmationDialog::rich(QString::fromStdString(txt), this);
|
||||
});
|
||||
addItem(regulatoryBtn);
|
||||
}
|
||||
|
||||
auto translateBtn = new ButtonControl(tr("Change Language"), tr("CHANGE"), "");
|
||||
connect(translateBtn, &ButtonControl::clicked, [=]() {
|
||||
QMap<QString, QString> langs = getSupportedLanguages();
|
||||
QString selection = MultiOptionDialog::getSelection(tr("Select a language"), langs.keys(), langs.key(uiState()->language), this);
|
||||
if (!selection.isEmpty()) {
|
||||
// put language setting, exit Qt UI, and trigger fast restart
|
||||
params.put("LanguageSetting", langs[selection].toStdString());
|
||||
qApp->exit(18);
|
||||
watchdog_kick(0);
|
||||
}
|
||||
});
|
||||
addItem(translateBtn);
|
||||
|
||||
QObject::connect(uiState()->prime_state, &PrimeState::changed, [this] (PrimeState::Type type) {
|
||||
pair_device->setVisible(type == PrimeState::PRIME_TYPE_UNPAIRED);
|
||||
});
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
for (auto btn : findChildren<ButtonControl *>()) {
|
||||
if (btn != pair_device && btn != resetCalibBtn && btn != resetDmCalibBtn) {
|
||||
btn->setEnabled(offroad);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// power buttons
|
||||
QHBoxLayout *power_layout = new QHBoxLayout();
|
||||
power_layout->setSpacing(30);
|
||||
|
||||
QPushButton *reboot_btn = new QPushButton(tr("Reboot"));
|
||||
reboot_btn->setObjectName("reboot_btn");
|
||||
power_layout->addWidget(reboot_btn);
|
||||
QObject::connect(reboot_btn, &QPushButton::clicked, this, &DevicePanel::reboot);
|
||||
|
||||
QPushButton *poweroff_btn = new QPushButton(tr("Power Off"));
|
||||
poweroff_btn->setObjectName("poweroff_btn");
|
||||
power_layout->addWidget(poweroff_btn);
|
||||
QObject::connect(poweroff_btn, &QPushButton::clicked, this, &DevicePanel::poweroff);
|
||||
|
||||
if (!Hardware::PC()) {
|
||||
connect(uiState(), &UIState::offroadTransition, poweroff_btn, &QPushButton::setVisible);
|
||||
}
|
||||
|
||||
setStyleSheet(R"(
|
||||
#reboot_btn { height: 120px; border-radius: 15px; background-color: #393939; }
|
||||
#reboot_btn:pressed { background-color: #4a4a4a; }
|
||||
#poweroff_btn { height: 120px; border-radius: 15px; background-color: #E22C2C; }
|
||||
#poweroff_btn:pressed { background-color: #FF2424; }
|
||||
)");
|
||||
addItem(power_layout);
|
||||
}
|
||||
|
||||
void DevicePanel::updateCalibDescription() {
|
||||
QString desc = tr("openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down.");
|
||||
std::string calib_bytes = params.get("CalibrationParams");
|
||||
if (!calib_bytes.empty()) {
|
||||
try {
|
||||
AlignedBuffer aligned_buf;
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(calib_bytes.data(), calib_bytes.size()));
|
||||
auto calib = cmsg.getRoot<cereal::Event>().getLiveCalibration();
|
||||
if (calib.getCalStatus() != cereal::LiveCalibrationData::Status::UNCALIBRATED) {
|
||||
double pitch = calib.getRpyCalib()[1] * (180 / M_PI);
|
||||
double yaw = calib.getRpyCalib()[2] * (180 / M_PI);
|
||||
desc += tr(" Your device is pointed %1° %2 and %3° %4.")
|
||||
.arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? tr("down") : tr("up"),
|
||||
QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? tr("left") : tr("right"));
|
||||
}
|
||||
} catch (kj::Exception) {
|
||||
qInfo() << "invalid CalibrationParams";
|
||||
}
|
||||
}
|
||||
|
||||
int lag_perc = 0;
|
||||
std::string lag_bytes = params.get("LiveDelay");
|
||||
if (!lag_bytes.empty()) {
|
||||
try {
|
||||
AlignedBuffer aligned_buf;
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(lag_bytes.data(), lag_bytes.size()));
|
||||
lag_perc = cmsg.getRoot<cereal::Event>().getLiveDelay().getCalPerc();
|
||||
} catch (kj::Exception) {
|
||||
qInfo() << "invalid LiveDelay";
|
||||
}
|
||||
}
|
||||
if (lag_perc < 100) {
|
||||
desc += tr("\n\nSteering lag calibration is %1% complete.").arg(lag_perc);
|
||||
} else {
|
||||
desc += tr("\n\nSteering lag calibration is complete.");
|
||||
}
|
||||
|
||||
std::string torque_bytes = params.get("LiveTorqueParameters");
|
||||
if (!torque_bytes.empty()) {
|
||||
try {
|
||||
AlignedBuffer aligned_buf;
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(torque_bytes.data(), torque_bytes.size()));
|
||||
auto torque = cmsg.getRoot<cereal::Event>().getLiveTorqueParameters();
|
||||
// don't add for non-torque cars
|
||||
if (torque.getUseParams()) {
|
||||
int torque_perc = torque.getCalPerc();
|
||||
if (torque_perc < 100) {
|
||||
desc += tr(" Steering torque response calibration is %1% complete.").arg(torque_perc);
|
||||
} else {
|
||||
desc += tr(" Steering torque response calibration is complete.");
|
||||
}
|
||||
}
|
||||
} catch (kj::Exception) {
|
||||
qInfo() << "invalid LiveTorqueParameters";
|
||||
}
|
||||
}
|
||||
|
||||
desc += "\n\n";
|
||||
desc += tr("openpilot is continuously calibrating, resetting is rarely required. "
|
||||
"Resetting calibration will restart openpilot if the car is powered on.");
|
||||
resetCalibBtn->setDescription(desc);
|
||||
}
|
||||
|
||||
void DevicePanel::reboot() {
|
||||
if (!uiState()->engaged()) {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to reboot?"), tr("Reboot"), this)) {
|
||||
// Check engaged again in case it changed while the dialog was open
|
||||
if (!uiState()->engaged()) {
|
||||
params.putBool("DoReboot", true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConfirmationDialog::alert(tr("Disengage to Reboot"), this);
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePanel::poweroff() {
|
||||
if (!uiState()->engaged()) {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to power off?"), tr("Power Off"), this)) {
|
||||
// Check engaged again in case it changed while the dialog was open
|
||||
if (!uiState()->engaged()) {
|
||||
params.putBool("DoShutdown", true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConfirmationDialog::alert(tr("Disengage to Power Off"), this);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsWindow::showEvent(QShowEvent *event) {
|
||||
setCurrentPanel(0);
|
||||
}
|
||||
|
||||
void SettingsWindow::hideEvent(QHideEvent *event) {
|
||||
closePanel();
|
||||
closeSubPanel();
|
||||
|
||||
panelOpen = false;
|
||||
subPanelOpen = false;
|
||||
subSubPanelOpen = false;
|
||||
subSubSubPanelOpen = false;
|
||||
|
||||
updateStarPilotToggles();
|
||||
}
|
||||
|
||||
void SettingsWindow::setCurrentPanel(int index, const QString ¶m) {
|
||||
if (!param.isEmpty()) {
|
||||
// Check if param ends with "Panel" to determine if it's a panel name
|
||||
if (param.endsWith("Panel")) {
|
||||
QString panelName = param;
|
||||
panelName.chop(5); // Remove "Panel" suffix
|
||||
|
||||
// Find the panel by name
|
||||
for (int i = 0; i < nav_btns->buttons().size(); i++) {
|
||||
if (nav_btns->buttons()[i]->text() == tr(panelName.toStdString().c_str())) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emit expandToggleDescription(param);
|
||||
emit scrollToToggle(param);
|
||||
}
|
||||
}
|
||||
|
||||
panel_widget->setCurrentIndex(index);
|
||||
nav_btns->buttons()[index]->setChecked(true);
|
||||
}
|
||||
|
||||
SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
|
||||
|
||||
// setup two main layouts
|
||||
sidebar_widget = new QWidget;
|
||||
QVBoxLayout *sidebar_layout = new QVBoxLayout(sidebar_widget);
|
||||
panel_widget = new QStackedWidget();
|
||||
|
||||
// close button
|
||||
QPushButton *close_btn = new QPushButton(tr("← Back"));
|
||||
close_btn->setStyleSheet(R"(
|
||||
QPushButton {
|
||||
font-size: 50px;
|
||||
border-radius: 25px;
|
||||
background-color: #292929;
|
||||
font-weight: 500;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #ADADAD;
|
||||
}
|
||||
)");
|
||||
close_btn->setFixedSize(300, 125);
|
||||
sidebar_layout->addSpacing(10);
|
||||
sidebar_layout->addWidget(close_btn, 0, Qt::AlignRight);
|
||||
QObject::connect(close_btn, &QPushButton::clicked, [this]() {
|
||||
if (subSubSubPanelOpen) {
|
||||
closeSubSubSubPanel();
|
||||
subSubSubPanelOpen = false;
|
||||
} else if (subSubPanelOpen) {
|
||||
closeSubSubPanel();
|
||||
subSubPanelOpen = false;
|
||||
} else if (subPanelOpen) {
|
||||
closeSubPanel();
|
||||
subPanelOpen = false;
|
||||
} else if (panelOpen) {
|
||||
closePanel();
|
||||
panelOpen = false;
|
||||
} else {
|
||||
closeSettings();
|
||||
}
|
||||
});
|
||||
|
||||
// setup panels
|
||||
DevicePanel *device = new DevicePanel(this);
|
||||
QObject::connect(device, &DevicePanel::reviewTrainingGuide, this, &SettingsWindow::reviewTrainingGuide);
|
||||
QObject::connect(device, &DevicePanel::showDriverView, this, &SettingsWindow::showDriverView);
|
||||
|
||||
TogglesPanel *toggles = new TogglesPanel(this);
|
||||
QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription);
|
||||
QObject::connect(this, &SettingsWindow::scrollToToggle, toggles, &TogglesPanel::scrollToToggle);
|
||||
|
||||
auto networking = new Networking(this);
|
||||
QObject::connect(uiState()->prime_state, &PrimeState::changed, networking, &Networking::setPrimeType);
|
||||
|
||||
QObject::connect(toggles, &TogglesPanel::updateMetric, this, &SettingsWindow::updateMetric);
|
||||
|
||||
StarPilotSettingsWindow *starpilotSettingsWindow = new StarPilotSettingsWindow(this);
|
||||
QObject::connect(starpilotSettingsWindow, &StarPilotSettingsWindow::openPanel, [this]() {panelOpen=true;});
|
||||
QObject::connect(starpilotSettingsWindow, &StarPilotSettingsWindow::openSubPanel, [this]() {subPanelOpen=true;});
|
||||
QObject::connect(starpilotSettingsWindow, &StarPilotSettingsWindow::openSubSubPanel, [this]() {subSubPanelOpen=true;});
|
||||
QObject::connect(starpilotSettingsWindow, &StarPilotSettingsWindow::openSubSubSubPanel, [this]() {subSubSubPanelOpen=true;});
|
||||
QObject::connect(starpilotSettingsWindow, &StarPilotSettingsWindow::tuningLevelChanged, this, &SettingsWindow::updateDeveloperToggle);
|
||||
|
||||
DeveloperPanel *developerPanel = new DeveloperPanel(this);
|
||||
QObject::connect(developerPanel, &DeveloperPanel::openSubPanel, [this]() {subPanelOpen=true;});
|
||||
QObject::connect(developerPanel, &DeveloperPanel::openSubSubPanel, [this]() {subSubPanelOpen=true;});
|
||||
QObject::connect(developerPanel, &DeveloperPanel::showAllTogglesChanged, [this]() {
|
||||
updateDeveloperToggle(params.getInt("TuningLevel"));
|
||||
});
|
||||
QObject::connect(toggles, &TogglesPanel::simpleModeChanged, [this](bool enabled) {
|
||||
updateDeveloperToggle(params.getInt("TuningLevel"));
|
||||
if (enabled && panel_widget->currentIndex() < nav_btns->buttons().size() &&
|
||||
nav_btns->buttons()[panel_widget->currentIndex()]->text() == tr("StarPilot")) {
|
||||
setCurrentPanel(2);
|
||||
}
|
||||
});
|
||||
|
||||
QList<QPair<QString, QWidget *>> panels = {
|
||||
{tr("Device"), device},
|
||||
{tr("Network"), networking},
|
||||
{tr("Toggles"), toggles},
|
||||
{tr("Software"), new SoftwarePanel(this)},
|
||||
{tr("Developer"), developerPanel},
|
||||
{tr("StarPilot"), starpilotSettingsWindow},
|
||||
};
|
||||
|
||||
nav_btns = new QButtonGroup(this);
|
||||
for (auto &[name, panel] : panels) {
|
||||
QPushButton *btn = new QPushButton(name);
|
||||
btn->setCheckable(true);
|
||||
btn->setChecked(nav_btns->buttons().size() == 0);
|
||||
btn->setStyleSheet(R"(
|
||||
QPushButton {
|
||||
color: grey;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 65px;
|
||||
font-weight: 500;
|
||||
}
|
||||
QPushButton:checked {
|
||||
color: white;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
color: #ADADAD;
|
||||
}
|
||||
)");
|
||||
btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
nav_btns->addButton(btn);
|
||||
sidebar_layout->addWidget(btn, 0, Qt::AlignRight);
|
||||
|
||||
const int lr_margin = name != tr("Network") ? 50 : 0; // Network panel handles its own margins
|
||||
panel->setContentsMargins(lr_margin, 25, lr_margin, 25);
|
||||
|
||||
ScrollView *panel_frame = new ScrollView(panel, this);
|
||||
panel_widget->addWidget(panel_frame);
|
||||
|
||||
QObject::connect(btn, &QPushButton::clicked, [=, w = panel_frame]() {
|
||||
if (w->widget() == starpilotSettingsWindow) {
|
||||
bool tuningLevelConfirmed = params.getBool("TuningLevelConfirmed");
|
||||
|
||||
if (!tuningLevelConfirmed) {
|
||||
int starpilotHours = QJsonDocument::fromJson(QString::fromStdString(params.get("StarPilotStats")).toUtf8()).object().value("StarPilotSeconds").toInt() / (60 * 60);
|
||||
int openpilotHours = params.getInt("KonikMinutes") / 60 + params.getInt("openpilotMinutes") / 60;
|
||||
|
||||
if (starpilotHours < 1 && openpilotHours < 100) {
|
||||
if (openpilotHours < 10) {
|
||||
if (ConfirmationDialog::alert(tr("Welcome to StarPilot! Since you're new to openpilot, the \"Minimal\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 0);
|
||||
}
|
||||
} else {
|
||||
if (ConfirmationDialog::alert(tr("Welcome to StarPilot! Since you're new to StarPilot, the \"Minimal\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 0);
|
||||
}
|
||||
}
|
||||
} else if (starpilotHours < 50 && openpilotHours < 100) {
|
||||
if (ConfirmationDialog::alert(tr("Since you're fairly new to StarPilot, the \"Minimal\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 0);
|
||||
}
|
||||
} else if (starpilotHours < 100) {
|
||||
if (openpilotHours >= 100) {
|
||||
if (ConfirmationDialog::alert(tr("Since you're experienced with openpilot, the \"Standard\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 1);
|
||||
}
|
||||
} else {
|
||||
if (ConfirmationDialog::alert(tr("Since you're experienced with StarPilot, the \"Standard\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 1);
|
||||
}
|
||||
}
|
||||
} else if (starpilotHours >= 100) {
|
||||
if (ConfirmationDialog::alert(tr("Since you're very experienced with StarPilot, the \"Advanced\" toggle preset has been applied, but you can change this at any time via the \"Tuning Level\" button!"), this, true)) {
|
||||
params.putBool("TuningLevelConfirmed", true);
|
||||
params.putInt("TuningLevel", 2);
|
||||
}
|
||||
}
|
||||
updateTuningLevel();
|
||||
}
|
||||
}
|
||||
|
||||
if (subSubSubPanelOpen) {
|
||||
closeSubSubSubPanel();
|
||||
subSubSubPanelOpen = false;
|
||||
}
|
||||
if (subSubPanelOpen) {
|
||||
closeSubSubPanel();
|
||||
subSubPanelOpen = false;
|
||||
}
|
||||
if (subPanelOpen) {
|
||||
closeSubPanel();
|
||||
subPanelOpen = false;
|
||||
}
|
||||
if (panelOpen) {
|
||||
closePanel();
|
||||
panelOpen = false;
|
||||
}
|
||||
btn->setChecked(true);
|
||||
panel_widget->setCurrentWidget(w);
|
||||
});
|
||||
}
|
||||
sidebar_layout->setContentsMargins(50, 50, 100, 50);
|
||||
|
||||
// main settings layout, sidebar + main panel
|
||||
QHBoxLayout *main_layout = new QHBoxLayout(this);
|
||||
|
||||
sidebar_widget->setFixedWidth(500);
|
||||
main_layout->addWidget(sidebar_widget);
|
||||
main_layout->addWidget(panel_widget);
|
||||
|
||||
setStyleSheet(R"(
|
||||
* {
|
||||
color: white;
|
||||
font-size: 50px;
|
||||
}
|
||||
SettingsWindow {
|
||||
background-color: black;
|
||||
}
|
||||
QStackedWidget, ScrollView {
|
||||
background-color: #292929;
|
||||
border-radius: 30px;
|
||||
}
|
||||
)");
|
||||
|
||||
updateDeveloperToggle(params.getInt("TuningLevel"));
|
||||
}
|
||||
|
||||
void SettingsWindow::updateDeveloperToggle(int tuningLevel) {
|
||||
for (QAbstractButton *btn : nav_btns->buttons()) {
|
||||
if (btn->text() == tr("Developer")) {
|
||||
btn->setVisible(tuningLevel >= 3 || params.getBool("ShowAllToggles"));
|
||||
} else if (btn->text() == tr("StarPilot")) {
|
||||
btn->setVisible(!params.getBool("SimpleMode"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QStackedWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/qt/widgets/controls.h"
|
||||
|
||||
// ********** settings window + top-level panels **********
|
||||
class SettingsWindow : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsWindow(QWidget *parent = 0);
|
||||
void setCurrentPanel(int index, const QString ¶m = "");
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
void hideEvent(QHideEvent *event) override;
|
||||
|
||||
signals:
|
||||
void closeSettings();
|
||||
void reviewTrainingGuide();
|
||||
void showDriverView();
|
||||
void expandToggleDescription(const QString ¶m);
|
||||
void scrollToToggle(const QString ¶m);
|
||||
|
||||
void closePanel();
|
||||
void closeSubPanel();
|
||||
void closeSubSubPanel();
|
||||
void closeSubSubSubPanel();
|
||||
void updateMetric(bool isMetric, bool bootRun=false);
|
||||
void updateTuningLevel();
|
||||
|
||||
private:
|
||||
QPushButton *sidebar_alert_widget;
|
||||
QWidget *sidebar_widget;
|
||||
QButtonGroup *nav_btns;
|
||||
QStackedWidget *panel_widget;
|
||||
|
||||
void updateDeveloperToggle(int tuningLevel);
|
||||
|
||||
bool panelOpen;
|
||||
bool subPanelOpen;
|
||||
bool subSubPanelOpen;
|
||||
bool subSubSubPanelOpen;
|
||||
|
||||
Params params;
|
||||
};
|
||||
|
||||
class GalaxyQRPopup : public DialogBase {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GalaxyQRPopup(const QString &url, QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override {
|
||||
reject();
|
||||
DialogBase::mousePressEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
class DevicePanel : public ListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DevicePanel(SettingsWindow *parent);
|
||||
|
||||
signals:
|
||||
void reviewTrainingGuide();
|
||||
void showDriverView();
|
||||
|
||||
private slots:
|
||||
void poweroff();
|
||||
void reboot();
|
||||
void updateCalibDescription();
|
||||
|
||||
private:
|
||||
Params params;
|
||||
ButtonControl *pair_device;
|
||||
ButtonControl *pair_galaxy;
|
||||
QPushButton *galaxy_qr_btn;
|
||||
ButtonControl *resetCalibBtn;
|
||||
ButtonControl *resetDmCalibBtn;
|
||||
};
|
||||
|
||||
class TogglesPanel : public ListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TogglesPanel(SettingsWindow *parent);
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
signals:
|
||||
void updateMetric(bool metric, bool bootRun=false);
|
||||
void simpleModeChanged(bool enabled);
|
||||
|
||||
public slots:
|
||||
void expandToggleDescription(const QString ¶m);
|
||||
void scrollToToggle(const QString ¶m);
|
||||
|
||||
private slots:
|
||||
void updateState(const UIState &s);
|
||||
|
||||
private:
|
||||
Params params;
|
||||
std::map<std::string, ParamControl*> toggles;
|
||||
ButtonParamControl *long_personality_setting;
|
||||
|
||||
void syncRhdToggle();
|
||||
void updateToggles();
|
||||
};
|
||||
|
||||
class SoftwarePanel : public ListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SoftwarePanel(QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void updateLabels();
|
||||
void checkForUpdates();
|
||||
|
||||
bool is_onroad = false;
|
||||
|
||||
QLabel *onroadLbl;
|
||||
LabelControl *versionLbl;
|
||||
ButtonControl *installBtn;
|
||||
ButtonControl *downloadBtn;
|
||||
ButtonControl *targetBranchBtn;
|
||||
|
||||
Params params;
|
||||
ParamWatcher *fs_watch;
|
||||
};
|
||||
@@ -1,202 +0,0 @@
|
||||
#include "selfdrive/ui/qt/offroad/settings.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/util.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
#include "selfdrive/ui/qt/widgets/controls.h"
|
||||
#include "selfdrive/ui/qt/widgets/input.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
|
||||
void SoftwarePanel::checkForUpdates() {
|
||||
std::system("pkill -SIGUSR1 -f system.updated.updated");
|
||||
}
|
||||
|
||||
SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
|
||||
onroadLbl = new QLabel(tr("Updates are only downloaded while the car is off or in park."));
|
||||
onroadLbl->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; padding-top: 30px; padding-bottom: 30px;");
|
||||
addItem(onroadLbl);
|
||||
|
||||
// current version
|
||||
versionLbl = new LabelControl(tr("Current Version"), "");
|
||||
addItem(versionLbl);
|
||||
|
||||
// automatic updates toggle
|
||||
ParamControl *automaticUpdatesToggle = new ParamControl("AutomaticUpdates", tr("Automatically Update StarPilot"),
|
||||
tr("Automatically update StarPilot when the vehicle is parked with an active internet connection."), "");
|
||||
automaticUpdatesToggle->setVisible(true);
|
||||
addItem(automaticUpdatesToggle);
|
||||
|
||||
// download update btn
|
||||
downloadBtn = new ButtonControl(tr("Download"), tr("CHECK"));
|
||||
connect(downloadBtn, &ButtonControl::clicked, [=]() {
|
||||
downloadBtn->setEnabled(false);
|
||||
if (downloadBtn->text() == tr("CHECK")) {
|
||||
checkForUpdates();
|
||||
} else {
|
||||
std::system("pkill -SIGHUP -f system.updated.updated");
|
||||
}
|
||||
starpilotUIState()->params_memory.putBool("ManualUpdateInitiated", true);
|
||||
});
|
||||
addItem(downloadBtn);
|
||||
|
||||
// install update btn
|
||||
installBtn = new ButtonControl(tr("Install Update"), tr("INSTALL"));
|
||||
connect(installBtn, &ButtonControl::clicked, [=]() {
|
||||
installBtn->setEnabled(false);
|
||||
params.putBool("DoReboot", true);
|
||||
});
|
||||
addItem(installBtn);
|
||||
|
||||
// branch selecting
|
||||
targetBranchBtn = new ButtonControl(tr("Target Branch"), tr("SELECT"));
|
||||
connect(targetBranchBtn, &ButtonControl::clicked, [=]() {
|
||||
auto current = params.get("GitBranch");
|
||||
QStringList branches = QString::fromStdString(params.get("UpdaterAvailableBranches")).split(",");
|
||||
if (!isFrogsGoMoo()) {
|
||||
branches.removeAll("StarPilot-Vetting");
|
||||
branches.removeAll("MAKE-PRS-HERE");
|
||||
}
|
||||
for (QString b : {current.c_str(), "devel-staging", "devel", "nightly", "nightly-dev", "master"}) {
|
||||
auto i = branches.indexOf(b);
|
||||
if (i >= 0) {
|
||||
branches.removeAt(i);
|
||||
branches.insert(0, b);
|
||||
}
|
||||
}
|
||||
|
||||
QString cur = QString::fromStdString(params.get("UpdaterTargetBranch"));
|
||||
QString selection = MultiOptionDialog::getSelection(tr("Select a branch"), branches, cur, this);
|
||||
if (!selection.isEmpty()) {
|
||||
params.put("UpdaterTargetBranch", selection.toStdString());
|
||||
targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch")));
|
||||
checkForUpdates();
|
||||
|
||||
if (selection != cur) {
|
||||
if (StarPilotConfirmationDialog::yesorno(tr("This branch must be downloaded before switching. Would you like to download it now?"), this)) {
|
||||
std::system("pkill -SIGHUP -f system.updated.updated");
|
||||
starpilotUIState()->params_memory.putBool("ManualUpdateInitiated", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addItem(targetBranchBtn);
|
||||
|
||||
// uninstall button
|
||||
auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL"));
|
||||
connect(uninstallBtn, &ButtonControl::clicked, [&]() {
|
||||
if (ConfirmationDialog::confirm(tr("Are you sure you want to uninstall?"), tr("Uninstall"), this)) {
|
||||
if (StarPilotConfirmationDialog::yesorno(tr("Do you want to perform a full factory reset? All saved assets and settings will be permanently deleted!"), this)) {
|
||||
if (StarPilotConfirmationDialog::yesorno(tr("This is a complete factory reset and cannot be undone. Are you absolutely sure you want to continue?"), this)) {
|
||||
Params().clearAll(ParamKeyFlag::ALL);
|
||||
}
|
||||
}
|
||||
params.putBool("DoUninstall", true);
|
||||
}
|
||||
});
|
||||
addItem(uninstallBtn);
|
||||
|
||||
// error log button
|
||||
auto errorLogBtn = new ButtonControl(tr("Error Log"), tr("VIEW"), tr("View the error log for openpilot crashes."));
|
||||
connect(errorLogBtn, &ButtonControl::clicked, [=]() {
|
||||
std::string txt = util::read_file("/data/error_logs/error.txt");
|
||||
ConfirmationDialog::rich(QString::fromStdString(txt), this);
|
||||
});
|
||||
addItem(errorLogBtn);
|
||||
|
||||
fs_watch = new ParamWatcher(this);
|
||||
QObject::connect(fs_watch, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) {
|
||||
updateLabels();
|
||||
});
|
||||
|
||||
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
is_onroad = !offroad;
|
||||
updateLabels();
|
||||
});
|
||||
|
||||
updateLabels();
|
||||
}
|
||||
|
||||
void SoftwarePanel::showEvent(QShowEvent *event) {
|
||||
// nice for testing on PC
|
||||
installBtn->setEnabled(true);
|
||||
|
||||
updateLabels();
|
||||
|
||||
StarPilotUIState &fs = *starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
|
||||
if (starpilot_scene.online && params.get("UpdaterState") == "idle") {
|
||||
checkForUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwarePanel::updateLabels() {
|
||||
StarPilotUIState &fs = *starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
|
||||
bool parked = starpilot_scene.parked || isFrogsGoMoo();
|
||||
|
||||
// add these back in case the files got removed
|
||||
fs_watch->addParam("LastUpdateTime");
|
||||
fs_watch->addParam("UpdateFailedCount");
|
||||
fs_watch->addParam("UpdaterState");
|
||||
fs_watch->addParam("UpdateAvailable");
|
||||
|
||||
if (!isVisible()) {
|
||||
starpilot_scene.downloading_update = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// updater only runs offroad or when parked
|
||||
onroadLbl->setVisible(is_onroad && !parked);
|
||||
downloadBtn->setVisible(!is_onroad || parked);
|
||||
|
||||
// download update
|
||||
QString updater_state = QString::fromStdString(params.get("UpdaterState"));
|
||||
bool failed = std::atoi(params.get("UpdateFailedCount").c_str()) > 0;
|
||||
if (updater_state != "idle") {
|
||||
downloadBtn->setEnabled(false);
|
||||
downloadBtn->setValue(updater_state);
|
||||
|
||||
starpilot_scene.downloading_update = true;
|
||||
} else {
|
||||
if (failed) {
|
||||
downloadBtn->setText(tr("CHECK"));
|
||||
downloadBtn->setValue(tr("failed to check for update"));
|
||||
} else if (params.getBool("UpdaterFetchAvailable")) {
|
||||
downloadBtn->setText(tr("DOWNLOAD"));
|
||||
downloadBtn->setValue(tr("update available"));
|
||||
} else {
|
||||
QString lastUpdate = tr("never");
|
||||
auto tm = params.get("LastUpdateTime");
|
||||
if (!tm.empty()) {
|
||||
lastUpdate = timeAgo(QDateTime::fromString(QString::fromStdString(tm + "Z"), Qt::ISODate));
|
||||
}
|
||||
downloadBtn->setText(tr("CHECK"));
|
||||
downloadBtn->setValue(tr("up to date, last checked %1").arg(lastUpdate));
|
||||
}
|
||||
downloadBtn->setEnabled(true);
|
||||
|
||||
starpilot_scene.downloading_update = false;
|
||||
}
|
||||
targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch")));
|
||||
|
||||
// current + new versions
|
||||
versionLbl->setText(formatStarPilotDisplayVersionDescription(QString::fromStdString(params.get("UpdaterCurrentDescription"))));
|
||||
versionLbl->setDescription(QString::fromStdString(params.get("UpdaterCurrentReleaseNotes")));
|
||||
|
||||
installBtn->setVisible((!is_onroad || parked) && params.getBool("UpdateAvailable"));
|
||||
installBtn->setValue(formatStarPilotDisplayVersionDescription(QString::fromStdString(params.get("UpdaterNewDescription"))));
|
||||
installBtn->setDescription(QString::fromStdString(params.get("UpdaterNewReleaseNotes")));
|
||||
|
||||
update();
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/alerts.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <map>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
void OnroadAlerts::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
Alert a = getAlert(*(s.sm), *(fs.sm), s.scene.started_frame);
|
||||
if (!alert.equal(a)) {
|
||||
// Hide only incoming NORMAL alerts. Keep userPrompt/critical visible.
|
||||
if (a.status == cereal::SelfdriveState::AlertStatus::NORMAL && starpilot_toggles.value("hide_alerts").toBool()) {
|
||||
clear();
|
||||
} else {
|
||||
alert = a;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
sidebarsOpen = fs.starpilot_scene.sidebars_open;
|
||||
}
|
||||
|
||||
void OnroadAlerts::clear() {
|
||||
alert = {};
|
||||
update();
|
||||
|
||||
alertHeight = 0;
|
||||
}
|
||||
|
||||
OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, const SubMaster &fpsm, uint64_t started_frame) {
|
||||
const cereal::SelfdriveState::Reader &ss = sm["selfdriveState"].getSelfdriveState();
|
||||
const uint64_t selfdrive_frame = sm.rcv_frame("selfdriveState");
|
||||
|
||||
const cereal::StarPilotSelfdriveState::Reader &fpss = fpsm["starpilotSelfdriveState"].getStarpilotSelfdriveState();
|
||||
const bool starpilot_alert_received = fpsm.rcv_frame("starpilotSelfdriveState") > 0;
|
||||
|
||||
Alert a = {};
|
||||
static QString crash_log_path = "/data/error_logs/error.txt";
|
||||
if (QFile::exists(crash_log_path)) {
|
||||
if (starpilot_toggles.value("random_events").toBool()) {
|
||||
a = {tr("openpilot crashed 💩"),
|
||||
tr("Please post the \"Error Log\" in the StarPilot Discord!"),
|
||||
"openpilotCrashedRandomEvent",
|
||||
cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::CRITICAL};
|
||||
} else {
|
||||
a = {tr("openpilot crashed"),
|
||||
tr("Please post the \"Error Log\" in the StarPilot Discord!"),
|
||||
"openpilotCrashed",
|
||||
cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::CRITICAL};
|
||||
}
|
||||
return a;
|
||||
} else if (selfdrive_frame >= started_frame) { // Don't get old alert.
|
||||
a = {ss.getAlertText1().cStr(), ss.getAlertText2().cStr(),
|
||||
ss.getAlertType().cStr(), ss.getAlertSize(), ss.getAlertStatus()};
|
||||
|
||||
if (a.size == cereal::SelfdriveState::AlertSize::NONE && starpilot_alert_received) {
|
||||
a = {fpss.getAlertText1().cStr(), fpss.getAlertText2().cStr(),
|
||||
fpss.getAlertType().cStr(), static_cast<cereal::SelfdriveState::AlertSize>(fpss.getAlertSize()), static_cast<cereal::SelfdriveState::AlertStatus>(fpss.getAlertStatus())};
|
||||
}
|
||||
}
|
||||
|
||||
if (!sm.updated("selfdriveState") && (sm.frame - started_frame) > 5 * UI_FREQ && !starpilot_toggles.value("force_onroad").toBool()) {
|
||||
const int SELFDRIVE_STATE_TIMEOUT = 5;
|
||||
const int ss_missing = (nanos_since_boot() - sm.rcv_time("selfdriveState")) / 1e9;
|
||||
|
||||
// Handle selfdrive timeout
|
||||
if (selfdrive_frame < started_frame) {
|
||||
// car is started, but selfdriveState hasn't been seen at all
|
||||
a = {tr("openpilot Unavailable"), tr("Waiting to start"),
|
||||
"selfdriveWaiting", cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::NORMAL};
|
||||
} else if (ss_missing > SELFDRIVE_STATE_TIMEOUT && !Hardware::PC()) {
|
||||
// car is started, but selfdrive is lagging or died
|
||||
if (ss.getEnabled() && (ss_missing - SELFDRIVE_STATE_TIMEOUT) < 10) {
|
||||
a = {tr("TAKE CONTROL IMMEDIATELY"), tr("System Unresponsive"),
|
||||
"selfdriveUnresponsive", cereal::SelfdriveState::AlertSize::FULL,
|
||||
cereal::SelfdriveState::AlertStatus::CRITICAL};
|
||||
} else {
|
||||
a = {tr("System Unresponsive"), tr("Reboot Device"),
|
||||
"selfdriveUnresponsivePermanent", cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::NORMAL};
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
||||
if (alert.size == cereal::SelfdriveState::AlertSize::NONE) {
|
||||
alertHeight = 0;
|
||||
return;
|
||||
}
|
||||
static std::map<cereal::SelfdriveState::AlertSize, const int> alert_heights = {
|
||||
{cereal::SelfdriveState::AlertSize::SMALL, 271},
|
||||
{cereal::SelfdriveState::AlertSize::MID, 420},
|
||||
{cereal::SelfdriveState::AlertSize::FULL, height()},
|
||||
};
|
||||
alertHeight = alert_heights[alert.size];
|
||||
int h = alertHeight;
|
||||
|
||||
int margin = 40;
|
||||
int radius = 30;
|
||||
if (alert.size == cereal::SelfdriveState::AlertSize::FULL) {
|
||||
margin = 0;
|
||||
radius = 0;
|
||||
}
|
||||
alertHeight -= margin;
|
||||
QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2);
|
||||
|
||||
QPainter p(this);
|
||||
const bool simple_mode = starpilot_toggles.value("simple_mode").toBool();
|
||||
QColor alert_color;
|
||||
if (simple_mode) {
|
||||
cereal::SelfdriveState::AlertStatus status = alert.status;
|
||||
if (status == static_cast<cereal::SelfdriveState::AlertStatus>(cereal::StarPilotSelfdriveState::AlertStatus::STARPILOT)) {
|
||||
status = cereal::SelfdriveState::AlertStatus::NORMAL;
|
||||
}
|
||||
alert_color = alert_colors.value(status, alert_colors.value(cereal::SelfdriveState::AlertStatus::NORMAL));
|
||||
} else {
|
||||
alert_color = starpilot_alert_colors.value(static_cast<cereal::StarPilotSelfdriveState::AlertStatus>(alert.status),
|
||||
alert_colors.value(cereal::SelfdriveState::AlertStatus::NORMAL));
|
||||
}
|
||||
|
||||
// draw background + gradient
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
p.setBrush(QBrush(alert_color));
|
||||
p.drawRoundedRect(r, radius, radius);
|
||||
|
||||
QLinearGradient g(0, r.y(), 0, r.bottom());
|
||||
g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05));
|
||||
g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35));
|
||||
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
|
||||
p.setBrush(QBrush(g));
|
||||
p.drawRoundedRect(r, radius, radius);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
|
||||
// text
|
||||
const QPoint c = r.center();
|
||||
p.setPen(QColor(0xff, 0xff, 0xff));
|
||||
p.setRenderHint(QPainter::TextAntialiasing);
|
||||
if (alert.size == cereal::SelfdriveState::AlertSize::SMALL) {
|
||||
bool long_alert1 = alert.text1.length() > 40;
|
||||
p.setFont(InterFont(long_alert1 && sidebarsOpen ? 64 : 74, QFont::DemiBold));
|
||||
p.drawText(r, Qt::AlignCenter, alert.text1);
|
||||
} else if (alert.size == cereal::SelfdriveState::AlertSize::MID) {
|
||||
bool long_alert1 = alert.text1.length() > 30;
|
||||
p.setFont(InterFont(long_alert1 && sidebarsOpen ? 78 : 88, QFont::Bold));
|
||||
p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1);
|
||||
bool long_alert2 = alert.text2.length() > 40;
|
||||
p.setFont(InterFont(long_alert2 && sidebarsOpen ? 56 : 66));
|
||||
p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2);
|
||||
} else if (alert.size == cereal::SelfdriveState::AlertSize::FULL) {
|
||||
bool l = alert.text1.length() > 15;
|
||||
p.setFont(InterFont(l ? 132 : 177, QFont::Bold));
|
||||
p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1);
|
||||
p.setFont(InterFont(88));
|
||||
p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, alert.text2);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class OnroadAlerts : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OnroadAlerts(QWidget *parent = 0) : QWidget(parent) {}
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
void clear();
|
||||
|
||||
int alertHeight;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
protected:
|
||||
struct Alert {
|
||||
QString text1;
|
||||
QString text2;
|
||||
QString type;
|
||||
cereal::SelfdriveState::AlertSize size;
|
||||
cereal::SelfdriveState::AlertStatus status;
|
||||
|
||||
bool equal(const Alert &other) const {
|
||||
return text1 == other.text1 && text2 == other.text2 && type == other.type &&
|
||||
size == other.size && status == other.status;
|
||||
}
|
||||
};
|
||||
|
||||
const QMap<cereal::SelfdriveState::AlertStatus, QColor> alert_colors = {
|
||||
{cereal::SelfdriveState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
|
||||
{cereal::SelfdriveState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
|
||||
{cereal::SelfdriveState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
OnroadAlerts::Alert getAlert(const SubMaster &sm, const SubMaster &fpsm, uint64_t started_frame);
|
||||
|
||||
QColor bg;
|
||||
Alert alert = {};
|
||||
|
||||
bool sidebarsOpen;
|
||||
|
||||
const QMap<cereal::StarPilotSelfdriveState::AlertStatus, QColor> starpilot_alert_colors = {
|
||||
{cereal::StarPilotSelfdriveState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
|
||||
{cereal::StarPilotSelfdriveState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
|
||||
{cereal::StarPilotSelfdriveState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
|
||||
{cereal::StarPilotSelfdriveState::AlertStatus::STARPILOT, QColor(0x17, 0x86, 0x44, 0xf1)},
|
||||
};
|
||||
};
|
||||
@@ -1,281 +0,0 @@
|
||||
|
||||
#include "selfdrive/ui/qt/onroad/annotated_camera.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/swaglog.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
constexpr int CAMERA_VIEW_NONE = 4;
|
||||
|
||||
// Window that shows camera view and variety of info drawn on top
|
||||
AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget *parent)
|
||||
: fps_filter(UI_FREQ, 3, 1. / UI_FREQ), CameraWidget("camerad", type, parent) {
|
||||
pm = std::make_unique<PubMaster>(std::vector<const char*>{"uiDebug"});
|
||||
|
||||
main_layout = new QVBoxLayout(this);
|
||||
main_layout->setMargin(UI_BORDER_SIZE);
|
||||
main_layout->setSpacing(0);
|
||||
|
||||
experimental_btn = new ExperimentalButton(this);
|
||||
main_layout->addWidget(experimental_btn, 0, Qt::AlignTop | Qt::AlignRight);
|
||||
|
||||
personality_btn = new DrivingPersonalityButton(this);
|
||||
personality_btn->setVisible(false);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(favorite_btns.size()); ++i) {
|
||||
favorite_btns[i] = new FavoriteButton(i, this);
|
||||
favorite_btns[i]->setVisible(false);
|
||||
}
|
||||
|
||||
screen_recorder = new ScreenRecorder(this);
|
||||
screen_recorder->setVisible(false);
|
||||
}
|
||||
|
||||
bool AnnotatedCameraWidget::handleHudPress(const QPoint &pos) {
|
||||
return hud.handleNavigationPress(pos);
|
||||
}
|
||||
|
||||
bool AnnotatedCameraWidget::handleHudRelease(const QPoint &pos) {
|
||||
return hud.handleNavigationRelease(pos);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
// update engageability/experimental mode button
|
||||
experimental_btn->updateState(s, fs);
|
||||
dmon.updateState(s);
|
||||
|
||||
const SubMaster &sm = *(s.sm);
|
||||
|
||||
const cereal::CarState::Reader &carState = sm["carState"].getCarState();
|
||||
|
||||
static Params params;
|
||||
const bool hide_steering_wheel = starpilot_toggles.value("hide_steering_wheel").toBool() || params.getBool("HideSteeringWheel");
|
||||
experimental_btn->setVisible(!hide_steering_wheel);
|
||||
|
||||
const QPoint experimental_button_position = hide_steering_wheel
|
||||
? QPoint(width() - UI_BORDER_SIZE - btn_size, UI_BORDER_SIZE)
|
||||
: QPoint(experimental_btn->x(), experimental_btn->y());
|
||||
starpilot_nvg->experimentalButtonPosition = experimental_button_position;
|
||||
|
||||
std::vector<FavoriteButton*> visible_favorite_btns;
|
||||
const bool favorites_anchor_ready = starpilot_nvg->dmIconPosition != QPoint(0, 0) && !starpilot_nvg->hideBottomIcons;
|
||||
for (FavoriteButton *favorite_btn : favorite_btns) {
|
||||
favorite_btn->updateState();
|
||||
if (favorites_anchor_ready && favorite_btn->shouldShow()) {
|
||||
visible_favorite_btns.push_back(favorite_btn);
|
||||
} else {
|
||||
favorite_btn->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
const bool onroad_distance_btn_enabled = favorites_anchor_ready && starpilot_toggles.value("onroad_distance_button").toBool();
|
||||
const int gap = UI_BORDER_SIZE / 2;
|
||||
int controls_width = 0;
|
||||
if (!visible_favorite_btns.empty()) {
|
||||
controls_width = visible_favorite_btns.size() * btn_size + (visible_favorite_btns.size() - 1) * gap;
|
||||
}
|
||||
if (onroad_distance_btn_enabled) {
|
||||
controls_width += (controls_width > 0 ? gap : 0) + personality_btn->width();
|
||||
}
|
||||
dmon.onroad_controls_width = controls_width;
|
||||
|
||||
const int controls_y = favorites_anchor_ready
|
||||
? std::clamp(starpilot_nvg->dmIconPosition.y() - (btn_size / 2), UI_BORDER_SIZE, height() - UI_BORDER_SIZE - btn_size)
|
||||
: 0;
|
||||
int cursor_x = starpilot_nvg->rightHandDM ? width() - UI_BORDER_SIZE : UI_BORDER_SIZE;
|
||||
|
||||
personality_btn->setVisible(onroad_distance_btn_enabled);
|
||||
if (onroad_distance_btn_enabled) {
|
||||
const int personality_x = starpilot_nvg->rightHandDM ? cursor_x - personality_btn->width() : cursor_x;
|
||||
personality_btn->move(personality_x, controls_y);
|
||||
personality_btn->updateState(s, fs);
|
||||
cursor_x += starpilot_nvg->rightHandDM ? -(personality_btn->width() + gap) : personality_btn->width() + gap;
|
||||
}
|
||||
|
||||
for (FavoriteButton *favorite_btn : visible_favorite_btns) {
|
||||
const int favorite_x = starpilot_nvg->rightHandDM ? cursor_x - favorite_btn->width() : cursor_x;
|
||||
favorite_btn->move(favorite_x, controls_y);
|
||||
favorite_btn->setVisible(true);
|
||||
cursor_x += starpilot_nvg->rightHandDM ? -(favorite_btn->width() + gap) : favorite_btn->width() + gap;
|
||||
}
|
||||
|
||||
const QPoint screen_recorder_position = hide_steering_wheel
|
||||
? experimental_button_position
|
||||
: QPoint(experimental_button_position.x() - UI_BORDER_SIZE - btn_size, experimental_button_position.y());
|
||||
screen_recorder->move(screen_recorder_position);
|
||||
screen_recorder->setVisible(starpilot_nvg->standstillDuration == 0 && !(starpilot_nvg->signalStyle == "static" && carState.getRightBlinker()) && starpilot_toggles.value("screen_recorder").toBool());
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::initializeGL() {
|
||||
CameraWidget::initializeGL();
|
||||
qInfo() << "OpenGL version:" << QString((const char*)glGetString(GL_VERSION));
|
||||
qInfo() << "OpenGL vendor:" << QString((const char*)glGetString(GL_VENDOR));
|
||||
qInfo() << "OpenGL renderer:" << QString((const char*)glGetString(GL_RENDERER));
|
||||
qInfo() << "OpenGL language version:" << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
prev_draw_t = millis_since_boot();
|
||||
setBackgroundColor(bg_colors[STATUS_DISENGAGED]);
|
||||
}
|
||||
|
||||
mat4 AnnotatedCameraWidget::calcFrameMatrix() {
|
||||
// Project point at "infinity" to compute x and y offsets
|
||||
// to ensure this ends up in the middle of the screen
|
||||
// for narrow come and a little lower for wide cam.
|
||||
// TODO: use proper perspective transform?
|
||||
|
||||
// Select intrinsic matrix and calibration based on camera type
|
||||
auto *s = uiState();
|
||||
bool wide_cam = active_stream_type == VISION_STREAM_WIDE_ROAD;
|
||||
const auto &intrinsic_matrix = wide_cam ? ECAM_INTRINSIC_MATRIX : FCAM_INTRINSIC_MATRIX;
|
||||
const auto &calibration = wide_cam ? s->scene.view_from_wide_calib : s->scene.view_from_calib;
|
||||
|
||||
// Compute the calibration transformation matrix
|
||||
const auto calib_transform = intrinsic_matrix * calibration;
|
||||
|
||||
float zoom = wide_cam ? 2.0 : 1.1;
|
||||
Eigen::Vector3f inf(1000., 0., 0.);
|
||||
auto Kep = calib_transform * inf;
|
||||
|
||||
int w = width(), h = height();
|
||||
float center_x = intrinsic_matrix(0, 2);
|
||||
float center_y = intrinsic_matrix(1, 2);
|
||||
|
||||
float max_x_offset = center_x * zoom - w / 2 - 5;
|
||||
float max_y_offset = center_y * zoom - h / 2 - 5;
|
||||
float x_offset = std::clamp<float>((Kep.x() / Kep.z() - center_x) * zoom, -max_x_offset, max_x_offset);
|
||||
float y_offset = std::clamp<float>((Kep.y() / Kep.z() - center_y) * zoom, -max_y_offset, max_y_offset);
|
||||
|
||||
// Apply transformation such that video pixel coordinates match video
|
||||
// 1) Put (0, 0) in the middle of the video
|
||||
// 2) Apply same scaling as video
|
||||
// 3) Put (0, 0) in top left corner of video
|
||||
Eigen::Matrix3f video_transform =(Eigen::Matrix3f() <<
|
||||
zoom, 0.0f, (w / 2 - x_offset) - (center_x * zoom),
|
||||
0.0f, zoom, (h / 2 - y_offset) - (center_y * zoom),
|
||||
0.0f, 0.0f, 1.0f).finished();
|
||||
|
||||
model.setTransform(video_transform * calib_transform);
|
||||
|
||||
float zx = zoom * 2 * center_x / w;
|
||||
float zy = zoom * 2 * center_y / h;
|
||||
return mat4{{
|
||||
zx, 0.0, 0.0, -x_offset / w * 2,
|
||||
0.0, zy, 0.0, y_offset / h * 2,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
}};
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::paintGL() {
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) {
|
||||
UIState *s = uiState();
|
||||
SubMaster &sm = *(s->sm);
|
||||
const double start_draw_t = millis_since_boot();
|
||||
|
||||
QPainter painter(this);
|
||||
static Params params;
|
||||
const std::string camera_view_param = params.get("CameraView");
|
||||
int camera_view = starpilot_toggles.value("camera_view").toInt();
|
||||
if (!camera_view_param.empty()) {
|
||||
try {
|
||||
camera_view = std::stoi(camera_view_param);
|
||||
} catch (const std::exception &) {
|
||||
LOGW("invalid CameraView param: %s", camera_view_param.c_str());
|
||||
}
|
||||
}
|
||||
const bool camera_view_none = camera_view == CAMERA_VIEW_NONE;
|
||||
|
||||
// draw camera frame
|
||||
if (camera_view_none) {
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
} else {
|
||||
std::lock_guard lk(frame_lock);
|
||||
|
||||
if (frames.empty()) {
|
||||
if (skip_frame_count > 0) {
|
||||
skip_frame_count--;
|
||||
qDebug() << "skipping frame, not ready";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// skip drawing up to this many frames if we're
|
||||
// missing camera frames. this smooths out the
|
||||
// transitions from the narrow and wide cameras
|
||||
skip_frame_count = 5;
|
||||
}
|
||||
|
||||
// Wide or narrow cam dependent on speed
|
||||
bool has_wide_cam = available_streams.count(VISION_STREAM_WIDE_ROAD);
|
||||
if (has_wide_cam) {
|
||||
float v_ego = sm["carState"].getCarState().getVEgo();
|
||||
if ((v_ego < 10) || available_streams.size() == 1) {
|
||||
wide_cam_requested = true;
|
||||
} else if (v_ego > 15) {
|
||||
wide_cam_requested = false;
|
||||
}
|
||||
wide_cam_requested = wide_cam_requested && sm["selfdriveState"].getSelfdriveState().getExperimentalMode() && camera_view == 0;
|
||||
}
|
||||
CameraWidget::setStreamType(camera_view == 1 ? VISION_STREAM_DRIVER :
|
||||
((camera_view == 3 && has_wide_cam) || wide_cam_requested) ? VISION_STREAM_WIDE_ROAD :
|
||||
VISION_STREAM_ROAD);
|
||||
CameraWidget::setFrameId(sm["modelV2"].getModelV2().getFrameId());
|
||||
|
||||
painter.beginNativePainting();
|
||||
CameraWidget::paintGL();
|
||||
painter.endNativePainting();
|
||||
}
|
||||
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
dmon.starpilot_nvg = starpilot_nvg;
|
||||
hud.starpilot_nvg = starpilot_nvg;
|
||||
model.starpilot_nvg = starpilot_nvg;
|
||||
|
||||
experimental_btn->starpilot_scene = starpilot_scene;
|
||||
model.starpilot_scene = starpilot_scene;
|
||||
|
||||
dmon.starpilot_toggles = starpilot_toggles;
|
||||
experimental_btn->starpilot_toggles = starpilot_toggles;
|
||||
hud.starpilot_toggles = starpilot_toggles;
|
||||
model.starpilot_toggles = starpilot_toggles;
|
||||
|
||||
if (!camera_view_none) {
|
||||
model.draw(painter, rect());
|
||||
}
|
||||
dmon.draw(painter, rect());
|
||||
hud.updateState(*s);
|
||||
hud.draw(painter, rect());
|
||||
|
||||
starpilot_nvg->paintStarPilotWidgets(painter, *s, camera_view_none);
|
||||
|
||||
double cur_draw_t = millis_since_boot();
|
||||
double dt = cur_draw_t - prev_draw_t;
|
||||
fps = fps_filter.update(1. / dt * 1000);
|
||||
if (fps < 15) {
|
||||
LOGW("slow frame rate: %.2f fps", fps);
|
||||
}
|
||||
prev_draw_t = cur_draw_t;
|
||||
|
||||
// publish debug msg
|
||||
MessageBuilder msg;
|
||||
auto m = msg.initEvent().initUiDebug();
|
||||
m.setDrawTimeMillis(cur_draw_t - start_draw_t);
|
||||
pm->send("uiDebug", msg);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::showEvent(QShowEvent *event) {
|
||||
CameraWidget::showEvent(event);
|
||||
|
||||
ui_update_params(uiState());
|
||||
prev_draw_t = millis_since_boot();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include "selfdrive/ui/qt/onroad/hud.h"
|
||||
#include "selfdrive/ui/qt/onroad/buttons.h"
|
||||
#include "selfdrive/ui/qt/onroad/driver_monitoring.h"
|
||||
#include "selfdrive/ui/qt/onroad/model.h"
|
||||
#include "selfdrive/ui/qt/widgets/cameraview.h"
|
||||
|
||||
#include "starpilot/ui/qt/onroad/starpilot_buttons.h"
|
||||
#include "starpilot/ui/screenrecorder/screenrecorder.h"
|
||||
|
||||
class AnnotatedCameraWidget : public CameraWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AnnotatedCameraWidget(VisionStreamType type, QWidget* parent = 0);
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
bool handleHudPress(const QPoint &pos);
|
||||
bool handleHudRelease(const QPoint &pos);
|
||||
|
||||
double fps;
|
||||
|
||||
StarPilotAnnotatedCameraWidget *starpilot_nvg;
|
||||
|
||||
StarPilotUIScene starpilot_scene;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
private:
|
||||
QVBoxLayout *main_layout;
|
||||
ExperimentalButton *experimental_btn;
|
||||
DriverMonitorRenderer dmon;
|
||||
HudRenderer hud;
|
||||
ModelRenderer model;
|
||||
std::unique_ptr<PubMaster> pm;
|
||||
|
||||
int skip_frame_count = 0;
|
||||
bool wide_cam_requested = false;
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
DrivingPersonalityButton *personality_btn;
|
||||
std::array<FavoriteButton*, 3> favorite_btns;
|
||||
ScreenRecorder *screen_recorder;
|
||||
|
||||
protected:
|
||||
void paintGL() override;
|
||||
void initializeGL() override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
mat4 calcFrameMatrix() override;
|
||||
|
||||
double prev_draw_t = 0;
|
||||
FirstOrderFilter fps_filter;
|
||||
};
|
||||
@@ -1,143 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/buttons.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
namespace {
|
||||
bool ccmManualOverride(int status) {
|
||||
return status == 1 || status == 2;
|
||||
}
|
||||
|
||||
bool cemManualOverride(int status) {
|
||||
return status == 1 || status == 2;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity, const int &angle) {
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setOpacity(1.0); // bg dictates opacity of ellipse
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(bg);
|
||||
p.drawEllipse(center, btn_size / 2, btn_size / 2);
|
||||
p.save();
|
||||
p.translate(center);
|
||||
p.rotate(angle);
|
||||
p.setOpacity(opacity);
|
||||
p.drawPixmap(-QPoint(img.width() / 2, img.height() / 2), img);
|
||||
p.restore();
|
||||
p.setOpacity(1.0);
|
||||
}
|
||||
|
||||
// ExperimentalButton
|
||||
ExperimentalButton::ExperimentalButton(QWidget *parent) : QPushButton(parent), experimental_mode(false), engageable(false), steering_angle_deg(0) {
|
||||
setFixedSize(btn_size, btn_size);
|
||||
|
||||
engage_img = loadPixmap("../assets/icons/chffr_wheel.png", {img_size, img_size});
|
||||
experimental_img = loadPixmap("../assets/icons/experimental.svg", {img_size, img_size});
|
||||
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
|
||||
|
||||
QObject::connect(starpilotUIState(), &StarPilotUIState::themeUpdated, this, &ExperimentalButton::updateTheme);
|
||||
}
|
||||
|
||||
void ExperimentalButton::changeMode() {
|
||||
const auto cp = (*uiState()->sm)["carParams"].getCarParams();
|
||||
if (params.getBool("SafeMode")) {
|
||||
return;
|
||||
}
|
||||
bool can_change = hasLongitudinalControl(cp) && params.getBool("ExperimentalModeConfirmed");
|
||||
if (can_change) {
|
||||
if (starpilot_toggles.value("conditional_experimental_mode").toBool()) {
|
||||
int override_value = cemManualOverride(starpilot_scene.conditional_status) ? 0 : experimental_mode ? 1 : 2;
|
||||
params_memory.putInt("CEStatus", override_value);
|
||||
params.putInt("PersistedCEStatus", params.getBool("PersistExperimentalState") ? override_value : 0);
|
||||
} else if (starpilot_toggles.value("conditional_chill_mode").toBool()) {
|
||||
int override_value = ccmManualOverride(starpilot_scene.conditional_status) ? 0 : experimental_mode ? 2 : 1;
|
||||
params_memory.putInt("CCStatus", override_value);
|
||||
params.putInt("PersistedCCStatus", params.getBool("PersistChillState") ? override_value : 0);
|
||||
} else {
|
||||
params.putBool("ExperimentalMode", !experimental_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExperimentalButton::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
const auto cs = (*s.sm)["selfdriveState"].getSelfdriveState();
|
||||
bool eng = cs.getEngageable() || cs.getEnabled() || fs.starpilot_scene.always_on_lateral_active;
|
||||
if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) {
|
||||
engageable = eng;
|
||||
experimental_mode = cs.getExperimentalMode();
|
||||
update();
|
||||
}
|
||||
|
||||
const cereal::CarState::Reader &carState = (*s.sm)["carState"].getCarState();
|
||||
|
||||
updateBackgroundColor();
|
||||
|
||||
int current_steering_angle_deg = -carState.getSteeringAngleDeg();
|
||||
if (current_steering_angle_deg != steering_angle_deg && starpilot_toggles.value("rotating_wheel").toBool()) {
|
||||
steering_angle_deg = current_steering_angle_deg;
|
||||
update();
|
||||
} else if (!starpilot_toggles.value("rotating_wheel").toBool()) {
|
||||
steering_angle_deg = 0;
|
||||
}
|
||||
|
||||
if (params_memory.getBool("UpdateWheelImage")) {
|
||||
updateTheme();
|
||||
params_memory.remove("UpdateWheelImage");
|
||||
}
|
||||
}
|
||||
|
||||
void ExperimentalButton::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.setClipRegion(QRegion(QRect(0, 0, btn_size, btn_size), QRegion::Ellipse));
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
if (starpilot_toggles.value("wheel_image").toString() == "stock") {
|
||||
QPixmap img = experimental_mode ? experimental_img : engage_img;
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
|
||||
} else if (wheel_gif) {
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), wheel_gif->currentPixmap(), background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
|
||||
} else if (!wheel_img.isNull()) {
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), wheel_img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
|
||||
} else {
|
||||
QPixmap img = experimental_mode ? experimental_img : engage_img;
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
|
||||
}
|
||||
}
|
||||
|
||||
void ExperimentalButton::showEvent(QShowEvent *event) {
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
void ExperimentalButton::updateBackgroundColor() {
|
||||
const bool conditional_experimental_mode = starpilot_toggles.value("conditional_experimental_mode").toBool();
|
||||
const bool conditional_chill_mode = starpilot_toggles.value("conditional_chill_mode").toBool();
|
||||
const bool highlight_override =
|
||||
(conditional_experimental_mode && starpilot_scene.conditional_status == 1) ||
|
||||
(conditional_chill_mode && ccmManualOverride(starpilot_scene.conditional_status));
|
||||
if (starpilot_toggles.value("simple_mode").toBool()) {
|
||||
background_color = QColor(0, 0, 0, 166);
|
||||
} else if (isDown() || !engageable) {
|
||||
background_color = QColor(0, 0, 0, 166);
|
||||
} else if (starpilot_scene.switchback_mode_enabled) {
|
||||
background_color = bg_colors[STATUS_SWITCHBACK_MODE_ENABLED];
|
||||
} else if (starpilot_scene.always_on_lateral_active) {
|
||||
background_color = bg_colors[STATUS_ALWAYS_ON_LATERAL_ACTIVE];
|
||||
} else if (highlight_override) {
|
||||
background_color = bg_colors[STATUS_CEM_DISABLED];
|
||||
} else if (experimental_mode) {
|
||||
background_color = bg_colors[STATUS_EXPERIMENTAL_MODE_ENABLED];
|
||||
} else if (starpilot_scene.traffic_mode_enabled) {
|
||||
background_color = bg_colors[STATUS_TRAFFIC_MODE_ENABLED];
|
||||
} else {
|
||||
background_color = QColor(0, 0, 0, 166);
|
||||
}
|
||||
}
|
||||
|
||||
void ExperimentalButton::updateTheme() {
|
||||
loadImage("../../starpilot/assets/active_theme/steering_wheel/wheel", wheel_img, wheel_gif, QSize(img_size, img_size), this);
|
||||
if (!wheel_gif && wheel_img.isNull()) {
|
||||
loadImage("../../starpilot/assets/stock_theme/steering_wheel/wheel", wheel_img, wheel_gif, QSize(img_size, img_size), this);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
const int btn_size = 192;
|
||||
const int img_size = (btn_size / 4) * 3;
|
||||
|
||||
class ExperimentalButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExperimentalButton(QWidget *parent = 0);
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
|
||||
StarPilotUIScene starpilot_scene;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void changeMode();
|
||||
|
||||
Params params;
|
||||
QPixmap engage_img;
|
||||
QPixmap experimental_img;
|
||||
bool experimental_mode;
|
||||
bool engageable;
|
||||
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void updateBackgroundColor();
|
||||
void updateTheme();
|
||||
|
||||
int steering_angle_deg;
|
||||
|
||||
Params params_memory{"", true};
|
||||
|
||||
QColor background_color;
|
||||
|
||||
QPixmap wheel_img;
|
||||
|
||||
QSharedPointer<QMovie> wheel_gif;
|
||||
};
|
||||
|
||||
void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity, const int &angle = 0);
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/driver_monitoring.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "selfdrive/ui/qt/onroad/buttons.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
// Default 3D coordinates for face keypoints
|
||||
static constexpr vec3 DEFAULT_FACE_KPTS_3D[] = {
|
||||
{-5.98, -51.20, 8.00}, {-17.64, -49.14, 8.00}, {-23.81, -46.40, 8.00}, {-29.98, -40.91, 8.00}, {-32.04, -37.49, 8.00},
|
||||
{-34.10, -32.00, 8.00}, {-36.16, -21.03, 8.00}, {-36.16, 6.40, 8.00}, {-35.47, 10.51, 8.00}, {-32.73, 19.43, 8.00},
|
||||
{-29.30, 26.29, 8.00}, {-24.50, 33.83, 8.00}, {-19.01, 41.37, 8.00}, {-14.21, 46.17, 8.00}, {-12.16, 47.54, 8.00},
|
||||
{-4.61, 49.60, 8.00}, {4.99, 49.60, 8.00}, {12.53, 47.54, 8.00}, {14.59, 46.17, 8.00}, {19.39, 41.37, 8.00},
|
||||
{24.87, 33.83, 8.00}, {29.67, 26.29, 8.00}, {33.10, 19.43, 8.00}, {35.84, 10.51, 8.00}, {36.53, 6.40, 8.00},
|
||||
{36.53, -21.03, 8.00}, {34.47, -32.00, 8.00}, {32.42, -37.49, 8.00}, {30.36, -40.91, 8.00}, {24.19, -46.40, 8.00},
|
||||
{18.02, -49.14, 8.00}, {6.36, -51.20, 8.00}, {-5.98, -51.20, 8.00},
|
||||
};
|
||||
|
||||
// Colors used for drawing based on monitoring state
|
||||
static const QColor DMON_ENGAGED_COLOR = QColor::fromRgbF(0.1, 0.945, 0.26);
|
||||
static const QColor DMON_DISENGAGED_COLOR = QColor::fromRgbF(0.545, 0.545, 0.545);
|
||||
|
||||
DriverMonitorRenderer::DriverMonitorRenderer() : face_kpts_draw(std::size(DEFAULT_FACE_KPTS_3D)) {
|
||||
dm_img = loadPixmap("../assets/icons/driver_face.png", {img_size + 5, img_size + 5});
|
||||
}
|
||||
|
||||
void DriverMonitorRenderer::updateState(const UIState &s) {
|
||||
auto &sm = *(s.sm);
|
||||
is_visible = sm["selfdriveState"].getSelfdriveState().getAlertSize() == cereal::SelfdriveState::AlertSize::NONE &&
|
||||
sm.rcv_frame("driverStateV2") > s.scene.started_frame;
|
||||
if (!is_visible) return;
|
||||
|
||||
auto dm_state = sm["driverMonitoringState"].getDriverMonitoringState();
|
||||
is_active = dm_state.getActivePolicy() == cereal::DriverMonitoringState::MonitoringPolicy::VISION;
|
||||
is_rhd = dm_state.getIsRHD();
|
||||
dm_fade_state = std::clamp(dm_fade_state + 0.2f * (0.5f - is_active), 0.0f, 1.0f);
|
||||
|
||||
const auto &driverstate = sm["driverStateV2"].getDriverStateV2();
|
||||
const auto driver_orient = is_rhd ? driverstate.getRightDriverData().getFaceOrientation() : driverstate.getLeftDriverData().getFaceOrientation();
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
float v_this = (i == 0 ? (driver_orient[i] < 0 ? 0.7 : 0.9) : 0.4) * driver_orient[i];
|
||||
driver_pose_diff[i] = std::abs(driver_pose_vals[i] - v_this);
|
||||
driver_pose_vals[i] = 0.8f * v_this + (1 - 0.8) * driver_pose_vals[i];
|
||||
driver_pose_sins[i] = std::sin(driver_pose_vals[i] * (1.0f - dm_fade_state));
|
||||
driver_pose_coss[i] = std::cos(driver_pose_vals[i] * (1.0f - dm_fade_state));
|
||||
}
|
||||
|
||||
auto [sin_y, sin_x, sin_z] = driver_pose_sins;
|
||||
auto [cos_y, cos_x, cos_z] = driver_pose_coss;
|
||||
|
||||
// Rotation matrix for transforming face keypoints based on driver's head orientation
|
||||
const mat3 r_xyz = {{
|
||||
cos_x * cos_z, cos_x * sin_z, -sin_x,
|
||||
-sin_y * sin_x * cos_z - cos_y * sin_z, -sin_y * sin_x * sin_z + cos_y * cos_z, -sin_y * cos_x,
|
||||
cos_y * sin_x * cos_z - sin_y * sin_z, cos_y * sin_x * sin_z + sin_y * cos_z, cos_y * cos_x,
|
||||
}};
|
||||
|
||||
// Transform vertices
|
||||
for (int i = 0; i < face_kpts_draw.size(); ++i) {
|
||||
vec3 kpt = matvecmul3(r_xyz, DEFAULT_FACE_KPTS_3D[i]);
|
||||
face_kpts_draw[i] = {{kpt.v[0], kpt.v[1], kpt.v[2] * (1.0f - dm_fade_state) + 8 * dm_fade_state}};
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMonitorRenderer::draw(QPainter &painter, const QRect &surface_rect) {
|
||||
if (!is_visible) return;
|
||||
|
||||
int offset = UI_BORDER_SIZE + btn_size / 2;
|
||||
float x = is_rhd ? surface_rect.width() - offset : offset;
|
||||
float y = surface_rect.height() - offset;
|
||||
|
||||
if (onroad_controls_width > 0) {
|
||||
const int controls_offset = onroad_controls_width + (2 * UI_BORDER_SIZE);
|
||||
if (is_rhd) {
|
||||
x -= controls_offset;
|
||||
} else {
|
||||
x += controls_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (starpilot_toggles.value("road_name_ui").toBool()) {
|
||||
y -= UI_BORDER_SIZE;
|
||||
}
|
||||
|
||||
if (starpilot_nvg) {
|
||||
starpilot_nvg->dmIconPosition.setX(x);
|
||||
starpilot_nvg->dmIconPosition.setY(y);
|
||||
starpilot_nvg->rightHandDM = is_rhd;
|
||||
}
|
||||
|
||||
if (starpilot_toggles.value("hide_dm_icon").toBool()) return;
|
||||
|
||||
painter.save();
|
||||
|
||||
float opacity = is_active ? 0.65f : 0.2f;
|
||||
|
||||
drawIcon(painter, QPoint(x, y), dm_img, QColor(0, 0, 0, 70), opacity);
|
||||
|
||||
QPointF keypoints[std::size(DEFAULT_FACE_KPTS_3D)];
|
||||
for (int i = 0; i < std::size(keypoints); ++i) {
|
||||
const auto &v = face_kpts_draw[i].v;
|
||||
float kp = (v[2] - 8) / 120.0f + 1.0f;
|
||||
keypoints[i] = QPointF(v[0] * kp + x, v[1] * kp + y);
|
||||
}
|
||||
|
||||
painter.setPen(QPen(QColor::fromRgbF(1.0, 1.0, 1.0, opacity), 5.2, Qt::SolidLine, Qt::RoundCap));
|
||||
painter.drawPolyline(keypoints, std::size(keypoints));
|
||||
|
||||
// tracking arcs
|
||||
const int arc_l = 133;
|
||||
const float arc_t_default = 6.7f;
|
||||
const float arc_t_extend = 12.0f;
|
||||
QColor arc_color = uiState()->engaged() ? DMON_ENGAGED_COLOR : DMON_DISENGAGED_COLOR;
|
||||
arc_color.setAlphaF(0.4 * (1.0f - dm_fade_state));
|
||||
|
||||
float delta_x = -driver_pose_sins[1] * arc_l / 2.0f;
|
||||
float delta_y = -driver_pose_sins[0] * arc_l / 2.0f;
|
||||
|
||||
// Draw horizontal tracking arc
|
||||
painter.setPen(QPen(arc_color, arc_t_default + arc_t_extend * std::min(1.0, driver_pose_diff[1] * 5.0), Qt::SolidLine, Qt::RoundCap));
|
||||
painter.drawArc(QRectF(std::min(x + delta_x, x), y - arc_l / 2, std::abs(delta_x), arc_l), (driver_pose_sins[1] > 0 ? 90 : -90) * 16, 180 * 16);
|
||||
|
||||
// Draw vertical tracking arc
|
||||
painter.setPen(QPen(arc_color, arc_t_default + arc_t_extend * std::min(1.0, driver_pose_diff[0] * 5.0), Qt::SolidLine, Qt::RoundCap));
|
||||
painter.drawArc(QRectF(x - arc_l / 2, std::min(y + delta_y, y), arc_l, std::abs(delta_y)), (driver_pose_sins[0] > 0 ? 0 : 180) * 16, 180 * 16);
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <QPainter>
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
#include "starpilot/ui/qt/onroad/starpilot_annotated_camera.h"
|
||||
|
||||
class DriverMonitorRenderer {
|
||||
public:
|
||||
DriverMonitorRenderer();
|
||||
void updateState(const UIState &s);
|
||||
void draw(QPainter &painter, const QRect &surface_rect);
|
||||
|
||||
StarPilotAnnotatedCameraWidget *starpilot_nvg;
|
||||
|
||||
int onroad_controls_width = 0;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
private:
|
||||
float driver_pose_vals[3] = {};
|
||||
float driver_pose_diff[3] = {};
|
||||
float driver_pose_sins[3] = {};
|
||||
float driver_pose_coss[3] = {};
|
||||
bool is_visible = false;
|
||||
bool is_active = false;
|
||||
bool is_rhd = false;
|
||||
float dm_fade_state = 1.0;
|
||||
QPixmap dm_img;
|
||||
std::vector<vec3> face_kpts_draw;
|
||||
};
|
||||
@@ -1,427 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/hud.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <cmath>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
constexpr int SET_SPEED_NA = 255;
|
||||
constexpr int NAV_CANCEL_HOLD_MS = 650;
|
||||
|
||||
HudRenderer::HudRenderer() {}
|
||||
|
||||
bool HudRenderer::handleNavigationPress(const QPoint &pos) {
|
||||
if (!navigation_valid || !nav_hit_rect.contains(pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nav_press_active = true;
|
||||
nav_press_timer.restart();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HudRenderer::handleNavigationRelease(const QPoint &pos) {
|
||||
if (!nav_press_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nav_press_active = false;
|
||||
if (!nav_hit_rect.contains(pos)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nav_press_timer.isValid() && nav_press_timer.elapsed() >= NAV_CANCEL_HOLD_MS) {
|
||||
cancelNavigation();
|
||||
} else {
|
||||
params_memory.putBool("NavInstructionCollapsed", !navigation_collapsed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HudRenderer::cancelNavigation() {
|
||||
params.remove("NavDestination");
|
||||
params_memory.remove("NavInstructionState");
|
||||
params_memory.remove("NavInstructionCollapsed");
|
||||
navigation_valid = false;
|
||||
navigation_collapsed = false;
|
||||
nav_hit_rect = QRect();
|
||||
nav_primary_text.clear();
|
||||
nav_secondary_text.clear();
|
||||
nav_distance.clear();
|
||||
nav_maneuver_type.clear();
|
||||
nav_modifier.clear();
|
||||
nav_next_maneuver_type.clear();
|
||||
nav_next_modifier.clear();
|
||||
}
|
||||
|
||||
void HudRenderer::updateState(const UIState &s) {
|
||||
is_metric = s.scene.is_metric;
|
||||
status = s.status;
|
||||
|
||||
const SubMaster &sm = *(s.sm);
|
||||
if (sm.rcv_frame("carState") < s.scene.started_frame) {
|
||||
is_cruise_set = false;
|
||||
set_speed = SET_SPEED_NA;
|
||||
speed = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &controls_state = sm["controlsState"].getControlsState();
|
||||
const auto &car_state = sm["carState"].getCarState();
|
||||
|
||||
// Handle older routes where vCruiseCluster is not set
|
||||
set_speed = car_state.getVCruiseCluster() == 0.0 ? controls_state.getVCruiseDEPRECATED() : car_state.getVCruiseCluster();
|
||||
is_cruise_set = set_speed > 0 && set_speed != SET_SPEED_NA;
|
||||
is_cruise_available = set_speed != -1;
|
||||
|
||||
if (is_cruise_set && starpilot_toggles.value("set_speed_offset").toDouble() > 0) {
|
||||
set_speed += starpilot_toggles.value("set_speed_offset").toDouble();
|
||||
}
|
||||
|
||||
if (is_cruise_set && !is_metric) {
|
||||
set_speed *= KM_TO_MILE;
|
||||
}
|
||||
|
||||
// Handle older routes where vEgoCluster is not set
|
||||
v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0;
|
||||
float v_ego = v_ego_cluster_seen && !starpilot_toggles.value("use_wheel_speed").toBool() ? car_state.getVEgoCluster() : car_state.getVEgo();
|
||||
speed = std::max<float>(0.0f, v_ego * (is_metric ? MS_TO_KPH : MS_TO_MPH));
|
||||
|
||||
navigation_enabled = params.getBool("NavigationUI");
|
||||
navigation_valid = false;
|
||||
navigation_has_next = false;
|
||||
navigation_collapsed = false;
|
||||
nav_hit_rect = QRect();
|
||||
nav_primary_text.clear();
|
||||
nav_secondary_text.clear();
|
||||
nav_distance.clear();
|
||||
nav_maneuver_type.clear();
|
||||
nav_modifier.clear();
|
||||
nav_next_maneuver_type.clear();
|
||||
nav_next_modifier.clear();
|
||||
|
||||
if (!navigation_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.get("NavDestination").empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string nav_state_raw = params_memory.get("NavInstructionState");
|
||||
if (nav_state_raw.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QJsonDocument nav_state_doc = QJsonDocument::fromJson(QByteArray::fromStdString(nav_state_raw));
|
||||
if (!nav_state_doc.isObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QJsonObject nav = nav_state_doc.object();
|
||||
if (!nav.value("valid").toBool(false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nav_primary_text = nav.value("maneuverPrimaryText").toString().trimmed();
|
||||
if (nav_primary_text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigation_valid = true;
|
||||
nav_secondary_text = nav.value("maneuverSecondaryText").toString().trimmed();
|
||||
nav_distance = formatNavDistance(static_cast<float>(nav.value("maneuverDistance").toDouble(0.0)));
|
||||
nav_maneuver_type = nav.value("maneuverType").toString().trimmed();
|
||||
nav_modifier = nav.value("maneuverModifier").toString().trimmed();
|
||||
nav_next_maneuver_type = nav.value("nextManeuverType").toString().trimmed();
|
||||
nav_next_modifier = nav.value("nextManeuverModifier").toString().trimmed();
|
||||
navigation_has_next = !nav_next_maneuver_type.isEmpty() || !nav_next_modifier.isEmpty();
|
||||
navigation_collapsed = params_memory.getBool("NavInstructionCollapsed");
|
||||
}
|
||||
|
||||
void HudRenderer::draw(QPainter &p, const QRect &surface_rect) {
|
||||
p.save();
|
||||
|
||||
// Draw header gradient — constant stops, build once
|
||||
static const QLinearGradient bg = []() {
|
||||
QLinearGradient g(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
|
||||
g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
|
||||
g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
|
||||
return g;
|
||||
}();
|
||||
p.fillRect(0, 0, surface_rect.width(), UI_HEADER_HEIGHT, bg);
|
||||
|
||||
|
||||
if (is_cruise_available) {
|
||||
drawSetSpeed(p, surface_rect);
|
||||
}
|
||||
if (starpilot_nvg->standstillDuration == 0 && !starpilot_toggles.value("hide_speed").toBool()) {
|
||||
drawCurrentSpeed(p, surface_rect);
|
||||
}
|
||||
if (navigation_valid) {
|
||||
drawNavigationCard(p, surface_rect);
|
||||
}
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
void HudRenderer::drawSetSpeed(QPainter &p, const QRect &surface_rect) {
|
||||
// Draw outer box + border to contain set speed
|
||||
const QSize default_size = {172, 204};
|
||||
QSize set_speed_size = is_metric ? QSize(200, 204) : default_size;
|
||||
|
||||
if (starpilot_nvg->speedLimitHeight != 0) {
|
||||
set_speed_size.rheight() += starpilot_nvg->speedLimitHeight;
|
||||
if (starpilot_toggles.value("speed_limit_vienna").toBool()) {
|
||||
set_speed_size.rwidth() = 200;
|
||||
}
|
||||
}
|
||||
|
||||
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
|
||||
|
||||
if (!starpilot_toggles.value("hide_max_speed").toBool()) {
|
||||
// Draw set speed box
|
||||
p.setPen(QPen(QColor(255, 255, 255, 75), 6));
|
||||
p.setBrush(QColor(0, 0, 0, 166));
|
||||
p.drawRoundedRect(set_speed_rect, 32, 32);
|
||||
|
||||
// Colors based on status
|
||||
QColor max_color = QColor(0xa6, 0xa6, 0xa6, 0xff);
|
||||
QColor set_speed_color = QColor(0x72, 0x72, 0x72, 0xff);
|
||||
if (is_cruise_set) {
|
||||
set_speed_color = QColor(255, 255, 255);
|
||||
if (status == STATUS_DISENGAGED) {
|
||||
max_color = QColor(255, 255, 255);
|
||||
} else if (status == STATUS_OVERRIDE) {
|
||||
max_color = QColor(0x91, 0x9b, 0x95, 0xff);
|
||||
} else {
|
||||
max_color = QColor(0x80, 0xd8, 0xa6, 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw "MAX" text
|
||||
p.setFont(InterFont(40, QFont::DemiBold));
|
||||
p.setPen(max_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX"));
|
||||
|
||||
// Draw set speed
|
||||
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(set_speed)) : "–";
|
||||
p.setFont(InterFont(90, QFont::Bold));
|
||||
p.setPen(set_speed_color);
|
||||
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr);
|
||||
}
|
||||
|
||||
starpilot_nvg->defaultSize = default_size;
|
||||
starpilot_nvg->isCruiseSet = is_cruise_set;
|
||||
starpilot_nvg->setSpeedRect = set_speed_rect;
|
||||
starpilot_nvg->speed = speed;
|
||||
}
|
||||
|
||||
void HudRenderer::drawCurrentSpeed(QPainter &p, const QRect &surface_rect) {
|
||||
QString speedStr = QString::number(std::nearbyint(speed));
|
||||
|
||||
p.setFont(InterFont(176, QFont::Bold));
|
||||
drawText(p, surface_rect.center().x(), 210, speedStr);
|
||||
|
||||
p.setFont(InterFont(66));
|
||||
drawText(p, surface_rect.center().x(), 290, is_metric ? tr("km/h") : tr("mph"), 200);
|
||||
}
|
||||
|
||||
void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
|
||||
QRect real_rect = p.fontMetrics().boundingRect(text);
|
||||
real_rect.moveCenter({x, y - real_rect.height() / 2});
|
||||
|
||||
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
|
||||
p.drawText(real_rect.x(), real_rect.bottom(), text);
|
||||
}
|
||||
|
||||
QString HudRenderer::formatNavDistance(float distance_m) const {
|
||||
if (is_metric) {
|
||||
if (distance_m < 1000.0f) {
|
||||
int step = distance_m < 500.0f ? 25 : 50;
|
||||
return QString("%1 m").arg(qRound(distance_m / step) * step);
|
||||
}
|
||||
float km = distance_m / 1000.0f;
|
||||
return km >= 10.0f ? QString("%1 km").arg(static_cast<int>(std::floor(km))) : QString("%1 km").arg(km, 0, 'f', 1);
|
||||
}
|
||||
|
||||
float distance_ft = distance_m * METER_TO_FOOT;
|
||||
if (distance_ft < 1000.0f) {
|
||||
int step = distance_ft <= 100.0f ? 10 : 50;
|
||||
return QString("%1 ft").arg(qRound(distance_ft / step) * step);
|
||||
}
|
||||
|
||||
float miles = distance_ft / 5280.0f;
|
||||
return miles >= 10.0f ? QString("%1 mi").arg(static_cast<int>(std::floor(miles))) : QString("%1 mi").arg(miles, 0, 'f', 1);
|
||||
}
|
||||
|
||||
QString HudRenderer::navigationIconFilename(const QString &maneuver_type, const QString &modifier) const {
|
||||
QString normalized_type = maneuver_type.isEmpty() ? "turn" : maneuver_type;
|
||||
if (normalized_type == "rotary") {
|
||||
normalized_type = "roundabout";
|
||||
} else if (normalized_type == "new name" || normalized_type == "continue") {
|
||||
normalized_type = "turn";
|
||||
}
|
||||
|
||||
if (modifier == "uturn") {
|
||||
return "direction_uturn.png";
|
||||
}
|
||||
|
||||
static const QHash<QString, QString> suffixes = {
|
||||
{"left", "left"},
|
||||
{"right", "right"},
|
||||
{"straight", "straight"},
|
||||
{"slightLeft", "slight_left"},
|
||||
{"slightRight", "slight_right"},
|
||||
{"sharpLeft", "sharp_left"},
|
||||
{"sharpRight", "sharp_right"},
|
||||
};
|
||||
|
||||
normalized_type.replace(" ", "_");
|
||||
const QString suffix = suffixes.value(modifier, "");
|
||||
const QString candidate = suffix.isEmpty() ? QString("direction_%1.png").arg(normalized_type)
|
||||
: QString("direction_%1_%2.png").arg(normalized_type, suffix);
|
||||
const QString candidate_path = QString("../../starpilot/assets/navigation/%1").arg(candidate);
|
||||
return QFileInfo::exists(candidate_path) ? candidate : "direction_turn_straight.png";
|
||||
}
|
||||
|
||||
QPixmap HudRenderer::getNavigationIcon(const QString &maneuver_type, const QString &modifier, int size) {
|
||||
const QString icon_name = navigationIconFilename(maneuver_type, modifier);
|
||||
const QString cache_key = QString("%1|%2").arg(icon_name).arg(size);
|
||||
if (!nav_icon_cache.contains(cache_key)) {
|
||||
nav_icon_cache.insert(cache_key, loadPixmap(QString("../../starpilot/assets/navigation/%1").arg(icon_name), QSize(size, size)));
|
||||
}
|
||||
return nav_icon_cache.value(cache_key);
|
||||
}
|
||||
|
||||
QStringList HudRenderer::wrapNavigationText(int max_width, int font_size, const QString &text) const {
|
||||
QStringList words = text.split(' ', QString::SkipEmptyParts);
|
||||
QStringList lines;
|
||||
QString current_line;
|
||||
const QFontMetrics metrics(InterFont(font_size, QFont::Bold));
|
||||
|
||||
for (const QString &word : words) {
|
||||
QString test_line = current_line.isEmpty() ? word : current_line + " " + word;
|
||||
if (metrics.horizontalAdvance(test_line) <= max_width) {
|
||||
current_line = test_line;
|
||||
} else {
|
||||
if (!current_line.isEmpty()) {
|
||||
lines.append(current_line);
|
||||
}
|
||||
current_line = word;
|
||||
if (lines.size() >= 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_line.isEmpty() && lines.size() < 2) {
|
||||
lines.append(current_line);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
void HudRenderer::drawNavigationCard(QPainter &p, const QRect &surface_rect) {
|
||||
if (navigation_collapsed) {
|
||||
const int chip_size = 94;
|
||||
const int chip_x = surface_rect.right() - chip_size - 32;
|
||||
const int chip_y = surface_rect.width() >= 1200 ? 232 : 204;
|
||||
nav_hit_rect = QRect(chip_x, chip_y, chip_size, chip_size);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QColor(7, 11, 18, 228));
|
||||
p.drawRoundedRect(nav_hit_rect, 28, 28);
|
||||
p.setPen(QPen(QColor(255, 255, 255, 40), 2));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRoundedRect(nav_hit_rect, 28, 28);
|
||||
|
||||
const int icon_size = 58;
|
||||
const QPixmap icon = getNavigationIcon(nav_maneuver_type, nav_modifier, icon_size);
|
||||
const int icon_x = chip_x + (chip_size - icon_size) / 2;
|
||||
const int icon_y = chip_y + (chip_size - icon_size) / 2;
|
||||
p.drawPixmap(icon_x, icon_y, icon);
|
||||
return;
|
||||
}
|
||||
|
||||
const int container_width = std::clamp(surface_rect.width() - 120, 760, 1080);
|
||||
const int container_height = surface_rect.width() >= 1200 ? 238 : 206;
|
||||
const int container_x = (surface_rect.width() - container_width) / 2;
|
||||
const int container_y = surface_rect.width() >= 1200 ? 332 : 298;
|
||||
const int border_radius = container_height == 238 ? 42 : 34;
|
||||
const int icon_size = container_height == 238 ? 150 : 122;
|
||||
const int icon_padding = container_height == 238 ? 30 : 24;
|
||||
const int then_section_width = container_height == 238 ? 180 : 144;
|
||||
const int then_icon_size = container_height == 238 ? 105 : 82;
|
||||
const int title_font_size = container_height == 238 ? 75 : 58;
|
||||
const int secondary_font_size = container_height == 238 ? 34 : 28;
|
||||
const int distance_font_size = container_height == 238 ? 48 : 40;
|
||||
const int title_top_padding = container_height == 238 ? 10 : 10;
|
||||
const int title_line_spacing = container_height == 238 ? 68 : 56;
|
||||
const int secondary_bottom_padding = container_height == 238 ? 24 : 20;
|
||||
const int secondary_gap = container_height == 238 ? 10 : 8;
|
||||
|
||||
QRect container(container_x, container_y, container_width, container_height);
|
||||
nav_hit_rect = container;
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QColor(0, 0, 0, 180));
|
||||
p.drawRoundedRect(container, border_radius, border_radius);
|
||||
|
||||
const int icon_x = container_x + icon_padding;
|
||||
const int icon_y = container_y + title_top_padding + 4;
|
||||
const QPixmap icon = getNavigationIcon(nav_maneuver_type, nav_modifier, icon_size);
|
||||
p.drawPixmap(icon_x, icon_y, icon);
|
||||
|
||||
p.setFont(InterFont(distance_font_size, QFont::Bold));
|
||||
p.setPen(Qt::white);
|
||||
const int distance_width = p.fontMetrics().horizontalAdvance(nav_distance);
|
||||
p.drawText(icon_x + (icon_size - distance_width) / 2, container_y + container_height - 18, nav_distance);
|
||||
|
||||
const int text_x = icon_x + icon_size + 53;
|
||||
const int right_gutter = icon_padding + (navigation_has_next ? then_section_width : 0);
|
||||
const int text_width = container_width - (text_x - container_x) - right_gutter;
|
||||
const QStringList title_lines = wrapNavigationText(text_width, title_font_size, nav_primary_text);
|
||||
const QFont title_font = InterFont(title_font_size, QFont::Bold);
|
||||
const QFontMetrics title_metrics(title_font);
|
||||
const int title_baseline = container_y + title_top_padding + title_metrics.ascent();
|
||||
|
||||
p.setFont(title_font);
|
||||
p.setPen(Qt::white);
|
||||
for (int index = 0; index < title_lines.size() && index < 2; ++index) {
|
||||
p.drawText(text_x, title_baseline + index * title_line_spacing, title_lines[index]);
|
||||
}
|
||||
|
||||
if (!nav_secondary_text.isEmpty()) {
|
||||
const QFont secondary_font = InterFont(secondary_font_size, QFont::Medium);
|
||||
const QFontMetrics secondary_metrics(secondary_font);
|
||||
const int title_bottom = title_baseline + (std::max(title_lines.size(), 1) - 1) * title_line_spacing + title_metrics.descent();
|
||||
const int secondary_max_baseline = container_y + container_height - secondary_bottom_padding - secondary_metrics.descent();
|
||||
const int secondary_preferred_baseline = title_bottom + secondary_gap + secondary_metrics.ascent();
|
||||
const int secondary_baseline = std::min(secondary_preferred_baseline, secondary_max_baseline);
|
||||
p.setFont(secondary_font);
|
||||
p.setPen(QColor(255, 255, 255, 180));
|
||||
p.drawText(text_x, secondary_baseline, nav_secondary_text);
|
||||
}
|
||||
|
||||
if (!navigation_has_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int divider_x = container_x + container_width - then_section_width - 8;
|
||||
p.setPen(QPen(QColor(255, 255, 255, 50), 2));
|
||||
p.drawLine(divider_x, container_y + 23, divider_x, container_y + container_height - 23);
|
||||
|
||||
p.setFont(InterFont(container_height == 225 ? 53 : 40, QFont::Medium));
|
||||
p.setPen(Qt::white);
|
||||
const QString then_label = tr("Then");
|
||||
const int then_x = divider_x + 15;
|
||||
const int then_label_width = p.fontMetrics().horizontalAdvance(then_label);
|
||||
p.drawText(then_x + (then_section_width - 23 - then_label_width) / 2, container_y + (container_height == 238 ? 66 : 60), then_label);
|
||||
|
||||
const QPixmap next_icon = getNavigationIcon(nav_next_maneuver_type, nav_next_modifier, then_icon_size);
|
||||
const int then_icon_x = then_x + (then_section_width - 23 - then_icon_size) / 2;
|
||||
const int then_icon_y = container_y + (container_height == 238 ? 96 : 78);
|
||||
p.drawPixmap(then_icon_x, then_icon_y, next_icon);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QElapsedTimer>
|
||||
#include <QJsonObject>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
#include "starpilot/ui/qt/onroad/starpilot_annotated_camera.h"
|
||||
|
||||
class HudRenderer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HudRenderer();
|
||||
void updateState(const UIState &s);
|
||||
void draw(QPainter &p, const QRect &surface_rect);
|
||||
bool handleNavigationPress(const QPoint &pos);
|
||||
bool handleNavigationRelease(const QPoint &pos);
|
||||
|
||||
StarPilotAnnotatedCameraWidget *starpilot_nvg;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
private:
|
||||
void drawSetSpeed(QPainter &p, const QRect &surface_rect);
|
||||
void drawCurrentSpeed(QPainter &p, const QRect &surface_rect);
|
||||
void drawNavigationCard(QPainter &p, const QRect &surface_rect);
|
||||
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
|
||||
QStringList wrapNavigationText(int max_width, int font_size, const QString &text) const;
|
||||
QString formatNavDistance(float distance_m) const;
|
||||
QString navigationIconFilename(const QString &maneuver_type, const QString &modifier) const;
|
||||
QPixmap getNavigationIcon(const QString &maneuver_type, const QString &modifier, int size);
|
||||
void cancelNavigation();
|
||||
|
||||
float speed = 0;
|
||||
float set_speed = 0;
|
||||
bool is_cruise_set = false;
|
||||
bool is_cruise_available = true;
|
||||
bool is_metric = false;
|
||||
bool v_ego_cluster_seen = false;
|
||||
bool navigation_enabled = false;
|
||||
bool navigation_valid = false;
|
||||
bool navigation_has_next = false;
|
||||
bool navigation_collapsed = false;
|
||||
int status = STATUS_DISENGAGED;
|
||||
QString nav_distance;
|
||||
QString nav_primary_text;
|
||||
QString nav_secondary_text;
|
||||
QString nav_maneuver_type;
|
||||
QString nav_modifier;
|
||||
QString nav_next_maneuver_type;
|
||||
QString nav_next_modifier;
|
||||
QRect nav_hit_rect;
|
||||
QHash<QString, QPixmap> nav_icon_cache;
|
||||
QElapsedTimer nav_press_timer;
|
||||
bool nav_press_active = false;
|
||||
Params params;
|
||||
Params params_memory{"", true};
|
||||
};
|
||||
@@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'alerts.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "alerts.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'alerts.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_OnroadAlerts_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[13];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_OnroadAlerts_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_OnroadAlerts_t qt_meta_stringdata_OnroadAlerts = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12) // "OnroadAlerts"
|
||||
|
||||
},
|
||||
"OnroadAlerts"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_OnroadAlerts[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void OnroadAlerts::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject OnroadAlerts::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_OnroadAlerts.data,
|
||||
qt_meta_data_OnroadAlerts,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *OnroadAlerts::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *OnroadAlerts::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_OnroadAlerts.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int OnroadAlerts::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'annotated_camera.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "annotated_camera.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'annotated_camera.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_AnnotatedCameraWidget_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[22];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_AnnotatedCameraWidget_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_AnnotatedCameraWidget_t qt_meta_stringdata_AnnotatedCameraWidget = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 21) // "AnnotatedCameraWidget"
|
||||
|
||||
},
|
||||
"AnnotatedCameraWidget"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_AnnotatedCameraWidget[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void AnnotatedCameraWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject AnnotatedCameraWidget::staticMetaObject = { {
|
||||
&CameraWidget::staticMetaObject,
|
||||
qt_meta_stringdata_AnnotatedCameraWidget.data,
|
||||
qt_meta_data_AnnotatedCameraWidget,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *AnnotatedCameraWidget::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *AnnotatedCameraWidget::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_AnnotatedCameraWidget.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return CameraWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int AnnotatedCameraWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = CameraWidget::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'buttons.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "buttons.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'buttons.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_ExperimentalButton_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[19];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_ExperimentalButton_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_ExperimentalButton_t qt_meta_stringdata_ExperimentalButton = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 18) // "ExperimentalButton"
|
||||
|
||||
},
|
||||
"ExperimentalButton"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_ExperimentalButton[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void ExperimentalButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject ExperimentalButton::staticMetaObject = { {
|
||||
&QPushButton::staticMetaObject,
|
||||
qt_meta_stringdata_ExperimentalButton.data,
|
||||
qt_meta_data_ExperimentalButton,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *ExperimentalButton::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *ExperimentalButton::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_ExperimentalButton.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QPushButton::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int ExperimentalButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QPushButton::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,94 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'hud.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "hud.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'hud.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_HudRenderer_t {
|
||||
QByteArrayData data[1];
|
||||
char stringdata0[12];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_HudRenderer_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_HudRenderer_t qt_meta_stringdata_HudRenderer = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 11) // "HudRenderer"
|
||||
|
||||
},
|
||||
"HudRenderer"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_HudRenderer[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void HudRenderer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
Q_UNUSED(_o);
|
||||
Q_UNUSED(_id);
|
||||
Q_UNUSED(_c);
|
||||
Q_UNUSED(_a);
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject HudRenderer::staticMetaObject = { {
|
||||
&QObject::staticMetaObject,
|
||||
qt_meta_stringdata_HudRenderer.data,
|
||||
qt_meta_data_HudRenderer,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *HudRenderer::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *HudRenderer::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_HudRenderer.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int HudRenderer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,128 +0,0 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'onroad_home.h'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.12.8)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "onroad_home.h"
|
||||
#include <QtCore/qbytearray.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'onroad_home.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 67
|
||||
#error "This file was generated using the moc from 5.12.8. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
struct qt_meta_stringdata_OnroadWindow_t {
|
||||
QByteArrayData data[9];
|
||||
char stringdata0[82];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) \
|
||||
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
|
||||
qptrdiff(offsetof(qt_meta_stringdata_OnroadWindow_t, stringdata0) + ofs \
|
||||
- idx * sizeof(QByteArrayData)) \
|
||||
)
|
||||
static const qt_meta_stringdata_OnroadWindow_t qt_meta_stringdata_OnroadWindow = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 12), // "OnroadWindow"
|
||||
QT_MOC_LITERAL(1, 13, 17), // "offroadTransition"
|
||||
QT_MOC_LITERAL(2, 31, 0), // ""
|
||||
QT_MOC_LITERAL(3, 32, 7), // "offroad"
|
||||
QT_MOC_LITERAL(4, 40, 11), // "updateState"
|
||||
QT_MOC_LITERAL(5, 52, 7), // "UIState"
|
||||
QT_MOC_LITERAL(6, 60, 1), // "s"
|
||||
QT_MOC_LITERAL(7, 62, 16), // "StarPilotUIState"
|
||||
QT_MOC_LITERAL(8, 79, 2) // "fs"
|
||||
|
||||
},
|
||||
"OnroadWindow\0offroadTransition\0\0offroad\0"
|
||||
"updateState\0UIState\0s\0StarPilotUIState\0"
|
||||
"fs"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_OnroadWindow[] = {
|
||||
|
||||
// content:
|
||||
8, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
2, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
1, 1, 24, 2, 0x08 /* Private */,
|
||||
4, 2, 27, 2, 0x08 /* Private */,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void, QMetaType::Bool, 3,
|
||||
QMetaType::Void, 0x80000000 | 5, 0x80000000 | 7, 6, 8,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
void OnroadWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
auto *_t = static_cast<OnroadWindow *>(_o);
|
||||
Q_UNUSED(_t)
|
||||
switch (_id) {
|
||||
case 0: _t->offroadTransition((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 1: _t->updateState((*reinterpret_cast< const UIState(*)>(_a[1])),(*reinterpret_cast< const StarPilotUIState(*)>(_a[2]))); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_INIT_METAOBJECT const QMetaObject OnroadWindow::staticMetaObject = { {
|
||||
&QWidget::staticMetaObject,
|
||||
qt_meta_stringdata_OnroadWindow.data,
|
||||
qt_meta_data_OnroadWindow,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
|
||||
const QMetaObject *OnroadWindow::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *OnroadWindow::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_OnroadWindow.stringdata0))
|
||||
return static_cast<void*>(this);
|
||||
return QWidget::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int OnroadWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QWidget::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 2)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 2;
|
||||
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 2)
|
||||
*reinterpret_cast<int*>(_a[0]) = -1;
|
||||
_id -= 2;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
QT_END_MOC_NAMESPACE
|
||||
@@ -1,401 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/model.h"
|
||||
|
||||
constexpr int CLIP_MARGIN = 500;
|
||||
|
||||
static int get_path_length_idx(const cereal::XYZTData::Reader &line, const float path_height) {
|
||||
const auto &line_x = line.getX();
|
||||
int max_idx = 0;
|
||||
for (int i = 1; i < line_x.size() && line_x[i] <= path_height; ++i) {
|
||||
max_idx = i;
|
||||
}
|
||||
return max_idx;
|
||||
}
|
||||
|
||||
void ModelRenderer::draw(QPainter &painter, const QRect &surface_rect) {
|
||||
auto *s = uiState();
|
||||
auto &sm = *(s->sm);
|
||||
// Check if data is up-to-date
|
||||
if (sm.rcv_frame("liveCalibration") < s->scene.started_frame ||
|
||||
sm.rcv_frame("modelV2") < s->scene.started_frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
clip_region = surface_rect.adjusted(-CLIP_MARGIN, -CLIP_MARGIN, CLIP_MARGIN, CLIP_MARGIN);
|
||||
experimental_mode = sm["selfdriveState"].getSelfdriveState().getExperimentalMode();
|
||||
longitudinal_control = sm["carParams"].getCarParams().getOpenpilotLongitudinalControl();
|
||||
path_offset_z = sm["liveCalibration"].getLiveCalibration().getHeight()[0];
|
||||
|
||||
painter.save();
|
||||
|
||||
const auto &model = sm["modelV2"].getModelV2();
|
||||
const auto &radar_state = sm["radarState"].getRadarState();
|
||||
const auto &lead_one = radar_state.getLeadOne();
|
||||
|
||||
update_model(model, lead_one, surface_rect.height());
|
||||
drawLaneLines(painter);
|
||||
drawPath(painter, model, surface_rect.height());
|
||||
|
||||
if ((longitudinal_control || starpilot_toggles.value("lead_info").toBool()) && sm.alive("radarState") && !starpilot_toggles.value("hide_lead_marker").toBool()) {
|
||||
update_leads(radar_state, model.getPosition());
|
||||
const auto &lead_two = radar_state.getLeadTwo();
|
||||
if (lead_one.getStatus()) {
|
||||
if (lead_one.getModelProb() >= starpilot_toggles.value("lead_detection_probability").toDouble()) {
|
||||
drawLead(painter, lead_one, lead_vertices[0], surface_rect, QColor(starpilot_toggles.value("lead_marker_color").toString()));
|
||||
} else {
|
||||
drawLead(painter, lead_one, lead_vertices[0], surface_rect, starpilot_nvg->whiteColor());
|
||||
}
|
||||
} else {
|
||||
starpilot_nvg->leadTextRect = QRect();
|
||||
}
|
||||
if (lead_two.getStatus() && (std::abs(lead_one.getDRel() - lead_two.getDRel()) > 3.0)) {
|
||||
drawLead(painter, lead_two, lead_vertices[1], surface_rect, QColor(starpilot_toggles.value("lead_marker_color").toString()));
|
||||
}
|
||||
|
||||
// Adjacent leads may be published by radard for non-UI consumers (e.g. HumanLaneChanges),
|
||||
// so gate drawing on the AdjacentLeadsUI toggle directly.
|
||||
if (starpilot_toggles.value("adjacent_lead_tracking").toBool()) {
|
||||
SubMaster &fpsm = *(starpilotUIState()->sm);
|
||||
const cereal::StarPilotRadarState::Reader &starpilot_radar_state = fpsm["starpilotRadarState"].getStarpilotRadarState();
|
||||
|
||||
const cereal::StarPilotRadarState::LeadData::Reader &lead_left = starpilot_radar_state.getLeadLeft();
|
||||
const cereal::StarPilotRadarState::LeadData::Reader &lead_right = starpilot_radar_state.getLeadRight();
|
||||
|
||||
updateAdjacentLeads(starpilot_radar_state, model.getPosition());
|
||||
|
||||
starpilot_nvg->adjacentLeadTextRect = QRect();
|
||||
|
||||
if (lead_left.getStatus() && lead_right.getStatus() && (lead_left.getDRel() < lead_right.getDRel())) {
|
||||
drawLead(painter, reinterpret_cast<const cereal::RadarState::LeadData::Reader&>(lead_left), adjacent_lead_vertices[0], surface_rect, starpilot_nvg->blueColor(), true);
|
||||
drawLead(painter, reinterpret_cast<const cereal::RadarState::LeadData::Reader&>(lead_right), adjacent_lead_vertices[1], surface_rect, starpilot_nvg->purpleColor(), true);
|
||||
} else {
|
||||
if (lead_left.getStatus()) {
|
||||
drawLead(painter, reinterpret_cast<const cereal::RadarState::LeadData::Reader&>(lead_left), adjacent_lead_vertices[0], surface_rect, starpilot_nvg->blueColor(), true);
|
||||
}
|
||||
if (lead_right.getStatus()) {
|
||||
drawLead(painter, reinterpret_cast<const cereal::RadarState::LeadData::Reader&>(lead_right), adjacent_lead_vertices[1], surface_rect, starpilot_nvg->purpleColor(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (starpilot_toggles.value("radar_tracks").toBool()) {
|
||||
updateRadarTracks(model.getPosition());
|
||||
}
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
void ModelRenderer::update_leads(const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const auto &lead_data = (i == 0) ? radar_state.getLeadOne() : radar_state.getLeadTwo();
|
||||
if (lead_data.getStatus()) {
|
||||
float z = line.getZ()[get_path_length_idx(line, lead_data.getDRel())];
|
||||
mapToScreen(lead_data.getDRel(), -lead_data.getYRel(), z + path_offset_z, &lead_vertices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead, float height) {
|
||||
const auto &model_position = model.getPosition();
|
||||
float max_distance = *(model_position.getX().end() - 1);
|
||||
|
||||
// update lane lines
|
||||
const auto &lane_lines = model.getLaneLines();
|
||||
const auto &line_probs = model.getLaneLineProbs();
|
||||
int max_idx = get_path_length_idx(lane_lines[0], max_distance);
|
||||
for (int i = 0; i < std::size(lane_line_vertices); i++) {
|
||||
lane_line_probs[i] = line_probs[i];
|
||||
mapLineToPolygon(lane_lines[i], (starpilot_toggles.value("model_ui").toBool() ? starpilot_toggles.value("lane_line_width").toDouble() : 0.025) * lane_line_probs[i], 0, &lane_line_vertices[i], max_idx);
|
||||
}
|
||||
|
||||
// update road edges
|
||||
const auto &road_edges = model.getRoadEdges();
|
||||
const auto &edge_stds = model.getRoadEdgeStds();
|
||||
for (int i = 0; i < std::size(road_edge_vertices); i++) {
|
||||
road_edge_stds[i] = edge_stds[i];
|
||||
mapLineToPolygon(road_edges[i], starpilot_toggles.value("model_ui").toBool() ? starpilot_toggles.value("road_edge_width").toDouble() : 0.025, 0, &road_edge_vertices[i], max_idx);
|
||||
}
|
||||
|
||||
// update path
|
||||
if (lead.getStatus()) {
|
||||
const float lead_d = lead.getDRel() * 2.;
|
||||
max_distance = std::clamp((float)(lead_d - fmin(lead_d * 0.35, 10.)), 0.0f, max_distance);
|
||||
}
|
||||
max_idx = get_path_length_idx(model_position, max_distance);
|
||||
float path_width = starpilot_toggles.value("path_width").toDouble();
|
||||
if (starpilot_toggles.value("dynamic_path_width").toBool()) {
|
||||
UIState *s = uiState();
|
||||
path_width *= s->status == STATUS_ENGAGED ? 1.0f : s->status == STATUS_ALWAYS_ON_LATERAL_ACTIVE ? 0.75f : 0.50f;
|
||||
}
|
||||
mapLineToPolygon(model_position, starpilot_toggles.value("model_ui").toBool() ? path_width * (1 - (starpilot_toggles.value("path_edge_width").toDouble() / 100.0f)) : 0.9, path_offset_z, &track_vertices, max_idx, false);
|
||||
|
||||
StarPilotUIState *fs = starpilotUIState();
|
||||
SubMaster &fpsm = *(fs->sm);
|
||||
|
||||
const cereal::StarPilotPlan::Reader &starpilotPlan = fpsm["starpilotPlan"].getStarpilotPlan();
|
||||
|
||||
starpilot_nvg->track_vertices = track_vertices;
|
||||
|
||||
mapLineToPolygon(model_position, starpilot_toggles.value("model_ui").toBool() ? path_width : 0, path_offset_z, &starpilot_nvg->track_edge_vertices, max_idx, false);
|
||||
|
||||
mapAveragedLineToPolygon(lane_lines[0], lane_lines[1], starpilotPlan.getLaneWidthLeft() / 2.0f, 0, &starpilot_nvg->track_adjacent_vertices[0], max_idx, height, false);
|
||||
mapAveragedLineToPolygon(lane_lines[2], lane_lines[3], starpilotPlan.getLaneWidthRight() / 2.0f, 0, &starpilot_nvg->track_adjacent_vertices[1], max_idx, height, false);
|
||||
}
|
||||
|
||||
void ModelRenderer::drawLaneLines(QPainter &painter) {
|
||||
// lanelines
|
||||
for (int i = 0; i < std::size(lane_line_vertices); ++i) {
|
||||
if (starpilot_toggles.value("color_scheme").toString() != "stock") {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(lane_line_probs[i], 0.0, 0.7)));
|
||||
} else {
|
||||
QColor lane_color = QColor(starpilot_toggles.value("lane_lines_color").toString());
|
||||
lane_color.setAlphaF(lane_color.alphaF() * std::clamp<float>(lane_line_probs[i], 0.0, 0.7));
|
||||
painter.setBrush(lane_color);
|
||||
}
|
||||
painter.drawPolygon(lane_line_vertices[i]);
|
||||
}
|
||||
|
||||
// road edges
|
||||
for (int i = 0; i < std::size(road_edge_vertices); ++i) {
|
||||
painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp<float>(1.0 - road_edge_stds[i], 0.0, 1.0)));
|
||||
painter.drawPolygon(road_edge_vertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRenderer::drawPath(QPainter &painter, const cereal::ModelDataV2::Reader &model, int height) {
|
||||
QLinearGradient bg(0, height, 0, 0);
|
||||
if (experimental_mode || starpilot_toggles.value("acceleration_path").toBool() || starpilot_toggles.value("rainbow_path").toBool()) {
|
||||
// The first half of track_vertices are the points for the right side of the path
|
||||
const auto &acceleration = model.getAcceleration().getX();
|
||||
const int max_len = std::min<int>(track_vertices.length() / 2, acceleration.size());
|
||||
|
||||
for (int i = 0; i < max_len; ++i) {
|
||||
// Some points are out of frame
|
||||
int track_idx = max_len - i - 1; // flip idx to start from bottom right
|
||||
if (track_vertices[track_idx].y() < 0 || track_vertices[track_idx].y() > height) continue;
|
||||
|
||||
// Flip so 0 is bottom of frame
|
||||
float lin_grad_point = (height - track_vertices[track_idx].y()) / height;
|
||||
|
||||
if ((fabs(acceleration[i]) < 0.25 || !starpilot_toggles.value("acceleration_path").toBool()) && starpilot_toggles.value("rainbow_path").toBool()) {
|
||||
starpilot_nvg->paintRainbowPath(painter, bg, lin_grad_point);
|
||||
} else if (fabs(acceleration[i]) < 0.25 && starpilot_toggles.value("color_scheme").toString() != "stock") {
|
||||
QColor color = QColor(starpilot_toggles.value("path_color").toString());
|
||||
color.setAlphaF(util::map_val(lin_grad_point, 0.0f, 1.0f, 1.0f, 0.1f));
|
||||
bg.setColorAt(lin_grad_point, color);
|
||||
} else {
|
||||
// speed up: 120, slow down: 0
|
||||
float path_hue = fmax(fmin(60 + acceleration[i] * 35, 120), 0);
|
||||
// FIXME: painter.drawPolygon can be slow if hue is not rounded
|
||||
path_hue = int(path_hue * 100 + 0.5) / 100;
|
||||
|
||||
float saturation = fmin(fabs(acceleration[i] * 1.5), 1);
|
||||
float lightness = util::map_val(saturation, 0.0f, 1.0f, 0.95f, 0.62f); // lighter when grey
|
||||
float alpha = util::map_val(lin_grad_point, 0.75f / 2.f, 0.75f, 0.4f, 0.0f); // matches previous alpha fade
|
||||
bg.setColorAt(lin_grad_point, QColor::fromHslF(path_hue / 360., saturation, lightness, alpha));
|
||||
|
||||
// Skip a point, unless next is last
|
||||
i += (i + 2) < max_len ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
updatePathGradient(bg);
|
||||
}
|
||||
|
||||
painter.setBrush(bg);
|
||||
painter.drawPolygon(track_vertices);
|
||||
|
||||
if (starpilot_toggles.value("adjacent_paths").toBool() || starpilot_toggles.value("adjacent_path_metrics").toBool()) {
|
||||
starpilot_nvg->paintAdjacentPaths(painter);
|
||||
} else if (starpilot_toggles.value("blind_spot_path").toBool()) {
|
||||
starpilot_nvg->paintBlindSpotPath(painter);
|
||||
}
|
||||
|
||||
starpilot_nvg->paintPathEdges(painter, height);
|
||||
}
|
||||
|
||||
void ModelRenderer::updatePathGradient(QLinearGradient &bg) {
|
||||
static const QColor throttle_colors[] = {
|
||||
QColor::fromHslF(148. / 360., 0.94, 0.51, 0.4),
|
||||
QColor::fromHslF(112. / 360., 1.0, 0.68, 0.35),
|
||||
QColor::fromHslF(112. / 360., 1.0, 0.68, 0.0)};
|
||||
|
||||
static const QColor no_throttle_colors[] = {
|
||||
QColor::fromHslF(148. / 360., 0.0, 0.95, 0.4),
|
||||
QColor::fromHslF(112. / 360., 0.0, 0.95, 0.35),
|
||||
QColor::fromHslF(112. / 360., 0.0, 0.95, 0.0),
|
||||
};
|
||||
|
||||
// Transition speed; 0.1 corresponds to 0.5 seconds at UI_FREQ
|
||||
constexpr float transition_speed = 0.1f;
|
||||
|
||||
// Start transition if throttle state changes
|
||||
bool allow_throttle = (*uiState()->sm)["longitudinalPlan"].getLongitudinalPlan().getAllowThrottle() || !longitudinal_control;
|
||||
if (allow_throttle != prev_allow_throttle) {
|
||||
prev_allow_throttle = allow_throttle;
|
||||
// Invert blend factor for a smooth transition when the state changes mid-animation
|
||||
blend_factor = std::max(1.0f - blend_factor, 0.0f);
|
||||
}
|
||||
|
||||
const QColor *begin_colors = allow_throttle ? no_throttle_colors : throttle_colors;
|
||||
const QColor *end_colors = allow_throttle ? throttle_colors : no_throttle_colors;
|
||||
if (blend_factor < 1.0f) {
|
||||
blend_factor = std::min(blend_factor + transition_speed, 1.0f);
|
||||
}
|
||||
|
||||
// Set gradient colors by blending the start and end colors
|
||||
bg.setColorAt(0.0f, blendColors(begin_colors[0], end_colors[0], blend_factor));
|
||||
bg.setColorAt(0.5f, blendColors(begin_colors[1], end_colors[1], blend_factor));
|
||||
bg.setColorAt(1.0f, blendColors(begin_colors[2], end_colors[2], blend_factor));
|
||||
}
|
||||
|
||||
QColor ModelRenderer::blendColors(const QColor &start, const QColor &end, float t) {
|
||||
if (t == 1.0f) return end;
|
||||
return QColor::fromRgbF(
|
||||
(1 - t) * start.redF() + t * end.redF(),
|
||||
(1 - t) * start.greenF() + t * end.greenF(),
|
||||
(1 - t) * start.blueF() + t * end.blueF(),
|
||||
(1 - t) * start.alphaF() + t * end.alphaF());
|
||||
}
|
||||
|
||||
void ModelRenderer::drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data,
|
||||
const QPointF &vd, const QRect &surface_rect, QColor marker_color, bool adjacent) {
|
||||
const float speedBuff = 10.;
|
||||
const float leadBuff = 40.;
|
||||
const float d_rel = lead_data.getDRel() + (adjacent ? fabs(lead_data.getYRel()) : 0);
|
||||
const float v_rel = lead_data.getVRel();
|
||||
|
||||
float fillAlpha = 0;
|
||||
if (d_rel < leadBuff) {
|
||||
fillAlpha = 255 * (1.0 - (d_rel / leadBuff));
|
||||
if (v_rel < 0) {
|
||||
fillAlpha += 255 * (-1 * (v_rel / speedBuff));
|
||||
}
|
||||
fillAlpha = (int)(fmin(fillAlpha, 255));
|
||||
}
|
||||
|
||||
float sz = std::clamp((25 * 30) / (d_rel / 3 + 30), 15.0f, 30.0f) * 2.35;
|
||||
float x = std::clamp<float>(vd.x(), 0.f, surface_rect.width() - sz / 2);
|
||||
float y = std::min<float>(vd.y(), surface_rect.height() - sz * 0.6);
|
||||
|
||||
float g_xo = sz / 5;
|
||||
float g_yo = sz / 10;
|
||||
|
||||
QPointF glow[] = {{x + (sz * 1.35) + g_xo, y + sz + g_yo}, {x, y - g_yo}, {x - (sz * 1.35) - g_xo, y + sz + g_yo}};
|
||||
painter.setBrush(QColor(218, 202, 37, 255));
|
||||
painter.drawPolygon(glow, std::size(glow));
|
||||
|
||||
// chevron
|
||||
QPointF chevron[] = {{x + (sz * 1.25), y + sz}, {x, y}, {x - (sz * 1.25), y + sz}};
|
||||
painter.setBrush(QColor(marker_color.red(), marker_color.green(), marker_color.blue(), fillAlpha));
|
||||
painter.drawPolygon(chevron, std::size(chevron));
|
||||
|
||||
if (starpilot_toggles.value("lead_info").toBool()) {
|
||||
starpilot_nvg->paintLeadMetrics(painter, adjacent, chevron, lead_data);
|
||||
}
|
||||
}
|
||||
|
||||
// Projects a point in car to space to the corresponding point in full frame image space.
|
||||
bool ModelRenderer::mapToScreen(float in_x, float in_y, float in_z, QPointF *out) {
|
||||
Eigen::Vector3f input(in_x, in_y, in_z);
|
||||
auto pt = car_space_transform * input;
|
||||
*out = QPointF(pt.x() / pt.z(), pt.y() / pt.z());
|
||||
return clip_region.contains(*out);
|
||||
}
|
||||
|
||||
void ModelRenderer::mapLineToPolygon(const cereal::XYZTData::Reader &line, float y_off, float z_off,
|
||||
QPolygonF *pvd, int max_idx, bool allow_invert) {
|
||||
const auto line_x = line.getX(), line_y = line.getY(), line_z = line.getZ();
|
||||
QPointF left, right;
|
||||
pvd->clear();
|
||||
for (int i = 0; i <= max_idx; i++) {
|
||||
// highly negative x positions are drawn above the frame and cause flickering, clip to zy plane of camera
|
||||
if (line_x[i] < 0) continue;
|
||||
|
||||
bool l = mapToScreen(line_x[i], line_y[i] - y_off, line_z[i] + z_off, &left);
|
||||
bool r = mapToScreen(line_x[i], line_y[i] + y_off, line_z[i] + z_off, &right);
|
||||
if (l && r) {
|
||||
// For wider lines the drawn polygon will "invert" when going over a hill and cause artifacts
|
||||
if (!allow_invert && pvd->size() && left.y() > pvd->back().y()) {
|
||||
continue;
|
||||
}
|
||||
pvd->push_back(left);
|
||||
pvd->push_front(right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRenderer::mapAveragedLineToPolygon(const cereal::XYZTData::Reader &line1, const cereal::XYZTData::Reader &line2, float y_off, float z_off,
|
||||
QPolygonF *pvd, int max_idx, float height, bool allow_invert) {
|
||||
const auto line_x1 = line1.getX(), line_y1 = line1.getY(), line_z1 = line1.getZ();
|
||||
const auto line_y2 = line2.getY();
|
||||
QPointF left, right;
|
||||
pvd->clear();
|
||||
for (int i = 0; i <= max_idx; i++) {
|
||||
// highly negative x positions are drawn above the frame and cause flickering, clip to zy plane of camera
|
||||
if (line_x1[i] < 0) continue;
|
||||
|
||||
bool l = mapToScreen(line_x1[i], ((line_y1[i] + line_y2[i]) / 2.0f) - y_off, line_z1[i] + z_off, &left);
|
||||
bool r = mapToScreen(line_x1[i], ((line_y1[i] + line_y2[i]) / 2.0f) + y_off, line_z1[i] + z_off, &right);
|
||||
if (l && r) {
|
||||
// For wider lines the drawn polygon will "invert" when going over a hill and cause artifacts
|
||||
if (!allow_invert && pvd->size() && left.y() > pvd->back().y()) {
|
||||
continue;
|
||||
}
|
||||
pvd->push_back(left);
|
||||
pvd->push_front(right);
|
||||
}
|
||||
}
|
||||
|
||||
// Ground the path
|
||||
if (pvd->size() >= 4) {
|
||||
int mid = pvd->size() / 2;
|
||||
|
||||
std::function<void(int, int)> extendToBottom = [&](int idx1, int idx2) {
|
||||
QPointF &p0 = (*pvd)[idx1];
|
||||
QPointF &p1 = (*pvd)[idx2];
|
||||
|
||||
float dy = p0.y() - p1.y();
|
||||
if (std::abs(dy) > 0.1f) {
|
||||
float slope = (p0.x() - p1.x()) / dy;
|
||||
p0.setX(p0.x() + (height - p0.y()) * slope);
|
||||
p0.setY(height);
|
||||
}
|
||||
};
|
||||
|
||||
extendToBottom(mid, mid + 1);
|
||||
extendToBottom(mid - 1, mid - 2);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRenderer::updateAdjacentLeads(const cereal::StarPilotRadarState::Reader &radar_state, const cereal::XYZTData::Reader &line) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const auto &lead_data = (i == 0) ? radar_state.getLeadLeft() : radar_state.getLeadRight();
|
||||
if (lead_data.getStatus()) {
|
||||
float z = line.getZ()[get_path_length_idx(line, lead_data.getDRel())];
|
||||
mapToScreen(lead_data.getDRel(), -lead_data.getYRel(), z + path_offset_z, &adjacent_lead_vertices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRenderer::updateRadarTracks(const cereal::XYZTData::Reader &line) {
|
||||
std::vector<QPointF> &radar_tracks = starpilot_nvg->radar_tracks;
|
||||
radar_tracks.clear();
|
||||
|
||||
SubMaster &fpsm = *(starpilotUIState()->sm);
|
||||
capnp::List<cereal::RadarData::RadarPoint>::Reader radar_points = fpsm["liveTracks"].getLiveTracks().getPoints();
|
||||
radar_tracks.reserve(radar_points.size());
|
||||
|
||||
capnp::List<float>::Reader line_z = line.getZ();
|
||||
|
||||
for (cereal::RadarData::RadarPoint::Reader point : radar_points) {
|
||||
float d_rel = point.getDRel();
|
||||
float z = line_z[get_path_length_idx(line, d_rel)];
|
||||
|
||||
QPointF calibrated_point;
|
||||
if (mapToScreen(d_rel, -point.getYRel(), z + path_offset_z, &calibrated_point)) {
|
||||
radar_tracks.push_back(calibrated_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPolygonF>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
#include "starpilot/ui/qt/onroad/starpilot_annotated_camera.h"
|
||||
|
||||
class ModelRenderer {
|
||||
public:
|
||||
ModelRenderer() {}
|
||||
void setTransform(const Eigen::Matrix3f &transform) { car_space_transform = transform; }
|
||||
void draw(QPainter &painter, const QRect &surface_rect);
|
||||
|
||||
StarPilotAnnotatedCameraWidget *starpilot_nvg;
|
||||
|
||||
StarPilotUIScene starpilot_scene;
|
||||
|
||||
QJsonObject starpilot_toggles;
|
||||
|
||||
private:
|
||||
bool mapToScreen(float in_x, float in_y, float in_z, QPointF *out);
|
||||
void mapLineToPolygon(const cereal::XYZTData::Reader &line, float y_off, float z_off,
|
||||
QPolygonF *pvd, int max_idx, bool allow_invert = true);
|
||||
void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd, const QRect &surface_rect, QColor marker_color, bool adjacent=false);
|
||||
void update_leads(const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line);
|
||||
void update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead, float height);
|
||||
void drawLaneLines(QPainter &painter);
|
||||
void drawPath(QPainter &painter, const cereal::ModelDataV2::Reader &model, int height);
|
||||
void updatePathGradient(QLinearGradient &bg);
|
||||
QColor blendColors(const QColor &start, const QColor &end, float t);
|
||||
|
||||
bool longitudinal_control = false;
|
||||
bool experimental_mode = false;
|
||||
float blend_factor = 1.0f;
|
||||
bool prev_allow_throttle = true;
|
||||
float lane_line_probs[4] = {};
|
||||
float road_edge_stds[2] = {};
|
||||
float path_offset_z = 1.22f;
|
||||
QPolygonF track_vertices;
|
||||
QPolygonF lane_line_vertices[4] = {};
|
||||
QPolygonF road_edge_vertices[2] = {};
|
||||
QPointF lead_vertices[2] = {};
|
||||
Eigen::Matrix3f car_space_transform = Eigen::Matrix3f::Zero();
|
||||
QRectF clip_region;
|
||||
|
||||
void mapAveragedLineToPolygon(const cereal::XYZTData::Reader &line1, const cereal::XYZTData::Reader &line2, float y_off, float z_off,
|
||||
QPolygonF *pvd, int max_idx, float height, bool allow_invert = true);
|
||||
void updateAdjacentLeads(const cereal::StarPilotRadarState::Reader &radar_state, const cereal::XYZTData::Reader &line);
|
||||
void updateRadarTracks(const cereal::XYZTData::Reader &line);
|
||||
|
||||
QPointF adjacent_lead_vertices[2] = {};
|
||||
};
|
||||
@@ -1,149 +0,0 @@
|
||||
#include "selfdrive/ui/qt/onroad/onroad_home.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStackedLayout>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
main_layout->setMargin(UI_BORDER_SIZE);
|
||||
QStackedLayout *stacked_layout = new QStackedLayout;
|
||||
stacked_layout->setStackingMode(QStackedLayout::StackAll);
|
||||
main_layout->addLayout(stacked_layout);
|
||||
|
||||
nvg = new AnnotatedCameraWidget(VISION_STREAM_ROAD, this);
|
||||
|
||||
QWidget * split_wrapper = new QWidget;
|
||||
split = new QHBoxLayout(split_wrapper);
|
||||
split->setContentsMargins(0, 0, 0, 0);
|
||||
split->setSpacing(0);
|
||||
split->addWidget(nvg);
|
||||
|
||||
if (getenv("DUAL_CAMERA_VIEW")) {
|
||||
CameraWidget *arCam = new CameraWidget("camerad", VISION_STREAM_ROAD, this);
|
||||
split->insertWidget(0, arCam);
|
||||
}
|
||||
|
||||
stacked_layout->addWidget(split_wrapper);
|
||||
|
||||
alerts = new OnroadAlerts(this);
|
||||
alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
stacked_layout->addWidget(alerts);
|
||||
|
||||
// setup stacking order
|
||||
alerts->raise();
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &OnroadWindow::updateState);
|
||||
QObject::connect(uiState(), &UIState::offroadTransition, this, &OnroadWindow::offroadTransition);
|
||||
|
||||
starpilot_nvg = new StarPilotAnnotatedCameraWidget(this);
|
||||
starpilot_onroad = new StarPilotOnroadWindow(this);
|
||||
starpilot_onroad->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
|
||||
stacked_layout->addWidget(starpilot_nvg);
|
||||
stacked_layout->addWidget(starpilot_onroad);
|
||||
|
||||
starpilot_onroad->raise();
|
||||
alerts->raise();
|
||||
|
||||
nvg->starpilot_nvg = starpilot_nvg;
|
||||
}
|
||||
|
||||
void OnroadWindow::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
if (!s.scene.started) {
|
||||
return;
|
||||
}
|
||||
|
||||
alerts->updateState(s, fs);
|
||||
nvg->updateState(s, fs);
|
||||
|
||||
const StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
const QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
const auto selfdriveState = (*s.sm)["selfdriveState"].getSelfdriveState();
|
||||
const bool enabled = selfdriveState.getEnabled();
|
||||
QColor bgColor = bg_colors[s.status];
|
||||
const bool conditional_experimental_mode = starpilot_toggles.value("conditional_experimental_mode").toBool();
|
||||
const bool conditional_chill_mode = starpilot_toggles.value("conditional_chill_mode").toBool();
|
||||
const bool highlight_override =
|
||||
enabled && ((conditional_experimental_mode && starpilot_scene.conditional_status == 1) ||
|
||||
(conditional_chill_mode && (starpilot_scene.conditional_status == 1 || starpilot_scene.conditional_status == 2)));
|
||||
if (starpilot_scene.switchback_mode_enabled && (enabled || starpilot_scene.always_on_lateral_active)) {
|
||||
bgColor = bg_colors[STATUS_SWITCHBACK_MODE_ENABLED];
|
||||
} else if (starpilot_scene.always_on_lateral_active) {
|
||||
bgColor = bg_colors[STATUS_ALWAYS_ON_LATERAL_ACTIVE];
|
||||
} else if (highlight_override) {
|
||||
bgColor = bg_colors[STATUS_CEM_DISABLED];
|
||||
} else if (enabled && selfdriveState.getExperimentalMode()) {
|
||||
bgColor = bg_colors[STATUS_EXPERIMENTAL_MODE_ENABLED];
|
||||
} else if (starpilot_scene.traffic_mode_enabled && enabled) {
|
||||
bgColor = bg_colors[STATUS_TRAFFIC_MODE_ENABLED];
|
||||
}
|
||||
|
||||
if (bg != bgColor) {
|
||||
// repaint border
|
||||
bg = bgColor;
|
||||
update();
|
||||
}
|
||||
starpilot_nvg->alertHeight = alerts->alertHeight;
|
||||
|
||||
starpilot_onroad->bg = bg;
|
||||
starpilot_onroad->fps = nvg->fps;
|
||||
|
||||
nvg->starpilot_nvg = starpilot_nvg;
|
||||
|
||||
nvg->starpilot_scene = starpilot_scene;
|
||||
starpilot_nvg->starpilot_scene = starpilot_scene;
|
||||
starpilot_onroad->starpilot_scene = starpilot_scene;
|
||||
|
||||
alerts->starpilot_toggles = starpilot_toggles;
|
||||
starpilot_nvg->starpilot_toggles = starpilot_toggles;
|
||||
starpilot_onroad->starpilot_toggles = starpilot_toggles;
|
||||
nvg->starpilot_toggles = starpilot_toggles;
|
||||
|
||||
starpilot_onroad->setGeometry(rect());
|
||||
|
||||
starpilot_nvg->updateState(s, fs);
|
||||
starpilot_onroad->updateState(s, fs);
|
||||
}
|
||||
|
||||
void OnroadWindow::offroadTransition(bool offroad) {
|
||||
alerts->clear();
|
||||
}
|
||||
|
||||
void OnroadWindow::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
|
||||
}
|
||||
|
||||
void OnroadWindow::mousePressEvent(QMouseEvent* mouseEvent) {
|
||||
if (nvg->handleHudPress(mouseEvent->pos())) {
|
||||
grabMouse();
|
||||
mouseEvent->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
starpilot_nvg->mousePressEvent(mouseEvent);
|
||||
|
||||
if (mouseEvent->isAccepted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// propagation event to parent(HomeWindow)
|
||||
QWidget::mousePressEvent(mouseEvent);
|
||||
}
|
||||
|
||||
void OnroadWindow::mouseReleaseEvent(QMouseEvent* mouseEvent) {
|
||||
const bool handled = nvg->handleHudRelease(mouseEvent->pos());
|
||||
if (QWidget::mouseGrabber() == this) {
|
||||
releaseMouse();
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
mouseEvent->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget::mouseReleaseEvent(mouseEvent);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "selfdrive/ui/qt/onroad/alerts.h"
|
||||
#include "selfdrive/ui/qt/onroad/annotated_camera.h"
|
||||
|
||||
#include "starpilot/ui/qt/onroad/starpilot_onroad.h"
|
||||
|
||||
class OnroadWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OnroadWindow(QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
OnroadAlerts *alerts;
|
||||
AnnotatedCameraWidget *nvg;
|
||||
QColor bg = bg_colors[STATUS_DISENGAGED];
|
||||
QHBoxLayout* split;
|
||||
|
||||
void mousePressEvent(QMouseEvent* mouseEvent);
|
||||
void mouseReleaseEvent(QMouseEvent* mouseEvent);
|
||||
|
||||
StarPilotAnnotatedCameraWidget *starpilot_nvg;
|
||||
StarPilotOnroadWindow *starpilot_onroad;
|
||||
|
||||
private slots:
|
||||
void offroadTransition(bool offroad);
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
#include "selfdrive/ui/qt/prime_state.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "selfdrive/ui/qt/api.h"
|
||||
#include "selfdrive/ui/qt/request_repeater.h"
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
PrimeState::PrimeState(QObject* parent) : QObject(parent) {
|
||||
const char *env_prime_type = std::getenv("PRIME_TYPE");
|
||||
auto type = env_prime_type ? env_prime_type : Params().get("PrimeType");
|
||||
|
||||
if (!type.empty()) {
|
||||
prime_type = static_cast<PrimeState::Type>(std::atoi(type.c_str()));
|
||||
}
|
||||
|
||||
if (auto dongleId = getDongleId()) {
|
||||
QString url = CommaApi::BASE_URL + "/v1.1/devices/" + *dongleId + "/";
|
||||
RequestRepeater* repeater = new RequestRepeater(this, url, "ApiCache_Device", 60);
|
||||
QObject::connect(repeater, &RequestRepeater::requestDone, this, &PrimeState::handleReply);
|
||||
}
|
||||
|
||||
// Emit the initial state change
|
||||
QTimer::singleShot(1, [this]() { emit changed(prime_type); });
|
||||
}
|
||||
|
||||
void PrimeState::handleReply(const QString& response, bool success) {
|
||||
if (!success) return;
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
|
||||
if (doc.isNull()) {
|
||||
qDebug() << "JSON Parse failed on getting pairing and PrimeState status";
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject json = doc.object();
|
||||
bool is_paired = json["is_paired"].toBool();
|
||||
auto type = static_cast<PrimeState::Type>(json["prime_type"].toInt());
|
||||
setType(is_paired ? type : PrimeState::PRIME_TYPE_UNPAIRED);
|
||||
}
|
||||
|
||||
void PrimeState::setType(PrimeState::Type type) {
|
||||
if (type != prime_type) {
|
||||
prime_type = type;
|
||||
Params().put("PrimeType", std::to_string(prime_type));
|
||||
emit changed(prime_type);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class PrimeState : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
PRIME_TYPE_UNKNOWN = -2,
|
||||
PRIME_TYPE_UNPAIRED = -1,
|
||||
PRIME_TYPE_NONE = 0,
|
||||
PRIME_TYPE_MAGENTA = 1,
|
||||
PRIME_TYPE_LITE = 2,
|
||||
PRIME_TYPE_BLUE = 3,
|
||||
PRIME_TYPE_MAGENTA_NEW = 4,
|
||||
PRIME_TYPE_PURPLE = 5,
|
||||
};
|
||||
|
||||
PrimeState(QObject *parent);
|
||||
void setType(PrimeState::Type type);
|
||||
inline PrimeState::Type currentType() const { return prime_type; }
|
||||
inline bool isSubscribed() const { return prime_type > PrimeState::PRIME_TYPE_NONE; }
|
||||
|
||||
signals:
|
||||
void changed(PrimeState::Type prime_type);
|
||||
|
||||
private:
|
||||
void handleReply(const QString &response, bool success);
|
||||
|
||||
PrimeState::Type prime_type = PrimeState::PRIME_TYPE_UNKNOWN;
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "selfdrive/ui/qt/qt_window.h"
|
||||
|
||||
void setMainWindow(QWidget *w) {
|
||||
const float scale = util::getenv("SCALE", 1.0f);
|
||||
const QSize sz = QGuiApplication::primaryScreen()->size();
|
||||
|
||||
if (Hardware::PC() && scale == 1.0 && !(sz - DEVICE_SCREEN_SIZE).isValid()) {
|
||||
w->setMinimumSize(QSize(640, 480)); // allow resize smaller than fullscreen
|
||||
w->setMaximumSize(DEVICE_SCREEN_SIZE);
|
||||
w->resize(sz);
|
||||
} else {
|
||||
w->setFixedSize(DEVICE_SCREEN_SIZE * scale);
|
||||
}
|
||||
w->show();
|
||||
|
||||
#ifdef QCOM2
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", w->windowHandle()));
|
||||
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
|
||||
wl_surface_commit(s);
|
||||
|
||||
w->setWindowState(Qt::WindowFullScreen);
|
||||
w->setVisible(true);
|
||||
|
||||
// ensure we have a valid eglDisplay, otherwise the ui will silently fail
|
||||
void *egl = native->nativeResourceForWindow("egldisplay", w->windowHandle());
|
||||
assert(egl != nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
void set_main_window(void *w) {
|
||||
setMainWindow((QWidget*)w);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
#include <QWidget>
|
||||
|
||||
#ifdef QCOM2
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#endif
|
||||
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
const QString ASSET_PATH = ":/";
|
||||
const QSize DEVICE_SCREEN_SIZE = {2160, 1080};
|
||||
|
||||
void setMainWindow(QWidget *w);
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "selfdrive/ui/qt/request_repeater.h"
|
||||
|
||||
RequestRepeater::RequestRepeater(QObject *parent, const QString &requestURL, const QString &cacheKey,
|
||||
int period, bool while_onroad) : HttpRequest(parent) {
|
||||
timer = new QTimer(this);
|
||||
timer->setTimerType(Qt::VeryCoarseTimer);
|
||||
QObject::connect(timer, &QTimer::timeout, [=]() {
|
||||
if ((!uiState()->scene.started || while_onroad) && device()->isAwake() && !active()) {
|
||||
sendRequest(requestURL);
|
||||
}
|
||||
});
|
||||
|
||||
timer->start(period * 1000);
|
||||
|
||||
if (!cacheKey.isEmpty()) {
|
||||
prevResp = QString::fromStdString(params.get(cacheKey.toStdString()));
|
||||
if (!prevResp.isEmpty()) {
|
||||
QTimer::singleShot(500, [=]() { emit requestDone(prevResp, true, QNetworkReply::NoError); });
|
||||
}
|
||||
QObject::connect(this, &HttpRequest::requestDone, [=](const QString &resp, bool success) {
|
||||
if (success && resp != prevResp) {
|
||||
params.put(cacheKey.toStdString(), resp.toStdString());
|
||||
prevResp = resp;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/util.h"
|
||||
#include "selfdrive/ui/qt/api.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
class RequestRepeater : public HttpRequest {
|
||||
public:
|
||||
RequestRepeater(QObject *parent, const QString &requestURL, const QString &cacheKey = "", int period = 0, bool while_onroad=false);
|
||||
|
||||
private:
|
||||
Params params;
|
||||
QTimer *timer;
|
||||
QString prevResp;
|
||||
};
|
||||
@@ -1,336 +0,0 @@
|
||||
#include "selfdrive/ui/qt/sidebar.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
void Sidebar::drawMetric(QPainter &p, const QPair<QString, QString> &label, QColor c, int y) {
|
||||
const QRect rect = {30, y, 240, 126};
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QBrush(c));
|
||||
p.setClipRect(rect.x() + 4, rect.y(), 18, rect.height(), Qt::ClipOperation::ReplaceClip);
|
||||
p.drawRoundedRect(QRect(rect.x() + 4, rect.y() + 4, 100, 118), 18, 18);
|
||||
p.setClipping(false);
|
||||
|
||||
QPen pen = QPen(QColor(0xff, 0xff, 0xff, 0x55));
|
||||
pen.setWidth(2);
|
||||
p.setPen(pen);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRoundedRect(rect, 20, 20);
|
||||
|
||||
p.setPen(QColor(0xff, 0xff, 0xff));
|
||||
p.setFont(InterFont(35, QFont::DemiBold));
|
||||
p.drawText(rect.adjusted(22, 0, 0, 0), Qt::AlignCenter, label.first + "\n" + label.second);
|
||||
}
|
||||
|
||||
Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false), mic_indicator_pressed(false) {
|
||||
home_img = loadPixmap("../assets/images/button_home.png", home_btn.size());
|
||||
flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size());
|
||||
settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio);
|
||||
mic_img = loadPixmap("../assets/icons/microphone.png", QSize(30, 30));
|
||||
link_img = loadPixmap("../assets/icons/link.png", QSize(60, 60));
|
||||
|
||||
connect(this, &Sidebar::valueChanged, [=] { update(); });
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
setFixedWidth(300);
|
||||
|
||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &Sidebar::updateState);
|
||||
|
||||
pm = std::make_unique<PubMaster>(std::vector<const char*>{"bookmarkButton"});
|
||||
|
||||
QObject::connect(starpilotUIState(), &StarPilotUIState::themeUpdated, this, &Sidebar::updateTheme);
|
||||
}
|
||||
|
||||
void Sidebar::mousePressEvent(QMouseEvent *event) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
static constexpr QRect cpuRect = {30, 496, 240, 126};
|
||||
static constexpr QRect memoryRect = {30, 654, 240, 126};
|
||||
static constexpr QRect tempRect = {30, 338, 240, 126};
|
||||
|
||||
static int showChip = 0;
|
||||
static int showMemory = 0;
|
||||
static int showTemp = 0;
|
||||
|
||||
StarPilotUIState *fs = starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs->starpilot_scene;
|
||||
QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
const bool simple_mode = starpilot_toggles.value("simple_mode").toBool();
|
||||
|
||||
if (!simple_mode && cpuRect.contains(pos) && starpilot_toggles.value("developer_ui").toBool()) {
|
||||
showChip = (showChip + 1) % 3;
|
||||
|
||||
params.putBool("ShowCPU", showChip == 1);
|
||||
params.putBool("ShowGPU", showChip == 2);
|
||||
} else if (!simple_mode && memoryRect.contains(pos) && starpilot_toggles.value("developer_ui").toBool()) {
|
||||
showMemory = (showMemory + 1) % 4;
|
||||
|
||||
params.putBool("ShowMemoryUsage", showMemory == 1);
|
||||
params.putBool("ShowStorageLeft", showMemory == 2);
|
||||
params.putBool("ShowStorageUsed", showMemory == 3);
|
||||
} else if (!simple_mode && tempRect.contains(pos) && starpilot_toggles.value("developer_ui").toBool()) {
|
||||
showTemp = (showTemp + 1) % 3;
|
||||
|
||||
params.putBool("Fahrenheit", showTemp == 2);
|
||||
params.putBool("NumericalTemp", showTemp != 0);
|
||||
} else if (onroad && home_btn.contains(pos)) {
|
||||
flag_pressed = true;
|
||||
} else if (settings_btn.contains(pos)) {
|
||||
settings_pressed = true;
|
||||
} else if (recording_audio && mic_indicator_btn.contains(event->pos())) {
|
||||
mic_indicator_pressed = true;
|
||||
}
|
||||
|
||||
if (!(flag_pressed || mic_indicator_pressed || settings_pressed)) {
|
||||
update();
|
||||
updateStarPilotToggles();
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (flag_pressed || settings_pressed || mic_indicator_pressed) {
|
||||
flag_pressed = settings_pressed = mic_indicator_pressed = false;
|
||||
update();
|
||||
}
|
||||
if (onroad && home_btn.contains(event->pos())) {
|
||||
MessageBuilder msg;
|
||||
msg.initEvent().initBookmarkButton();
|
||||
pm->send("bookmarkButton", msg);
|
||||
} else if (settings_btn.contains(event->pos())) {
|
||||
emit openSettings();
|
||||
} else if (recording_audio && mic_indicator_btn.contains(event->pos())) {
|
||||
emit openSettings(2, "RecordAudio");
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::offroadTransition(bool offroad) {
|
||||
onroad = !offroad;
|
||||
update();
|
||||
}
|
||||
|
||||
void Sidebar::updateState(const UIState &s, const StarPilotUIState &fs) {
|
||||
if (!isVisible()) return;
|
||||
|
||||
const StarPilotUIScene &starpilot_scene = fs.starpilot_scene;
|
||||
const QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
const bool simple_mode = starpilot_toggles.value("simple_mode").toBool();
|
||||
static bool previous_simple_mode = simple_mode;
|
||||
if (previous_simple_mode != simple_mode) {
|
||||
updateTheme();
|
||||
previous_simple_mode = simple_mode;
|
||||
}
|
||||
|
||||
const SubMaster &fpsm = *(fs.sm);
|
||||
|
||||
const cereal::StarPilotDeviceState::Reader &starpilotDeviceState = fpsm["starpilotDeviceState"].getStarpilotDeviceState();
|
||||
|
||||
auto &sm = *(s.sm);
|
||||
|
||||
networking = networking ? networking : window()->findChild<Networking *>("");
|
||||
bool tethering_on = networking && networking->wifi->tethering_on;
|
||||
auto deviceState = sm["deviceState"].getDeviceState();
|
||||
|
||||
const char *desktop_fake_wifi_env = std::getenv("SP_ALLOW_DESKTOP_FAKE_WIFI");
|
||||
const bool desktop_force_online = Hardware::PC() && desktop_fake_wifi_env != nullptr && std::string(desktop_fake_wifi_env) != "0";
|
||||
|
||||
auto net_type_value = desktop_force_online ? cereal::DeviceState::NetworkType::WIFI : deviceState.getNetworkType();
|
||||
setProperty("netType", tethering_on ? "Hotspot" : network_type[net_type_value]);
|
||||
int strength = tethering_on ? 4 : (desktop_force_online ? 4 : (int)deviceState.getNetworkStrength());
|
||||
setProperty("netStrength", strength > 0 ? strength + 1 : 0);
|
||||
|
||||
ItemStatus connectStatus;
|
||||
auto last_ping = deviceState.getLastAthenaPingTime();
|
||||
if (desktop_force_online) {
|
||||
connectStatus = ItemStatus{{tr("CONNECT"), tr("ONLINE")}, simple_mode ? good_color : QColor(starpilot_toggles.value("sidebar_color3").toString())};
|
||||
} else if (last_ping == 0) {
|
||||
connectStatus = ItemStatus{{tr("CONNECT"), tr("OFFLINE")}, warning_color};
|
||||
} else {
|
||||
connectStatus = nanos_since_boot() - last_ping < 80e9
|
||||
? ItemStatus{{tr("CONNECT"), tr("ONLINE")}, simple_mode ? good_color : QColor(starpilot_toggles.value("sidebar_color3").toString())}
|
||||
: ItemStatus{{tr("CONNECT"), tr("ERROR")}, danger_color};
|
||||
}
|
||||
setProperty("connectStatus", QVariant::fromValue(connectStatus));
|
||||
|
||||
int maxTempC = deviceState.getMaxTempC();
|
||||
QString max_temp = starpilot_toggles.value("fahrenheit").toBool() ? QString::number(maxTempC * 9 / 5 + 32) + "°F" : QString::number(maxTempC) + "°C";
|
||||
ItemStatus tempStatus = {{tr("TEMP"), simple_mode ? tr("HIGH") : (starpilot_toggles.value("numerical_temp").toBool() ? max_temp : tr("HIGH"))}, danger_color};
|
||||
auto ts = deviceState.getThermalStatus();
|
||||
if (ts == cereal::DeviceState::ThermalStatus::GREEN) {
|
||||
tempStatus = {{tr("TEMP"), simple_mode ? tr("GOOD") : (starpilot_toggles.value("numerical_temp").toBool() ? max_temp : tr("GOOD"))},
|
||||
simple_mode ? good_color : QColor(starpilot_toggles.value("sidebar_color1").toString())};
|
||||
} else if (ts == cereal::DeviceState::ThermalStatus::YELLOW) {
|
||||
tempStatus = {{tr("TEMP"), simple_mode ? tr("OK") : (starpilot_toggles.value("numerical_temp").toBool() ? max_temp : tr("OK"))}, warning_color};
|
||||
}
|
||||
setProperty("tempStatus", QVariant::fromValue(tempStatus));
|
||||
|
||||
ItemStatus pandaStatus = {{tr("VEHICLE"), tr("ONLINE")}, simple_mode ? good_color : QColor(starpilot_toggles.value("sidebar_color2").toString())};
|
||||
if (s.scene.pandaType == cereal::PandaState::PandaType::UNKNOWN) {
|
||||
pandaStatus = {{tr("NO"), tr("PANDA")}, danger_color};
|
||||
}
|
||||
setProperty("pandaStatus", QVariant::fromValue(pandaStatus));
|
||||
|
||||
setProperty("recordingAudio", s.scene.recording_audio);
|
||||
|
||||
if (!simple_mode && (starpilot_toggles.value("cpu_metrics").toBool() || starpilot_toggles.value("gpu_metrics").toBool())) {
|
||||
capnp::List<int8_t>::Reader cpu_loads = deviceState.getCpuUsagePercent();
|
||||
int cpu_usage = cpu_loads.size() != 0 ? std::accumulate(cpu_loads.begin(), cpu_loads.end(), 0) / cpu_loads.size() : 0;
|
||||
int gpu_usage = deviceState.getGpuUsagePercent();
|
||||
int usage = starpilot_toggles.value("cpu_metrics").toBool() ? cpu_usage : gpu_usage;
|
||||
|
||||
QString chip_usage = QString::number(usage) + "%";
|
||||
|
||||
ItemStatus chipStatus = {{starpilot_toggles.value("gpu_metrics").toBool() ? tr("GPU") : tr("CPU"), chip_usage}, QColor(starpilot_toggles.value("sidebar_color2").toString())};
|
||||
if (usage >= 85) {
|
||||
chipStatus = {{starpilot_toggles.value("gpu_metrics").toBool() ? tr("GPU") : tr("CPU"), chip_usage}, danger_color};
|
||||
} else if (usage >= 70) {
|
||||
chipStatus = {{starpilot_toggles.value("gpu_metrics").toBool() ? tr("GPU") : tr("CPU"), chip_usage}, warning_color};
|
||||
}
|
||||
setProperty("chipStatus", QVariant::fromValue(chipStatus));
|
||||
}
|
||||
|
||||
if (!simple_mode && (starpilot_toggles.value("memory_metrics").toBool() || starpilot_toggles.value("storage_left_metrics").toBool() || starpilot_toggles.value("storage_used_metrics").toBool())) {
|
||||
int free_space = deviceState.getFreeSpacePercent();
|
||||
int memory_usage = deviceState.getMemoryUsagePercent();
|
||||
int storage_left = starpilotDeviceState.getFreeSpace();
|
||||
int storage_used = starpilotDeviceState.getUsedSpace();
|
||||
|
||||
QString memory = QString::number(memory_usage) + "%";
|
||||
QString storage = QString::number(starpilot_toggles.value("storage_left_metrics").toBool() ? storage_left : storage_used) + tr(" GB");
|
||||
|
||||
if (starpilot_toggles.value("memory_metrics").toBool()) {
|
||||
ItemStatus memoryStatus = {{tr("MEMORY"), memory}, QColor(starpilot_toggles.value("sidebar_color3").toString())};
|
||||
if (memory_usage >= 85) {
|
||||
memoryStatus = {{tr("MEMORY"), memory}, danger_color};
|
||||
} else if (memory_usage >= 70) {
|
||||
memoryStatus = {{tr("MEMORY"), memory}, warning_color};
|
||||
}
|
||||
setProperty("memoryStatus", QVariant::fromValue(memoryStatus));
|
||||
} else {
|
||||
ItemStatus storageStatus = {{starpilot_toggles.value("storage_left_metrics").toBool() ? tr("LEFT") : tr("USED"), storage}, QColor(starpilot_toggles.value("sidebar_color3").toString())};
|
||||
if (free_space < 25 && free_space >= 10) {
|
||||
storageStatus = {{starpilot_toggles.value("storage_left_metrics").toBool() ? tr("LEFT") : tr("USED"), storage}, warning_color};
|
||||
} else if (10 > free_space) {
|
||||
storageStatus = {{starpilot_toggles.value("storage_left_metrics").toBool() ? tr("LEFT") : tr("USED"), storage}, danger_color};
|
||||
}
|
||||
setProperty("storageStatus", QVariant::fromValue(storageStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
p.fillRect(rect(), QColor(57, 57, 57));
|
||||
|
||||
// buttons
|
||||
p.setOpacity(settings_pressed ? 0.65 : 1.0);
|
||||
p.drawPixmap(settings_btn.x(), settings_btn.y(), settings_gif ? settings_gif->currentPixmap() : settings_img);
|
||||
p.setOpacity(onroad && flag_pressed ? 0.65 : 1.0);
|
||||
p.drawPixmap(home_btn.x(), home_btn.y(), onroad ? flag_gif ? flag_gif->currentPixmap() : flag_img : home_gif ? home_gif->currentPixmap() : home_img);
|
||||
if (recording_audio) {
|
||||
p.setBrush(danger_color);
|
||||
p.setOpacity(mic_indicator_pressed ? 0.65 : 1.0);
|
||||
p.drawRoundedRect(mic_indicator_btn, mic_indicator_btn.height() / 2, mic_indicator_btn.height() / 2);
|
||||
int icon_x = mic_indicator_btn.x() + (mic_indicator_btn.width() - mic_img.width()) / 2;
|
||||
int icon_y = mic_indicator_btn.y() + (mic_indicator_btn.height() - mic_img.height()) / 2;
|
||||
p.drawPixmap(icon_x, icon_y, mic_img);
|
||||
}
|
||||
p.setOpacity(1.0);
|
||||
|
||||
StarPilotUIState *fs = starpilotUIState();
|
||||
StarPilotUIScene &starpilot_scene = fs->starpilot_scene;
|
||||
QJsonObject &starpilot_toggles = starpilot_scene.starpilot_toggles;
|
||||
const bool simple_mode = starpilot_toggles.value("simple_mode").toBool();
|
||||
|
||||
// network
|
||||
if (!simple_mode && starpilot_toggles.value("ip_metrics").toBool()) {
|
||||
p.setPen(QColor(0xff, 0xff, 0xff));
|
||||
p.save();
|
||||
p.setFont(InterFont(30));
|
||||
p.drawText(QRect(50, 196, 225, 27), Qt::AlignLeft | Qt::AlignVCenter, starpilotUIState()->wifi->getIp4Address());
|
||||
p.restore();
|
||||
} else {
|
||||
int x = 58;
|
||||
const QColor gray(0x54, 0x54, 0x54);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
p.setBrush(i < net_strength ? Qt::white : gray);
|
||||
p.drawEllipse(x, 196, 27, 27);
|
||||
x += 37;
|
||||
}
|
||||
}
|
||||
|
||||
p.setFont(InterFont(35));
|
||||
p.setPen(QColor(0xff, 0xff, 0xff));
|
||||
const QRect r = QRect(58, 247, width() - 100, 50);
|
||||
|
||||
if (net_type == "Hotspot") {
|
||||
p.drawPixmap(r.x(), r.y() + (r.height() - link_img.height()) / 2, link_img);
|
||||
} else {
|
||||
p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, net_type);
|
||||
}
|
||||
|
||||
// metrics
|
||||
drawMetric(p, temp_status.first, temp_status.second, 338);
|
||||
if (simple_mode) {
|
||||
drawMetric(p, panda_status.first, panda_status.second, 496);
|
||||
drawMetric(p, connect_status.first, connect_status.second, 654);
|
||||
} else if (starpilot_toggles.value("cpu_metrics").toBool() || starpilot_toggles.value("gpu_metrics").toBool()) {
|
||||
drawMetric(p, chip_status.first, chip_status.second, 496);
|
||||
} else {
|
||||
drawMetric(p, panda_status.first, panda_status.second, 496);
|
||||
}
|
||||
if (starpilot_toggles.value("memory_metrics").toBool()) {
|
||||
drawMetric(p, memory_status.first, memory_status.second, 654);
|
||||
} else if (starpilot_toggles.value("storage_left_metrics").toBool() || starpilot_toggles.value("storage_used_metrics").toBool()) {
|
||||
drawMetric(p, storage_status.first, storage_status.second, 654);
|
||||
} else {
|
||||
drawMetric(p, connect_status.first, connect_status.second, 654);
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::showEvent(QShowEvent *event) {
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
void Sidebar::updateTheme() {
|
||||
auto clearMovie = [](QSharedPointer<QMovie> &movie) {
|
||||
if (!movie.isNull()) {
|
||||
movie->stop();
|
||||
movie.reset();
|
||||
}
|
||||
};
|
||||
|
||||
if (starpilotUIState()->starpilot_scene.starpilot_toggles.value("simple_mode").toBool()) {
|
||||
clearMovie(home_gif);
|
||||
clearMovie(flag_gif);
|
||||
clearMovie(settings_gif);
|
||||
|
||||
home_img = loadPixmap("../assets/images/button_home.png", home_btn.size());
|
||||
flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size());
|
||||
settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio);
|
||||
return;
|
||||
}
|
||||
|
||||
loadImage("../../starpilot/assets/active_theme/icons/button_home", home_img, home_gif, home_btn.size(), this);
|
||||
loadImage("../../starpilot/assets/active_theme/icons/button_flag", flag_img, flag_gif, home_btn.size(), this);
|
||||
loadImage("../../starpilot/assets/active_theme/icons/button_settings", settings_img, settings_gif, settings_btn.size(), this);
|
||||
|
||||
// Keep stock icons visible when a theme is partial or missing an icon.
|
||||
if (!home_gif && home_img.isNull()) {
|
||||
home_img = loadPixmap("../assets/images/button_home.png", home_btn.size());
|
||||
}
|
||||
if (!flag_gif && flag_img.isNull()) {
|
||||
flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size());
|
||||
}
|
||||
if (!settings_gif && settings_img.isNull()) {
|
||||
settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QFrame>
|
||||
#include <QMap>
|
||||
|
||||
#include "selfdrive/ui/ui.h"
|
||||
#include "selfdrive/ui/qt/network/networking.h"
|
||||
|
||||
typedef QPair<QPair<QString, QString>, QColor> ItemStatus;
|
||||
Q_DECLARE_METATYPE(ItemStatus);
|
||||
|
||||
class Sidebar : public QFrame {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ItemStatus connectStatus MEMBER connect_status NOTIFY valueChanged);
|
||||
Q_PROPERTY(ItemStatus pandaStatus MEMBER panda_status NOTIFY valueChanged);
|
||||
Q_PROPERTY(ItemStatus tempStatus MEMBER temp_status NOTIFY valueChanged);
|
||||
Q_PROPERTY(QString netType MEMBER net_type NOTIFY valueChanged);
|
||||
Q_PROPERTY(int netStrength MEMBER net_strength NOTIFY valueChanged);
|
||||
Q_PROPERTY(bool recordingAudio MEMBER recording_audio NOTIFY valueChanged);
|
||||
|
||||
// Additional properties
|
||||
Q_PROPERTY(ItemStatus chipStatus MEMBER chip_status NOTIFY valueChanged)
|
||||
Q_PROPERTY(ItemStatus memoryStatus MEMBER memory_status NOTIFY valueChanged)
|
||||
Q_PROPERTY(ItemStatus storageStatus MEMBER storage_status NOTIFY valueChanged)
|
||||
|
||||
public:
|
||||
explicit Sidebar(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void openSettings(int index = 0, const QString ¶m = "");
|
||||
void valueChanged();
|
||||
|
||||
public slots:
|
||||
void offroadTransition(bool offroad);
|
||||
void updateState(const UIState &s, const StarPilotUIState &fs);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void drawMetric(QPainter &p, const QPair<QString, QString> &label, QColor c, int y);
|
||||
|
||||
QPixmap home_img, flag_img, settings_img, mic_img, link_img;
|
||||
bool onroad, recording_audio, flag_pressed, settings_pressed, mic_indicator_pressed;
|
||||
const QMap<cereal::DeviceState::NetworkType, QString> network_type = {
|
||||
{cereal::DeviceState::NetworkType::NONE, tr("--")},
|
||||
{cereal::DeviceState::NetworkType::WIFI, tr("Wi-Fi")},
|
||||
{cereal::DeviceState::NetworkType::ETHERNET, tr("ETH")},
|
||||
{cereal::DeviceState::NetworkType::CELL2_G, tr("2G")},
|
||||
{cereal::DeviceState::NetworkType::CELL3_G, tr("3G")},
|
||||
{cereal::DeviceState::NetworkType::CELL4_G, tr("LTE")},
|
||||
{cereal::DeviceState::NetworkType::CELL5_G, tr("5G")}
|
||||
};
|
||||
|
||||
const QRect home_btn = QRect(60, 860, 180, 180);
|
||||
const QRect settings_btn = QRect(50, 35, 200, 117);
|
||||
const QRect mic_indicator_btn = QRect(158, 252, 75, 40);
|
||||
const QColor good_color = QColor(255, 255, 255);
|
||||
const QColor warning_color = QColor(218, 202, 37);
|
||||
const QColor danger_color = QColor(201, 34, 49);
|
||||
|
||||
ItemStatus connect_status, panda_status, temp_status;
|
||||
QString net_type;
|
||||
int net_strength = 0;
|
||||
|
||||
ItemStatus chip_status, memory_status, storage_status;
|
||||
|
||||
private:
|
||||
std::unique_ptr<PubMaster> pm;
|
||||
Networking *networking = nullptr;
|
||||
|
||||
void showEvent(QShowEvent *event);
|
||||
void updateTheme();
|
||||
|
||||
Params params;
|
||||
|
||||
QSharedPointer<QMovie> flag_gif;
|
||||
QSharedPointer<QMovie> home_gif;
|
||||
QSharedPointer<QMovie> settings_gif;
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,248 +0,0 @@
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QHash>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLayoutItem>
|
||||
#include <QStyleOption>
|
||||
#include <QPainterPath>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QtXml/QDomDocument>
|
||||
|
||||
#include "common/swaglog.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
QString getVersion() {
|
||||
static QString version = QString::fromStdString(Params().get("Version"));
|
||||
return version;
|
||||
}
|
||||
|
||||
QString getBrand() {
|
||||
return QObject::tr("StarPilot");
|
||||
}
|
||||
|
||||
QString getStarPilotDisplayVersion() {
|
||||
return "6.7";
|
||||
}
|
||||
|
||||
QString formatStarPilotDisplayVersionDescription(const QString &description) {
|
||||
if (description.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
QStringList parts = description.split(" / ");
|
||||
if (parts.isEmpty()) {
|
||||
return getStarPilotDisplayVersion();
|
||||
}
|
||||
|
||||
parts[0] = getStarPilotDisplayVersion();
|
||||
return parts.join(" / ");
|
||||
}
|
||||
|
||||
QString getUserAgent() {
|
||||
return "openpilot-" + getVersion();
|
||||
}
|
||||
|
||||
std::optional<QString> getDongleId() {
|
||||
std::string id = Params().get("DongleId");
|
||||
|
||||
if (!id.empty() && (id != "UnregisteredDevice")) {
|
||||
return QString::fromStdString(id);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QMap<QString, QString> getSupportedLanguages() {
|
||||
QFile f(":/languages.json");
|
||||
f.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QString val = f.readAll();
|
||||
|
||||
QJsonObject obj = QJsonDocument::fromJson(val.toUtf8()).object();
|
||||
QMap<QString, QString> map;
|
||||
for (auto key : obj.keys()) {
|
||||
map[key] = obj[key].toString();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
QString timeAgo(const QDateTime &date) {
|
||||
if (!util::system_time_valid()) {
|
||||
return date.date().toString();
|
||||
}
|
||||
|
||||
int diff = date.secsTo(QDateTime::currentDateTimeUtc());
|
||||
|
||||
QString s;
|
||||
if (diff < 60) {
|
||||
s = QObject::tr("now");
|
||||
} else if (diff < 60 * 60) {
|
||||
int minutes = diff / 60;
|
||||
s = QObject::tr("%n minute(s) ago", "", minutes);
|
||||
} else if (diff < 60 * 60 * 24) {
|
||||
int hours = diff / (60 * 60);
|
||||
s = QObject::tr("%n hour(s) ago", "", hours);
|
||||
} else if (diff < 3600 * 24 * 7) {
|
||||
int days = diff / (60 * 60 * 24);
|
||||
s = QObject::tr("%n day(s) ago", "", days);
|
||||
} else {
|
||||
s = date.date().toString();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void setQtSurfaceFormat() {
|
||||
QSurfaceFormat fmt;
|
||||
#ifdef __APPLE__
|
||||
fmt.setVersion(3, 2);
|
||||
fmt.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
fmt.setRenderableType(QSurfaceFormat::OpenGL);
|
||||
#else
|
||||
fmt.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
#endif
|
||||
fmt.setSamples(16);
|
||||
fmt.setStencilBufferSize(1);
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
}
|
||||
|
||||
void sigTermHandler(int s) {
|
||||
std::signal(s, SIG_DFL);
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
void initApp(int argc, char *argv[], bool disable_hidpi) {
|
||||
Hardware::set_display_power(true);
|
||||
Hardware::set_brightness(65);
|
||||
|
||||
// setup signal handlers to exit gracefully
|
||||
std::signal(SIGINT, sigTermHandler);
|
||||
std::signal(SIGTERM, sigTermHandler);
|
||||
|
||||
QString app_dir;
|
||||
#ifdef __APPLE__
|
||||
// Get the devicePixelRatio, and scale accordingly to maintain 1:1 rendering
|
||||
QApplication tmp(argc, argv);
|
||||
app_dir = QCoreApplication::applicationDirPath();
|
||||
if (disable_hidpi) {
|
||||
qputenv("QT_SCALE_FACTOR", QString::number(1.0 / tmp.devicePixelRatio()).toLocal8Bit());
|
||||
}
|
||||
#else
|
||||
app_dir = QFileInfo(util::readlink("/proc/self/exe").c_str()).path();
|
||||
#endif
|
||||
|
||||
qputenv("QT_DBL_CLICK_DIST", QByteArray::number(150));
|
||||
// ensure the current dir matches the exectuable's directory
|
||||
QDir::setCurrent(app_dir);
|
||||
|
||||
setQtSurfaceFormat();
|
||||
}
|
||||
|
||||
void swagLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
||||
static std::map<QtMsgType, int> levels = {
|
||||
{QtMsgType::QtDebugMsg, CLOUDLOG_DEBUG},
|
||||
{QtMsgType::QtInfoMsg, CLOUDLOG_INFO},
|
||||
{QtMsgType::QtWarningMsg, CLOUDLOG_WARNING},
|
||||
{QtMsgType::QtCriticalMsg, CLOUDLOG_ERROR},
|
||||
{QtMsgType::QtSystemMsg, CLOUDLOG_ERROR},
|
||||
{QtMsgType::QtFatalMsg, CLOUDLOG_CRITICAL},
|
||||
};
|
||||
|
||||
std::string file, function;
|
||||
if (context.file != nullptr) file = context.file;
|
||||
if (context.function != nullptr) function = context.function;
|
||||
|
||||
auto bts = msg.toUtf8();
|
||||
cloudlog_e(levels[type], file.c_str(), context.line, function.c_str(), "%s", bts.constData());
|
||||
}
|
||||
|
||||
|
||||
QWidget* topWidget(QWidget* widget) {
|
||||
while (widget->parentWidget() != nullptr) widget=widget->parentWidget();
|
||||
return widget;
|
||||
}
|
||||
|
||||
QPixmap loadPixmap(const QString &fileName, const QSize &size, Qt::AspectRatioMode aspectRatioMode) {
|
||||
if (size.isEmpty()) {
|
||||
return QPixmap(fileName);
|
||||
} else {
|
||||
return QPixmap(fileName).scaled(size, aspectRatioMode, Qt::SmoothTransformation);
|
||||
}
|
||||
}
|
||||
|
||||
static QHash<QString, QByteArray> load_bootstrap_icons() {
|
||||
QHash<QString, QByteArray> icons;
|
||||
|
||||
QFile f(":/bootstrap-icons.svg");
|
||||
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QDomDocument xml;
|
||||
xml.setContent(&f);
|
||||
QDomNode n = xml.documentElement().firstChild();
|
||||
while (!n.isNull()) {
|
||||
QDomElement e = n.toElement();
|
||||
if (!e.isNull() && e.hasAttribute("id")) {
|
||||
QString svg_str;
|
||||
QTextStream stream(&svg_str);
|
||||
n.save(stream, 0);
|
||||
svg_str.replace("<symbol", "<svg");
|
||||
svg_str.replace("</symbol>", "</svg>");
|
||||
icons[e.attribute("id")] = svg_str.toUtf8();
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
}
|
||||
return icons;
|
||||
}
|
||||
|
||||
QPixmap bootstrapPixmap(const QString &id) {
|
||||
static QHash<QString, QByteArray> icons = load_bootstrap_icons();
|
||||
|
||||
QPixmap pixmap;
|
||||
if (auto it = icons.find(id); it != icons.end()) {
|
||||
pixmap.loadFromData(it.value(), "svg");
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
bool hasLongitudinalControl(const cereal::CarParams::Reader &car_params) {
|
||||
// Using the experimental longitudinal toggle, returns whether longitudinal control
|
||||
// will be active without needing a restart of openpilot
|
||||
Params params = Params();
|
||||
return (car_params.getAlphaLongitudinalAvailable()
|
||||
? params.getBool("AlphaLongitudinalEnabled")
|
||||
: car_params.getOpenpilotLongitudinalControl()) && !params.getBool("DisableOpenpilotLongitudinal");
|
||||
}
|
||||
|
||||
// ParamWatcher
|
||||
|
||||
ParamWatcher::ParamWatcher(QObject *parent) : QObject(parent) {
|
||||
watcher = new QFileSystemWatcher(this);
|
||||
QObject::connect(watcher, &QFileSystemWatcher::fileChanged, this, &ParamWatcher::fileChanged);
|
||||
}
|
||||
|
||||
void ParamWatcher::fileChanged(const QString &path) {
|
||||
auto param_name = QFileInfo(path).fileName();
|
||||
auto param_value = QString::fromStdString(params.get(param_name.toStdString()));
|
||||
|
||||
auto it = params_hash.find(param_name);
|
||||
bool content_changed = (it == params_hash.end()) || (it.value() != param_value);
|
||||
params_hash[param_name] = param_value;
|
||||
// emit signal when the content changes.
|
||||
if (content_changed) {
|
||||
emit paramChanged(param_name, param_value);
|
||||
}
|
||||
}
|
||||
|
||||
void ParamWatcher::addParam(const QString ¶m_name) {
|
||||
watcher->addPath(QString::fromStdString(params.getParamPath(param_name.toStdString())));
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QWidget>
|
||||
|
||||
#include "cereal/gen/cpp/car.capnp.h"
|
||||
#include "common/params.h"
|
||||
|
||||
QString getVersion();
|
||||
QString getBrand();
|
||||
QString getStarPilotDisplayVersion();
|
||||
QString formatStarPilotDisplayVersionDescription(const QString &description);
|
||||
QString getUserAgent();
|
||||
std::optional<QString> getDongleId();
|
||||
QMap<QString, QString> getSupportedLanguages();
|
||||
void setQtSurfaceFormat();
|
||||
void sigTermHandler(int s);
|
||||
QString timeAgo(const QDateTime &date);
|
||||
void swagLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||
void initApp(int argc, char *argv[], bool disable_hidpi = true);
|
||||
QWidget* topWidget(QWidget* widget);
|
||||
QPixmap loadPixmap(const QString &fileName, const QSize &size = {}, Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio);
|
||||
QPixmap bootstrapPixmap(const QString &id);
|
||||
bool hasLongitudinalControl(const cereal::CarParams::Reader &car_params);
|
||||
|
||||
struct InterFont : public QFont {
|
||||
InterFont(int pixel_size, QFont::Weight weight = QFont::Normal) : QFont("Inter") {
|
||||
setPixelSize(pixel_size);
|
||||
setWeight(weight);
|
||||
}
|
||||
};
|
||||
|
||||
class ParamWatcher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ParamWatcher(QObject *parent);
|
||||
void addParam(const QString ¶m_name);
|
||||
|
||||
signals:
|
||||
void paramChanged(const QString ¶m_name, const QString ¶m_value);
|
||||
|
||||
private:
|
||||
void fileChanged(const QString &path);
|
||||
|
||||
QFileSystemWatcher *watcher;
|
||||
QHash<QString, QString> params_hash;
|
||||
Params params;
|
||||
};
|
||||
@@ -1,365 +0,0 @@
|
||||
#include "selfdrive/ui/qt/widgets/cameraview.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl3.h>
|
||||
#else
|
||||
#include <GLES3/gl3.h>
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <QApplication>
|
||||
|
||||
namespace {
|
||||
|
||||
const char frame_vertex_shader[] =
|
||||
#ifdef __APPLE__
|
||||
"#version 330 core\n"
|
||||
#else
|
||||
"#version 300 es\n"
|
||||
#endif
|
||||
"layout(location = 0) in vec4 aPosition;\n"
|
||||
"layout(location = 1) in vec2 aTexCoord;\n"
|
||||
"uniform mat4 uTransform;\n"
|
||||
"out vec2 vTexCoord;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = uTransform * aPosition;\n"
|
||||
" vTexCoord = aTexCoord;\n"
|
||||
"}\n";
|
||||
|
||||
const char frame_fragment_shader[] =
|
||||
#ifdef QCOM2
|
||||
"#version 300 es\n"
|
||||
"#extension GL_OES_EGL_image_external_essl3 : enable\n"
|
||||
"precision mediump float;\n"
|
||||
"uniform samplerExternalOES uTexture;\n"
|
||||
"in vec2 vTexCoord;\n"
|
||||
"out vec4 colorOut;\n"
|
||||
"void main() {\n"
|
||||
" colorOut = texture(uTexture, vTexCoord);\n"
|
||||
// gamma to improve worst case visibility when dark
|
||||
" colorOut.rgb = pow(colorOut.rgb, vec3(1.0/1.28));\n"
|
||||
"}\n";
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
"#version 330 core\n"
|
||||
#else
|
||||
"#version 300 es\n"
|
||||
"precision mediump float;\n"
|
||||
#endif
|
||||
"uniform sampler2D uTextureY;\n"
|
||||
"uniform sampler2D uTextureUV;\n"
|
||||
"in vec2 vTexCoord;\n"
|
||||
"out vec4 colorOut;\n"
|
||||
"void main() {\n"
|
||||
" float y = texture(uTextureY, vTexCoord).r;\n"
|
||||
" vec2 uv = texture(uTextureUV, vTexCoord).rg - 0.5;\n"
|
||||
" float r = y + 1.402 * uv.y;\n"
|
||||
" float g = y - 0.344 * uv.x - 0.714 * uv.y;\n"
|
||||
" float b = y + 1.772 * uv.x;\n"
|
||||
" colorOut = vec4(r, g, b, 1.0);\n"
|
||||
"}\n";
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
CameraWidget::CameraWidget(std::string stream_name, VisionStreamType type, QWidget* parent) :
|
||||
stream_name(stream_name), active_stream_type(type), requested_stream_type(type), QOpenGLWidget(parent) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
qRegisterMetaType<std::set<VisionStreamType>>("availableStreams");
|
||||
QObject::connect(this, &CameraWidget::vipcThreadConnected, this, &CameraWidget::vipcConnected, Qt::BlockingQueuedConnection);
|
||||
QObject::connect(this, &CameraWidget::vipcThreadFrameReceived, this, &CameraWidget::vipcFrameReceived, Qt::QueuedConnection);
|
||||
QObject::connect(this, &CameraWidget::vipcAvailableStreamsUpdated, this, &CameraWidget::availableStreamsUpdated, Qt::QueuedConnection);
|
||||
QObject::connect(QApplication::instance(), &QCoreApplication::aboutToQuit, this, &CameraWidget::stopVipcThread);
|
||||
}
|
||||
|
||||
CameraWidget::~CameraWidget() {
|
||||
makeCurrent();
|
||||
stopVipcThread();
|
||||
if (isValid()) {
|
||||
glDeleteVertexArrays(1, &frame_vao);
|
||||
glDeleteBuffers(1, &frame_vbo);
|
||||
glDeleteBuffers(1, &frame_ibo);
|
||||
#ifndef QCOM2
|
||||
glDeleteTextures(2, textures);
|
||||
#endif
|
||||
}
|
||||
doneCurrent();
|
||||
}
|
||||
|
||||
// Qt uses device-independent pixels, depending on platform this may be
|
||||
// different to what OpenGL uses
|
||||
int CameraWidget::glWidth() {
|
||||
return width() * devicePixelRatio();
|
||||
}
|
||||
|
||||
int CameraWidget::glHeight() {
|
||||
return height() * devicePixelRatio();
|
||||
}
|
||||
|
||||
void CameraWidget::initializeGL() {
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
program = std::make_unique<QOpenGLShaderProgram>(context());
|
||||
bool ret = program->addShaderFromSourceCode(QOpenGLShader::Vertex, frame_vertex_shader);
|
||||
assert(ret);
|
||||
ret = program->addShaderFromSourceCode(QOpenGLShader::Fragment, frame_fragment_shader);
|
||||
assert(ret);
|
||||
|
||||
program->link();
|
||||
GLint frame_pos_loc = program->attributeLocation("aPosition");
|
||||
GLint frame_texcoord_loc = program->attributeLocation("aTexCoord");
|
||||
|
||||
auto [x1, x2, y1, y2] = requested_stream_type == VISION_STREAM_DRIVER ? std::tuple(0.f, 1.f, 1.f, 0.f) : std::tuple(1.f, 0.f, 1.f, 0.f);
|
||||
const uint8_t frame_indicies[] = {0, 1, 2, 0, 2, 3};
|
||||
const float frame_coords[4][4] = {
|
||||
{-1.0, -1.0, x2, y1}, // bl
|
||||
{-1.0, 1.0, x2, y2}, // tl
|
||||
{ 1.0, 1.0, x1, y2}, // tr
|
||||
{ 1.0, -1.0, x1, y1}, // br
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &frame_vao);
|
||||
glBindVertexArray(frame_vao);
|
||||
glGenBuffers(1, &frame_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, frame_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(frame_coords), frame_coords, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(frame_pos_loc);
|
||||
glVertexAttribPointer(frame_pos_loc, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(frame_coords[0]), (const void *)0);
|
||||
glEnableVertexAttribArray(frame_texcoord_loc);
|
||||
glVertexAttribPointer(frame_texcoord_loc, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(frame_coords[0]), (const void *)(sizeof(float) * 2));
|
||||
glGenBuffers(1, &frame_ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, frame_ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(frame_indicies), frame_indicies, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glUseProgram(program->programId());
|
||||
|
||||
#ifdef QCOM2
|
||||
glUniform1i(program->uniformLocation("uTexture"), 0);
|
||||
#else
|
||||
glGenTextures(2, textures);
|
||||
glUniform1i(program->uniformLocation("uTextureY"), 0);
|
||||
glUniform1i(program->uniformLocation("uTextureUV"), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CameraWidget::showEvent(QShowEvent *event) {
|
||||
if (!vipc_thread) {
|
||||
clearFrames();
|
||||
vipc_thread = new QThread();
|
||||
connect(vipc_thread, &QThread::started, [=]() { vipcThread(); });
|
||||
connect(vipc_thread, &QThread::finished, vipc_thread, &QObject::deleteLater);
|
||||
vipc_thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraWidget::stopVipcThread() {
|
||||
makeCurrent();
|
||||
if (vipc_thread) {
|
||||
vipc_thread->requestInterruption();
|
||||
vipc_thread->quit();
|
||||
vipc_thread->wait();
|
||||
vipc_thread = nullptr;
|
||||
}
|
||||
|
||||
#ifdef QCOM2
|
||||
EGLDisplay egl_display = eglGetCurrentDisplay();
|
||||
assert(egl_display != EGL_NO_DISPLAY);
|
||||
for (auto &pair : egl_images) {
|
||||
eglDestroyImageKHR(egl_display, pair.second);
|
||||
assert(eglGetError() == EGL_SUCCESS);
|
||||
}
|
||||
egl_images.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CameraWidget::availableStreamsUpdated(std::set<VisionStreamType> streams) {
|
||||
available_streams = streams;
|
||||
}
|
||||
|
||||
mat4 CameraWidget::calcFrameMatrix() {
|
||||
// Scale the frame to fit the widget while maintaining the aspect ratio.
|
||||
float widget_aspect_ratio = (float)width() / height();
|
||||
float frame_aspect_ratio = (float)stream_width / stream_height;
|
||||
float zx = std::min(frame_aspect_ratio / widget_aspect_ratio, 1.0f);
|
||||
float zy = std::min(widget_aspect_ratio / frame_aspect_ratio, 1.0f);
|
||||
|
||||
return mat4{{
|
||||
zx, 0.0, 0.0, 0.0,
|
||||
0.0, zy, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
}};
|
||||
}
|
||||
|
||||
void CameraWidget::paintGL() {
|
||||
glClearColor(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF());
|
||||
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
std::lock_guard lk(frame_lock);
|
||||
if (frames.empty()) return;
|
||||
|
||||
int frame_idx = frames.size() - 1;
|
||||
|
||||
// Always draw latest frame until sync logic is more stable
|
||||
// for (frame_idx = 0; frame_idx < frames.size() - 1; frame_idx++) {
|
||||
// if (frames[frame_idx].first == draw_frame_id) break;
|
||||
// }
|
||||
|
||||
// Log duplicate/dropped frames
|
||||
if (frames[frame_idx].first == prev_frame_id) {
|
||||
qDebug() << "Drawing same frame twice" << frames[frame_idx].first;
|
||||
} else if (frames[frame_idx].first != prev_frame_id + 1) {
|
||||
qDebug() << "Skipped frame" << frames[frame_idx].first;
|
||||
}
|
||||
prev_frame_id = frames[frame_idx].first;
|
||||
VisionBuf *frame = frames[frame_idx].second;
|
||||
assert(frame != nullptr);
|
||||
|
||||
auto frame_mat = calcFrameMatrix();
|
||||
|
||||
glViewport(0, 0, glWidth(), glHeight());
|
||||
glBindVertexArray(frame_vao);
|
||||
glUseProgram(program->programId());
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
#ifdef QCOM2
|
||||
// no frame copy
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_images[frame->idx]);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
#else
|
||||
// fallback to copy
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width, stream_height, GL_RED, GL_UNSIGNED_BYTE, frame->y);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride/2);
|
||||
glActiveTexture(GL_TEXTURE0 + 1);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width/2, stream_height/2, GL_RG, GL_UNSIGNED_BYTE, frame->uv);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
#endif
|
||||
|
||||
glUniformMatrix4fv(program->uniformLocation("uTransform"), 1, GL_TRUE, frame_mat.v);
|
||||
glEnableVertexAttribArray(0);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (const void *)0);
|
||||
glDisableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
|
||||
void CameraWidget::vipcConnected(VisionIpcClient *vipc_client) {
|
||||
makeCurrent();
|
||||
stream_width = vipc_client->buffers[0].width;
|
||||
stream_height = vipc_client->buffers[0].height;
|
||||
stream_stride = vipc_client->buffers[0].stride;
|
||||
|
||||
#ifdef QCOM2
|
||||
EGLDisplay egl_display = eglGetCurrentDisplay();
|
||||
assert(egl_display != EGL_NO_DISPLAY);
|
||||
for (auto &pair : egl_images) {
|
||||
eglDestroyImageKHR(egl_display, pair.second);
|
||||
}
|
||||
egl_images.clear();
|
||||
|
||||
for (int i = 0; i < vipc_client->num_buffers; i++) { // import buffers into OpenGL
|
||||
int fd = dup(vipc_client->buffers[i].fd); // eglDestroyImageKHR will close, so duplicate
|
||||
EGLint img_attrs[] = {
|
||||
EGL_WIDTH, (int)vipc_client->buffers[i].width,
|
||||
EGL_HEIGHT, (int)vipc_client->buffers[i].height,
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_NV12,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, fd,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, (int)vipc_client->buffers[i].stride,
|
||||
EGL_DMA_BUF_PLANE1_FD_EXT, fd,
|
||||
EGL_DMA_BUF_PLANE1_OFFSET_EXT, (int)vipc_client->buffers[i].uv_offset,
|
||||
EGL_DMA_BUF_PLANE1_PITCH_EXT, (int)vipc_client->buffers[i].stride,
|
||||
EGL_NONE
|
||||
};
|
||||
egl_images[i] = eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, 0, img_attrs);
|
||||
assert(eglGetError() == EGL_SUCCESS);
|
||||
}
|
||||
#else
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, stream_width, stream_height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, stream_width/2, stream_height/2, 0, GL_RG, GL_UNSIGNED_BYTE, nullptr);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CameraWidget::vipcFrameReceived() {
|
||||
update();
|
||||
}
|
||||
|
||||
void CameraWidget::vipcThread() {
|
||||
VisionStreamType cur_stream = requested_stream_type;
|
||||
std::unique_ptr<VisionIpcClient> vipc_client;
|
||||
VisionIpcBufExtra meta_main = {0};
|
||||
|
||||
while (!QThread::currentThread()->isInterruptionRequested()) {
|
||||
if (!vipc_client || cur_stream != requested_stream_type) {
|
||||
clearFrames();
|
||||
qDebug().nospace() << "connecting to stream " << requested_stream_type << ", was connected to " << cur_stream;
|
||||
cur_stream = requested_stream_type;
|
||||
vipc_client.reset(new VisionIpcClient(stream_name, cur_stream, false));
|
||||
}
|
||||
active_stream_type = cur_stream;
|
||||
|
||||
if (!vipc_client->connected) {
|
||||
clearFrames();
|
||||
auto streams = VisionIpcClient::getAvailableStreams(stream_name, false);
|
||||
if (streams.empty()) {
|
||||
QThread::msleep(100);
|
||||
continue;
|
||||
}
|
||||
emit vipcAvailableStreamsUpdated(streams);
|
||||
|
||||
if (!vipc_client->connect(false)) {
|
||||
QThread::msleep(100);
|
||||
continue;
|
||||
}
|
||||
emit vipcThreadConnected(vipc_client.get());
|
||||
}
|
||||
|
||||
if (VisionBuf *buf = vipc_client->recv(&meta_main, 1000)) {
|
||||
{
|
||||
std::lock_guard lk(frame_lock);
|
||||
frames.push_back(std::make_pair(meta_main.frame_id, buf));
|
||||
while (frames.size() > FRAME_BUFFER_SIZE) {
|
||||
frames.pop_front();
|
||||
}
|
||||
}
|
||||
emit vipcThreadFrameReceived();
|
||||
} else {
|
||||
if (!isVisible()) {
|
||||
vipc_client->connected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CameraWidget::clearFrames() {
|
||||
std::lock_guard lk(frame_lock);
|
||||
frames.clear();
|
||||
available_streams.clear();
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QThread>
|
||||
|
||||
#ifdef QCOM2
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#define EGL_NO_X11
|
||||
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#include "msgq/visionipc/visionipc_client.h"
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
const int FRAME_BUFFER_SIZE = 5;
|
||||
|
||||
class CameraWidget : public QOpenGLWidget, protected QOpenGLFunctions {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using QOpenGLWidget::QOpenGLWidget;
|
||||
explicit CameraWidget(std::string stream_name, VisionStreamType stream_type, QWidget* parent = nullptr);
|
||||
~CameraWidget();
|
||||
void setBackgroundColor(const QColor &color) { bg = color; }
|
||||
void setFrameId(int frame_id) { draw_frame_id = frame_id; }
|
||||
void setStreamType(VisionStreamType type) { requested_stream_type = type; }
|
||||
VisionStreamType getStreamType() { return active_stream_type; }
|
||||
void stopVipcThread();
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
void vipcThreadConnected(VisionIpcClient *);
|
||||
void vipcThreadFrameReceived();
|
||||
void vipcAvailableStreamsUpdated(std::set<VisionStreamType>);
|
||||
|
||||
protected:
|
||||
void paintGL() override;
|
||||
void initializeGL() override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override { emit clicked(); }
|
||||
virtual mat4 calcFrameMatrix();
|
||||
void vipcThread();
|
||||
void clearFrames();
|
||||
|
||||
int glWidth();
|
||||
int glHeight();
|
||||
|
||||
GLuint frame_vao, frame_vbo, frame_ibo;
|
||||
GLuint textures[2];
|
||||
std::unique_ptr<QOpenGLShaderProgram> program;
|
||||
QColor bg = QColor("#000000");
|
||||
|
||||
#ifdef QCOM2
|
||||
std::map<int, EGLImageKHR> egl_images;
|
||||
#endif
|
||||
|
||||
std::string stream_name;
|
||||
int stream_width = 0;
|
||||
int stream_height = 0;
|
||||
int stream_stride = 0;
|
||||
std::atomic<VisionStreamType> active_stream_type;
|
||||
std::atomic<VisionStreamType> requested_stream_type;
|
||||
std::set<VisionStreamType> available_streams;
|
||||
QThread *vipc_thread = nullptr;
|
||||
std::recursive_mutex frame_lock;
|
||||
std::deque<std::pair<uint32_t, VisionBuf*>> frames;
|
||||
uint32_t draw_frame_id = 0;
|
||||
uint32_t prev_frame_id = 0;
|
||||
|
||||
protected slots:
|
||||
void vipcConnected(VisionIpcClient *vipc_client);
|
||||
void vipcFrameReceived();
|
||||
void availableStreamsUpdated(std::set<VisionStreamType> streams);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(std::set<VisionStreamType>);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user