diff --git a/bec_widgets/utils/bec_widget.py b/bec_widgets/utils/bec_widget.py index 502493e2..bdaefda1 100644 --- a/bec_widgets/utils/bec_widget.py +++ b/bec_widgets/utils/bec_widget.py @@ -80,8 +80,8 @@ class BECWidget(BECConnector): def _connect_to_theme_change(self): """Connect to the theme change signal.""" qapp = QApplication.instance() - if hasattr(qapp, "theme_signal"): - qapp.theme_signal.theme_updated.connect(self._update_theme) + if hasattr(qapp, "theme"): + qapp.theme.theme_changed.connect(self._update_theme) def _update_theme(self, theme: str | None = None): """Update the theme.""" diff --git a/bec_widgets/utils/colors.py b/bec_widgets/utils/colors.py index 78180919..6f58b10d 100644 --- a/bec_widgets/utils/colors.py +++ b/bec_widgets/utils/colors.py @@ -40,72 +40,9 @@ def get_accent_colors() -> AccentColors | None: def apply_theme(theme: Literal["dark", "light"]): """ - Apply the theme to all pyqtgraph widgets. Do not use this function directly. Use set_theme instead. + Apply the theme via the global theming API. This updates QSS, QPalette, and pyqtgraph globally. """ - app = QApplication.instance() - graphic_layouts = [ - child - for top in app.topLevelWidgets() - for child in top.findChildren(pg.GraphicsLayoutWidget) - ] - - plot_items = [ - item - for gl in graphic_layouts - for item in gl.ci.items.keys() # ci is internal pg.GraphicsLayout that hosts all items - if isinstance(item, pg.PlotItem) - ] - - histograms = [ - item - for gl in graphic_layouts - for item in gl.ci.items.keys() # ci is internal pg.GraphicsLayout that hosts all items - if isinstance(item, pg.HistogramLUTItem) - ] - - # Update background color based on the theme - if theme == "light": - background_color = "#e9ecef" # Subtle contrast for light mode - foreground_color = "#141414" - label_color = "#000000" - axis_color = "#666666" - else: - background_color = "#141414" # Dark mode - foreground_color = "#e9ecef" - label_color = "#FFFFFF" - axis_color = "#CCCCCC" - - # update GraphicsLayoutWidget - pg.setConfigOptions(foreground=foreground_color, background=background_color) - for pg_widget in graphic_layouts: - pg_widget.setBackground(background_color) - - # update PlotItems - for plot_item in plot_items: - for axis in ["left", "right", "top", "bottom"]: - plot_item.getAxis(axis).setPen(pg.mkPen(color=axis_color)) - plot_item.getAxis(axis).setTextPen(pg.mkPen(color=label_color)) - - # Change title color - plot_item.titleLabel.setText(plot_item.titleLabel.text, color=label_color) - - # Change legend color - if hasattr(plot_item, "legend") and plot_item.legend is not None: - plot_item.legend.setLabelTextColor(label_color) - # if legend is in plot item and theme is changed, has to be like that because of pg opt logic - for sample, label in plot_item.legend.items: - label_text = label.text - label.setText(label_text, color=label_color) - - # update HistogramLUTItem - for histogram in histograms: - histogram.axis.setPen(pg.mkPen(color=axis_color)) - histogram.axis.setTextPen(pg.mkPen(color=label_color)) - - # now define stylesheet according to theme and apply it - apply_theme_global(theme) # TODO for now this is patch - # style = bec_qthemes.load_stylesheet(theme) - # app.setStyleSheet(style) + apply_theme_global(theme) class Colors: diff --git a/bec_widgets/utils/round_frame.py b/bec_widgets/utils/round_frame.py index 51ec3497..f8399d1b 100644 --- a/bec_widgets/utils/round_frame.py +++ b/bec_widgets/utils/round_frame.py @@ -1,11 +1,12 @@ import pyqtgraph as pg -from qtpy.QtCore import Property +from qtpy.QtCore import Property, Qt from qtpy.QtWidgets import QApplication, QFrame, QHBoxLayout, QVBoxLayout, QWidget from bec_widgets.widgets.utility.visual.dark_mode_button.dark_mode_button import DarkModeButton class RoundedFrame(QFrame): + # TODO this should be removed completely in favor of QSS styling, no time now """ A custom QFrame with rounded corners and optional theme updates. The frame can contain any QWidget, however it is mainly designed to wrap PlotWidgets to provide a consistent look and feel with other BEC Widgets. @@ -28,6 +29,9 @@ class RoundedFrame(QFrame): self.setProperty("skip_settings", True) self.setObjectName("roundedFrame") + # Ensure QSS can paint background/border on this widget + self.setAttribute(Qt.WA_StyledBackground, True) + # Create a layout for the frame if orientation == "vertical": self.layout = QVBoxLayout(self) @@ -45,22 +49,10 @@ class RoundedFrame(QFrame): # Automatically apply initial styles to the GraphicalLayoutWidget if applicable self.apply_plot_widget_style() + self.update_style() def apply_theme(self, theme: str): - """ - Apply the theme to the frame and its content if theme updates are enabled. - """ - if self.content_widget is not None and isinstance( - self.content_widget, pg.GraphicsLayoutWidget - ): - self.content_widget.setBackground(self.background_color) - - # Update background color based on the theme - if theme == "light": - self.background_color = "#e9ecef" # Subtle contrast for light mode - else: - self.background_color = "#141414" # Dark mode - + """Deprecated: RoundedFrame no longer handles theme; styling is QSS-driven.""" self.update_style() @Property(int) @@ -77,34 +69,21 @@ class RoundedFrame(QFrame): """ Update the style of the frame based on the background color. """ - if self.background_color: - self.setStyleSheet( - f""" + self.setStyleSheet( + f""" QFrame#roundedFrame {{ - background-color: {self.background_color}; - border-radius: {self._radius}; /* Rounded corners */ + border-radius: {self._radius}px; }} """ - ) + ) self.apply_plot_widget_style() def apply_plot_widget_style(self, border: str = "none"): """ - Automatically apply background, border, and axis styles to the PlotWidget. - - Args: - border (str): Border style (e.g., 'none', '1px solid red'). + Let QSS/pyqtgraph handle plot styling; avoid overriding here. """ if isinstance(self.content_widget, pg.GraphicsLayoutWidget): - # Apply border style via stylesheet - self.content_widget.setStyleSheet( - f""" - GraphicsLayoutWidget {{ - border: {border}; /* Explicitly set the border */ - }} - """ - ) - self.content_widget.setBackground(self.background_color) + self.content_widget.setStyleSheet("") class ExampleApp(QWidget): # pragma: no cover @@ -128,24 +107,14 @@ class ExampleApp(QWidget): # pragma: no cover plot_item_2.plot([1, 2, 4, 8, 16, 32], pen="r") plot2.plot_item = plot_item_2 - # Wrap PlotWidgets in RoundedFrame - rounded_plot1 = RoundedFrame(parent=self, content_widget=plot1) - rounded_plot2 = RoundedFrame(parent=self, content_widget=plot2) - - # Add to layout + # Add to layout (no RoundedFrame wrapper; QSS styles plots) layout.addWidget(dark_button) - layout.addWidget(rounded_plot1) - layout.addWidget(rounded_plot2) + layout.addWidget(plot1) + layout.addWidget(plot2) self.setLayout(layout) - from qtpy.QtCore import QTimer - - def change_theme(): - rounded_plot1.apply_theme("light") - rounded_plot2.apply_theme("dark") - - QTimer.singleShot(100, change_theme) + # Theme flip demo removed; global theming applies automatically if __name__ == "__main__": # pragma: no cover diff --git a/bec_widgets/widgets/plots/plot_base.py b/bec_widgets/widgets/plots/plot_base.py index 1e112ed7..f213aa26 100644 --- a/bec_widgets/widgets/plots/plot_base.py +++ b/bec_widgets/widgets/plots/plot_base.py @@ -135,7 +135,7 @@ class PlotBase(BECWidget, QWidget): self._init_ui() self._connect_to_theme_change() - self._update_theme() + self._update_theme(None) def apply_theme(self, theme: str): self.round_plot_widget.apply_theme(theme) @@ -143,6 +143,8 @@ class PlotBase(BECWidget, QWidget): def _init_ui(self): self.layout.addWidget(self.layout_manager) self.round_plot_widget = RoundedFrame(parent=self, content_widget=self.plot_widget) + self.round_plot_widget.setProperty("variant", "plot_background") + self.round_plot_widget.setProperty("frameless", True) self.layout_manager.add_widget(self.round_plot_widget) self.layout_manager.add_widget_relative(self.fps_label, self.round_plot_widget, "top") diff --git a/bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py b/bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py index 76311605..bdff2b54 100644 --- a/bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py +++ b/bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py @@ -3,12 +3,11 @@ from __future__ import annotations import json from typing import TYPE_CHECKING -from qtpy.QtWidgets import QApplication - from bec_lib.logger import bec_logger from bec_qthemes._icon.material_icons import material_icon from qtpy.QtCore import Qt from qtpy.QtWidgets import ( + QApplication, QComboBox, QHBoxLayout, QHeaderView,