From be6e8ec356166c2df0fba443a086afc971aaefbd Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Mon, 21 Sep 2026 00:24:25 -0600 Subject: Fix white native-chrome artifacts on dark theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QSS alone doesn't reach everything Qt draws — splitter/dock separator grip-dot decorations and a checkable QMenu item's tick come from the app's QPalette, which was never set (stylesheet-only theming), so they stayed Qt's default light palette under the dark stylesheet: - MainWindow._apply_theme() now also sets a matching dark QPalette (restored to the style's standard palette for light theme). - QMainWindow::separator and a generic QMenu rule (only #profileMenu was styled before — the toolbar's View menu had no objectName and so no styling at all) added to style_dark.qss, with QMenu::indicator styled as a filled/outline square so checkmarks are visible regardless of palette. - QTabWidget/QTabBar (the bare containers, not ::pane/::tab) had no background set, so the strip beside the tab buttons fell back to the light palette — fixed globally, covers both the Devices/Channels/Plot config tabs and the Settings window since both share the same QTabWidget styling. Co-Authored-By: Claude Sonnet 5 --- ui/main_window.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'ui/main_window.py') diff --git a/ui/main_window.py b/ui/main_window.py index 07ab0b2..d7c297f 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -13,7 +13,7 @@ from PyQt6.QtWidgets import ( QAbstractSpinBox, QComboBox, QMenu, ) from PyQt6.QtCore import Qt, QTimer, QObject, QEvent, QRect, QByteArray, pyqtSignal, pyqtSlot -from PyQt6.QtGui import QPainter, QColor, QFont, QAction +from PyQt6.QtGui import QPainter, QColor, QFont, QAction, QPalette import logging import base64 import os @@ -822,8 +822,39 @@ class MainWindow(QMainWindow): if os.path.exists(qss_file): with open(qss_file) as f: QApplication.instance().setStyleSheet(f.read()) + self._apply_palette(theme) self._chart.set_theme(theme) + def _apply_palette(self, theme: str): + """QSS alone doesn't reach every Qt-drawn pixel — a splitter/dock + separator's grip-dot decoration, a QMenu's checkmark tick, etc. are + drawn from the app's QPalette, not stylesheet background-color. + Without ever setting one, those stay Qt's default light palette + regardless of the dark stylesheet, showing up as stray white dots/ + slivers on top of otherwise-correctly-dark widgets.""" + app = QApplication.instance() + if theme == "dark": + pal = QPalette() + pal.setColor(QPalette.ColorRole.Window, QColor("#0b0e13")) + pal.setColor(QPalette.ColorRole.WindowText, QColor("#c7d2fe")) + pal.setColor(QPalette.ColorRole.Base, QColor("#111620")) + pal.setColor(QPalette.ColorRole.AlternateBase, QColor("#161d2e")) + pal.setColor(QPalette.ColorRole.Text, QColor("#c7d2fe")) + pal.setColor(QPalette.ColorRole.Button, QColor("#161d2e")) + pal.setColor(QPalette.ColorRole.ButtonText, QColor("#c7d2fe")) + pal.setColor(QPalette.ColorRole.Highlight, QColor("#3b82f6")) + pal.setColor(QPalette.ColorRole.HighlightedText, QColor("#0b0e13")) + pal.setColor(QPalette.ColorRole.ToolTipBase, QColor("#161d2e")) + pal.setColor(QPalette.ColorRole.ToolTipText, QColor("#c7d2fe")) + pal.setColor(QPalette.ColorRole.Light, QColor("#2a3558")) + pal.setColor(QPalette.ColorRole.Midlight, QColor("#2a3558")) + pal.setColor(QPalette.ColorRole.Dark, QColor("#060810")) + pal.setColor(QPalette.ColorRole.Mid, QColor("#1c2540")) + pal.setColor(QPalette.ColorRole.Shadow, QColor("#000000")) + app.setPalette(pal) + else: + app.setPalette(app.style().standardPalette()) + def _apply_settings_on_startup(self): self._apply_theme(self._settings.get("theme", "dark")) self.engine._interval = self._settings.get("poll_ms", 100) / 1000.0 -- cgit v1.2.3