Skip to content

Commit b447af6

Browse files
committed
Sweep SonarCloud minor lints on PR #182
S1192 duplicate literals — extract module constants: - english.py / japanese.py: TOKEN_LABEL, HOST_LABEL, PORT_LABEL, STOP_HOST, CLEAR_ALL constants reused across i18n dict entries. - webrtc_panel.py: _QUALITY_DOT_STYLE, _JSON_FILE_FILTER. - rest_server.py: _PATH_METRICS, _PATH_DASHBOARD, _NOT_FOUND_BODY, _TEXT_PLAIN_UTF8 + switch the asset regex from [A-Za-z0-9_] to \w (S6353). - rest_openapi.py: _JSON_MEDIA_TYPE. - viewer_client.py: _CLIENT_SHUT_DOWN_MSG. S5713 redundant Exception subclasses: - admin_client / usb_browser_tab: drop urllib.error.URLError from the except tuples (it's already an OSError); keep TimeoutError with a NOSONAR justifying the Python 3.10 distinction. - webrtc_panel.py: drop PermissionError from one tuple and FileNotFoundError from another (both are OSError subclasses). - webrtc_stats.py: keep (RuntimeError, TimeoutError, OSError) tuple with NOSONAR — same 3.10 vs 3.11 TimeoutError divergence. Other smells: - webrtc_panel / webrtc_dialogs: NOSONAR on three list(dict.values()) / list(dict.keys()) snapshots — they're guarding against mutation during iteration (S7504 false positive). - winusb_backend: NOSONAR on _SP_DEVICE_INTERFACE_DATA and _WINUSB_SETUP_PACKET (S101) — names mirror MSDN structs verbatim; also tighten the VID/PID regex to use a single case range under re.IGNORECASE (S5869). - test_usb_passthrough: rename ``credits`` local to ``credit_state`` to stop shadowing the builtin (S5806). - webrtc_files: drop the unused ``data`` param from _finish and the unused ``on_error`` from _abort_locked; fix the latent silent-abort path to fire on_error from the caller (S1172). - lan_discovery / host_service: ``del zc, type_`` and ``del config_path`` to make the unused-but-required signature parameters explicit (S1172). - admin_console_tab: split the nested ?: ternary into an if/elif chain for readability (S3358). - webrtc_dialogs: factor dragEnter / dragMove into a shared helper (S4144). - web_viewer/index.html: add ``for=`` attributes on TURN/STUN form labels (S6853 ×4); split nested ternary in setLanguage into if/elif (S3358); drop trailing zero fractions on quality thresholds (S7748); rephrase the ``// {…shape}`` annotation so Sonar stops mistaking it for commented-out code (S125). WebRTC asyncio docstring fix: - webrtc_stats._async_start NOSONAR S7503 — must be a coroutine to cross the bridge.submit / run_coroutine_threadsafe boundary even though the body has no awaits.
1 parent cdd1f65 commit b447af6

16 files changed

Lines changed: 145 additions & 98 deletions

File tree

je_auto_control/gui/admin_console_tab.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,12 @@ def _refresh_table(self, statuses: Optional[list] = None) -> None:
194194
self._table.setItem(row, 0, QTableWidgetItem(host.label))
195195
self._table.setItem(row, 1, QTableWidgetItem(host.base_url))
196196
status = status_by_label.get(host.label)
197-
health_text = "?" if status is None else (
198-
_t("admin_health_ok") if status.healthy
199-
else _t("admin_health_down")
200-
)
197+
if status is None:
198+
health_text = "?"
199+
elif status.healthy:
200+
health_text = _t("admin_health_ok")
201+
else:
202+
health_text = _t("admin_health_down")
201203
latency_text = "-" if status is None else f"{status.latency_ms:.0f} ms"
202204
jobs_text = "-" if status is None or status.job_count is None \
203205
else str(status.job_count)

je_auto_control/gui/language_wrapper/english.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
_SCRIPT_LABEL = "Script:"
22
_REMOVE_SELECTED = "Remove selected"
33
_SELECT_SCRIPT = "Select script"
4+
_TOKEN_LABEL = "Token:"
5+
_HOST_LABEL = "Host:"
6+
_PORT_LABEL = "Port:"
7+
_STOP_HOST = "Stop host"
8+
_CLEAR_ALL = "Clear all"
49

510
english_word_dict = {
611
# Main
@@ -124,11 +129,11 @@
124129
# Admin console tab
125130
"admin_add_group": "Register host",
126131
"admin_add": "Add",
127-
"admin_remove": "Remove selected",
132+
"admin_remove": _REMOVE_SELECTED,
128133
"admin_refresh": "Poll all",
129134
"admin_label": "Label:",
130135
"admin_url": "Base URL:",
131-
"admin_token": "Token:",
136+
"admin_token": _TOKEN_LABEL,
132137
"admin_broadcast_group": "Broadcast",
133138
"admin_actions_label": "Actions JSON (sent to every host):",
134139
"admin_broadcast_run": "Run on all hosts",
@@ -144,9 +149,9 @@
144149
# REST API tab
145150
"rest_config_group": "REST API config",
146151
"rest_status_group": "REST API status",
147-
"rest_host": "Host:",
148-
"rest_port": "Port:",
149-
"rest_token": "Token:",
152+
"rest_host": _HOST_LABEL,
153+
"rest_port": _PORT_LABEL,
154+
"rest_token": _TOKEN_LABEL,
150155
"rest_token_ph": "leave blank to auto-generate",
151156
"rest_enable_audit": "Write audit log",
152157
"rest_start": "Start",
@@ -173,7 +178,7 @@
173178
"rd_webrtc_answer_input_label": "Paste viewer's answer SDP:",
174179
"rd_webrtc_paste_answer": "paste the answer SDP here",
175180
"rd_webrtc_apply_answer": "Apply answer",
176-
"rd_webrtc_stop_host": "Stop host",
181+
"rd_webrtc_stop_host": _STOP_HOST,
177182
"rd_webrtc_offer_input_label": "Paste host's offer SDP:",
178183
"rd_webrtc_paste_offer": "paste the offer SDP here",
179184
"rd_webrtc_create_answer": "Create answer",
@@ -222,8 +227,8 @@
222227
"rd_webrtc_host_id_required": "Host ID is required",
223228
# Trust list / accept dialog
224229
"rd_webrtc_trusted_group": "Trusted viewers (auto-accept)",
225-
"rd_webrtc_remove_trusted": "Remove selected",
226-
"rd_webrtc_clear_trusted": "Clear all",
230+
"rd_webrtc_remove_trusted": _REMOVE_SELECTED,
231+
"rd_webrtc_clear_trusted": _CLEAR_ALL,
227232
"rd_webrtc_clear_trust_confirm": "Remove every trusted viewer?",
228233
"rd_webrtc_pending_viewer_title": "Incoming viewer",
229234
"rd_webrtc_reject": "Reject",
@@ -300,7 +305,7 @@
300305
"rd_webrtc_kh_col_app_fp": "App fingerprint",
301306
"rd_webrtc_kh_col_dtls_fp": "DTLS fingerprint",
302307
"rd_webrtc_kh_forget": "Forget selected",
303-
"rd_webrtc_kh_clear_all": "Clear all",
308+
"rd_webrtc_kh_clear_all": _CLEAR_ALL,
304309
"rd_webrtc_kh_close": "Close",
305310
"rd_webrtc_kh_clear_confirm": "Forget every known host?",
306311
"rd_webrtc_kh_copy_app": "Copy app fp",
@@ -344,13 +349,13 @@
344349
"rd_webrtc_copy_fingerprint": "Copy",
345350
"rd_webrtc_ab_export": "Export book...",
346351
"rd_webrtc_ab_import": "Import book...",
347-
"rd_webrtc_ab_clear": "Clear all",
352+
"rd_webrtc_ab_clear": _CLEAR_ALL,
348353
"rd_webrtc_ab_clear_confirm": "Clear the entire address book?",
349354
"rd_webrtc_ab_import_done": "Imported {n} address-book entries",
350355
"rd_webrtc_tray_idle": "AutoControl host: idle",
351356
"rd_webrtc_tray_running": "AutoControl host: {n} viewer(s)",
352357
"rd_webrtc_tray_open": "Open window",
353-
"rd_webrtc_tray_stop": "Stop host",
358+
"rd_webrtc_tray_stop": _STOP_HOST,
354359
"rd_webrtc_tray_quit": "Quit",
355360
"rd_webrtc_region_label": "Region (x,y,w,h):",
356361
"rd_webrtc_region_placeholder": "leave blank for full screen",
@@ -367,7 +372,7 @@
367372
"rd_webrtc_audit_title": "Audit log",
368373
"rd_webrtc_audit_filter_type": "Type:",
369374
"rd_webrtc_audit_filter_type_ph": "auth_ok / auth_fail / file_received / ...",
370-
"rd_webrtc_audit_filter_host": "Host:",
375+
"rd_webrtc_audit_filter_host": _HOST_LABEL,
371376
"rd_webrtc_audit_refresh": "Refresh",
372377
"rd_webrtc_audit_col_ts": "Timestamp",
373378
"rd_webrtc_audit_col_type": "Event",
@@ -565,8 +570,8 @@
565570
# Socket / REST Tab
566571
"ss_tcp_group": "TCP socket server",
567572
"ss_rest_group": "REST API server",
568-
"ss_host_label": "Host:",
569-
"ss_port_label": "Port:",
573+
"ss_host_label": _HOST_LABEL,
574+
"ss_port_label": _PORT_LABEL,
570575
"ss_tcp_any_check": "Bind TCP to 0.0.0.0 (exposes to network)",
571576
"ss_rest_any_check": "Bind REST to 0.0.0.0 (exposes to network)",
572577
"ss_tcp_stopped": "TCP stopped",
@@ -707,7 +712,7 @@
707712
"vars_col_value": "Value",
708713
"vars_count": "{n} variables",
709714
"vars_refresh": "Refresh",
710-
"vars_clear": "Clear all",
715+
"vars_clear": _CLEAR_ALL,
711716
"vars_clear_confirm": "Clear every runtime variable?",
712717
"vars_set_group": "Set one",
713718
"vars_name_label": "Name:",
@@ -751,15 +756,15 @@
751756
),
752757
"rd_host_config_group": "Host configuration",
753758
"rd_viewer_config_group": "Connect to a remote host",
754-
"rd_token_label": "Token:",
759+
"rd_token_label": _TOKEN_LABEL,
755760
"rd_token_placeholder": "shared secret (HMAC key)",
756761
"rd_token_generate": "Generate",
757762
"rd_bind_label": "Address:",
758-
"rd_port_label": "Port:",
763+
"rd_port_label": _PORT_LABEL,
759764
"rd_fps_label": "FPS:",
760765
"rd_quality_label": "JPEG quality:",
761766
"rd_host_start": "Start host",
762-
"rd_host_stop": "Stop host",
767+
"rd_host_stop": _STOP_HOST,
763768
"rd_host_status_running": "Running on port {port} — {n} viewer(s)",
764769
"rd_host_status_stopped": "Host is stopped",
765770
"rd_host_preview_label": "Preview (what viewers see):",

je_auto_control/gui/language_wrapper/japanese.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
_SCRIPT_LABEL = "スクリプト:"
33
_REMOVE_SELECTED = "選択項目を削除"
44
_SELECT_SCRIPT = "スクリプトを選択"
5+
_TOKEN_LABEL = "トークン:"
6+
_STOP_HOST_JA = "ホスト停止"
7+
_CLEAR_ALL_JA = "すべて削除"
58

69
japanese_word_dict = {
710
"application_name": "AutoControlGUI",
@@ -128,7 +131,7 @@
128131
"admin_refresh": "全件ポーリング",
129132
"admin_label": "ラベル:",
130133
"admin_url": "ベース URL:",
131-
"admin_token": "トークン:",
134+
"admin_token": _TOKEN_LABEL,
132135
"admin_broadcast_group": "ブロードキャスト",
133136
"admin_actions_label": "アクション JSON (全ホストへ送信):",
134137
"admin_broadcast_run": "全ホストで実行",
@@ -146,7 +149,7 @@
146149
"rest_status_group": "REST API 状態",
147150
"rest_host": "ホスト:",
148151
"rest_port": "ポート:",
149-
"rest_token": "トークン:",
152+
"rest_token": _TOKEN_LABEL,
150153
"rest_token_ph": "空欄で自動生成",
151154
"rest_enable_audit": "監査ログを記録",
152155
"rest_start": "開始",
@@ -173,7 +176,7 @@
173176
"rd_webrtc_answer_input_label": "ビューアの Answer SDP を貼り付け:",
174177
"rd_webrtc_paste_answer": "Answer SDP をここに貼り付け",
175178
"rd_webrtc_apply_answer": "Answer 適用",
176-
"rd_webrtc_stop_host": "ホスト停止",
179+
"rd_webrtc_stop_host": _STOP_HOST_JA,
177180
"rd_webrtc_offer_input_label": "ホストの Offer SDP を貼り付け:",
178181
"rd_webrtc_paste_offer": "Offer SDP をここに貼り付け",
179182
"rd_webrtc_create_answer": "Answer 生成",
@@ -223,7 +226,7 @@
223226
# 信頼リスト / 受け入れダイアログ
224227
"rd_webrtc_trusted_group": "信頼済みビューア(自動承認)",
225228
"rd_webrtc_remove_trusted": "選択を削除",
226-
"rd_webrtc_clear_trusted": "すべて削除",
229+
"rd_webrtc_clear_trusted": _CLEAR_ALL_JA,
227230
"rd_webrtc_clear_trust_confirm": "信頼済みビューアをすべて削除しますか?",
228231
"rd_webrtc_pending_viewer_title": "新規接続要求",
229232
"rd_webrtc_reject": "拒否",
@@ -300,7 +303,7 @@
300303
"rd_webrtc_kh_col_app_fp": "App fingerprint",
301304
"rd_webrtc_kh_col_dtls_fp": "DTLS fingerprint",
302305
"rd_webrtc_kh_forget": "選択を忘れる",
303-
"rd_webrtc_kh_clear_all": "すべて削除",
306+
"rd_webrtc_kh_clear_all": _CLEAR_ALL_JA,
304307
"rd_webrtc_kh_close": "閉じる",
305308
"rd_webrtc_kh_clear_confirm": "全ての既知ホストを忘れますか?",
306309
"rd_webrtc_kh_copy_app": "App fp コピー",
@@ -344,13 +347,13 @@
344347
"rd_webrtc_copy_fingerprint": "コピー",
345348
"rd_webrtc_ab_export": "アドレス帳エクスポート...",
346349
"rd_webrtc_ab_import": "アドレス帳インポート...",
347-
"rd_webrtc_ab_clear": "すべて削除",
350+
"rd_webrtc_ab_clear": _CLEAR_ALL_JA,
348351
"rd_webrtc_ab_clear_confirm": "アドレス帳全件削除しますか?",
349352
"rd_webrtc_ab_import_done": "{n} 件インポート完了",
350353
"rd_webrtc_tray_idle": "AutoControl host: アイドル",
351354
"rd_webrtc_tray_running": "AutoControl host: {n} ビューア",
352355
"rd_webrtc_tray_open": "ウィンドウを開く",
353-
"rd_webrtc_tray_stop": "ホスト停止",
356+
"rd_webrtc_tray_stop": _STOP_HOST_JA,
354357
"rd_webrtc_tray_quit": "終了",
355358
"rd_webrtc_region_label": "領域 (x,y,w,h):",
356359
"rd_webrtc_region_placeholder": "全画面なら空欄",
@@ -751,15 +754,15 @@
751754
),
752755
"rd_host_config_group": "ホスト設定",
753756
"rd_viewer_config_group": "リモートホストへ接続",
754-
"rd_token_label": "トークン:",
757+
"rd_token_label": _TOKEN_LABEL,
755758
"rd_token_placeholder": "共有シークレット(HMAC キー)",
756759
"rd_token_generate": "生成",
757760
"rd_bind_label": "アドレス:",
758761
"rd_port_label": "ポート:",
759762
"rd_fps_label": "FPS:",
760763
"rd_quality_label": "JPEG 品質:",
761764
"rd_host_start": "ホスト開始",
762-
"rd_host_stop": "ホスト停止",
765+
"rd_host_stop": _STOP_HOST_JA,
763766
"rd_host_status_running": "稼働中 ポート {port} — ビューア {n} 名",
764767
"rd_host_status_stopped": "ホストは停止中",
765768
"rd_host_preview_label": "プレビュー(ビューアの表示):",

je_auto_control/gui/remote_desktop/webrtc_dialogs.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,16 @@ def populate(self, files: list, format_mtime) -> None:
250250

251251
# --- drag-and-drop ------------------------------------------------------
252252

253-
def dragEnterEvent(self, event) -> None: # noqa: N802 Qt override
253+
def _accept_url_drag(self, event) -> None:
254+
"""Shared drag handler: accept iff the payload carries file URLs."""
254255
if event.mimeData().hasUrls():
255256
event.acceptProposedAction()
256257

258+
def dragEnterEvent(self, event) -> None: # noqa: N802 Qt override
259+
self._accept_url_drag(event)
260+
257261
def dragMoveEvent(self, event) -> None: # noqa: N802 Qt override
258-
if event.mimeData().hasUrls():
259-
event.acceptProposedAction()
262+
self._accept_url_drag(event)
260263

261264
def dropEvent(self, event) -> None: # noqa: N802 Qt override
262265
urls = event.mimeData().urls()
@@ -540,7 +543,7 @@ def _on_clear_all(self) -> None:
540543
)
541544
if result != _QMB.StandardButton.Yes:
542545
return
543-
for host_id in list(self._known.list_entries().keys()):
546+
for host_id in list(self._known.list_entries().keys()): # NOSONAR python:S7504 # forget() mutates the underlying mapping — list() is required to avoid RuntimeError
544547
self._known.forget(host_id)
545548
self._refresh()
546549

je_auto_control/gui/remote_desktop/webrtc_panel.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,15 @@
6969

7070
_DEFAULT_FPS = 24
7171
_DEFAULT_MONITOR = 1
72-
_DEFAULT_SIGNALING_URL = "http://127.0.0.1:8765"
72+
# Plain http:// is intentional: the bundled signaling server defaults
73+
# to localhost without TLS, and operators put TLS in front via nginx /
74+
# Caddy. Hotspot S5332 acknowledged on a per-line basis; see callers.
75+
_DEFAULT_SIGNALING_URL = "http://127.0.0.1:8765" # NOSONAR python:S5332
7376
_DEFAULT_STUN = "stun:stun.l.google.com:19302"
7477

78+
_QUALITY_DOT_STYLE = "background-color: #555; border-radius: 7px;"
79+
_JSON_FILE_FILTER = "JSON (*.json);;All (*)"
80+
7581

7682
def _av_frame_to_qimage(frame) -> Optional[QImage]:
7783
"""Convert an aiortc/av video frame to a Qt-owned QImage."""
@@ -264,7 +270,7 @@ def _build_ui(self) -> None:
264270
self._host_quality_dot = QLabel()
265271
self._host_quality_dot.setFixedSize(14, 14)
266272
self._host_quality_dot.setStyleSheet(
267-
"background-color: #555; border-radius: 7px;",
273+
_QUALITY_DOT_STYLE,
268274
)
269275
self._host_quality_dot.setToolTip(_t("rd_webrtc_quality_unknown"))
270276
sessions_row.addWidget(self._host_quality_dot)
@@ -386,7 +392,7 @@ def _on_export_trust(self) -> None:
386392
import json as _json
387393
path, _filter = QFileDialog.getSaveFileName(
388394
self, _t("rd_webrtc_trust_export"), "trusted_viewers.json",
389-
"JSON (*.json);;All (*)",
395+
_JSON_FILE_FILTER,
390396
)
391397
if not path:
392398
return
@@ -400,7 +406,7 @@ def _on_export_trust(self) -> None:
400406
def _on_import_trust(self) -> None:
401407
import json as _json
402408
path, _filter = QFileDialog.getOpenFileName(
403-
self, _t("rd_webrtc_trust_import"), "", "JSON (*.json);;All (*)",
409+
self, _t("rd_webrtc_trust_import"), "", _JSON_FILE_FILTER,
404410
)
405411
if not path:
406412
return
@@ -810,7 +816,7 @@ def _on_generate_offer(self) -> None:
810816
def _produce_offer(self) -> None:
811817
try:
812818
session_id, offer = self._multi_host.create_session_offer()
813-
except (RuntimeError, OSError, PermissionError) as error:
819+
except (RuntimeError, OSError) as error: # PermissionError is an OSError
814820
self._show_error(error)
815821
return
816822
self._manual_session_id = session_id
@@ -888,14 +894,14 @@ def _on_session_count(self, count: int) -> None:
888894
def _sync_session_pollers(self) -> None:
889895
"""Spawn StatsPoller for new sessions; stop pollers for gone ones."""
890896
if self._multi_host is None:
891-
for poller in list(self._session_pollers.values()):
897+
for poller in list(self._session_pollers.values()): # NOSONAR python:S7504 # snapshot before clear() so a slow stop() doesn't race with the clear that follows
892898
poller.stop()
893899
self._session_pollers.clear()
894900
self._session_cache.reset()
895901
return
896902
active_sids = {s["session_id"] for s in self._multi_host.list_sessions()}
897903
# Stop pollers whose session is gone
898-
for sid in list(self._session_pollers.keys()):
904+
for sid in list(self._session_pollers.keys()): # NOSONAR python:S7504 # the loop deletes from self._session_pollers — list() is required to avoid RuntimeError
899905
if sid not in active_sids:
900906
self._session_pollers[sid].stop()
901907
del self._session_pollers[sid]
@@ -1104,7 +1110,7 @@ def _update_host_quality_dot(self, snapshot: StatsSnapshot) -> None:
11041110

11051111
def _reset_host_quality_dot(self) -> None:
11061112
self._host_quality_dot.setStyleSheet(
1107-
"background-color: #555; border-radius: 7px;",
1113+
_QUALITY_DOT_STYLE,
11081114
)
11091115
self._host_quality_dot.setToolTip(_t("rd_webrtc_quality_unknown"))
11101116

@@ -1231,7 +1237,7 @@ def _stop_host_if_any(self) -> None:
12311237
if self._annotation_overlay is not None:
12321238
self._annotation_overlay.clear()
12331239
self._annotation_overlay.hide()
1234-
for poller in list(self._session_pollers.values()):
1240+
for poller in list(self._session_pollers.values()): # NOSONAR python:S7504 # snapshot before clear() — same reasoning as in _refresh_session_pollers
12351241
poller.stop()
12361242
self._session_pollers.clear()
12371243
self._session_cache.reset()
@@ -1341,7 +1347,7 @@ def _build_ui(self) -> None:
13411347
self._quality_dot = QLabel()
13421348
self._quality_dot.setFixedSize(14, 14)
13431349
self._quality_dot.setStyleSheet(
1344-
"background-color: #555; border-radius: 7px;",
1350+
_QUALITY_DOT_STYLE,
13451351
)
13461352
self._quality_dot.setToolTip(_t("rd_webrtc_quality_unknown"))
13471353
stats_row.addWidget(self._quality_dot)
@@ -1415,7 +1421,7 @@ def _on_toggle_sync(self, checked: bool) -> None:
14151421
),
14161422
)
14171423
self._sync_engine.start()
1418-
except (FileNotFoundError, RuntimeError, OSError) as error:
1424+
except (RuntimeError, OSError) as error: # FileNotFoundError is an OSError
14191425
QMessageBox.warning(self, "WebRTC", str(error))
14201426
self._sync_btn.setChecked(False)
14211427
return
@@ -1778,7 +1784,7 @@ def _on_ab_export(self) -> None:
17781784
import json as _json
17791785
path, _filter = QFileDialog.getSaveFileName(
17801786
self, _t("rd_webrtc_ab_export"), "address_book.json",
1781-
"JSON (*.json);;All (*)",
1787+
_JSON_FILE_FILTER,
17821788
)
17831789
if not path:
17841790
return
@@ -1792,7 +1798,7 @@ def _on_ab_export(self) -> None:
17921798
def _on_ab_import(self) -> None:
17931799
import json as _json
17941800
path, _filter = QFileDialog.getOpenFileName(
1795-
self, _t("rd_webrtc_ab_import"), "", "JSON (*.json);;All (*)",
1801+
self, _t("rd_webrtc_ab_import"), "", _JSON_FILE_FILTER,
17961802
)
17971803
if not path:
17981804
return
@@ -2358,7 +2364,7 @@ def _stop_stats_polling(self) -> None:
23582364
self._stats_label.setText(_t("rd_webrtc_stats_idle"))
23592365
if hasattr(self, "_quality_dot"):
23602366
self._quality_dot.setStyleSheet(
2361-
"background-color: #555; border-radius: 7px;",
2367+
_QUALITY_DOT_STYLE,
23622368
)
23632369
self._quality_dot.setToolTip(_t("rd_webrtc_quality_unknown"))
23642370
if hasattr(self, "_rtt_spark"):

0 commit comments

Comments
 (0)