From 8972afb5aba77a69f7c2b61e2cf999ff1411c7c8 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Wed, 29 Nov 2023 19:43:25 +0100 Subject: [PATCH] application: Reconfigure stylesheet on application palette changes --- orangecanvas/application/application.py | 3 +++ .../application/tests/test_application.py | 8 ++++++++ orangecanvas/application/tests/test_main.py | 19 +++++++++++++++++++ orangecanvas/main.py | 16 +++++++++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/orangecanvas/application/application.py b/orangecanvas/application/application.py index 6073d5017..18e1410dc 100644 --- a/orangecanvas/application/application.py +++ b/orangecanvas/application/application.py @@ -110,6 +110,7 @@ def maybe_match_prefix(prefix: str, path: str) -> Optional[str]: class CanvasApplication(QApplication): fileOpenRequest = Signal(QUrl) + applicationPaletteChanged = Signal() __args = None @@ -160,6 +161,8 @@ def event(self, event): self.fileOpenRequest.emit(event.url()) elif event.type() == QEvent.PolishRequest: self.configureStyle() + elif event.type() == QEvent.Type.ApplicationPaletteChange: + self.applicationPaletteChanged.emit() return super().event(event) def exec(self) -> int: diff --git a/orangecanvas/application/tests/test_application.py b/orangecanvas/application/tests/test_application.py index 479324a3e..01caf9486 100644 --- a/orangecanvas/application/tests/test_application.py +++ b/orangecanvas/application/tests/test_application.py @@ -3,6 +3,9 @@ import time import unittest +from AnyQt.QtGui import QPalette +from AnyQt.QtTest import QSignalSpy + from orangecanvas.utils import shtools as sh from orangecanvas.application import application as appmod from orangecanvas.utils.shtools import temp_named_file @@ -10,6 +13,11 @@ def application_test_helper(): app = appmod.CanvasApplication([]) + p = app.palette() + spy = QSignalSpy(app.applicationPaletteChanged) + p.setColor(QPalette.Base, p.color(QPalette.Text)) + app.setPalette(p) + assert list(spy) == [[]] app.quit() return diff --git a/orangecanvas/application/tests/test_main.py b/orangecanvas/application/tests/test_main.py index 927375e87..841763299 100644 --- a/orangecanvas/application/tests/test_main.py +++ b/orangecanvas/application/tests/test_main.py @@ -5,6 +5,9 @@ from typing import Iterable from unittest.mock import patch, Mock +from AnyQt.QtCore import Qt +from AnyQt.QtGui import QPalette + from orangecanvas import config from orangecanvas.application.canvasmain import CanvasMainWindow from orangecanvas.config import Config, EntryPoint @@ -131,3 +134,19 @@ def test_run_with_file(self): res = m.run(["-", "--no-welcome", "--no-splash", fname]) CanvasMainWindow.open_scheme_file.assert_called_with(fname) self.assertEqual(res, 42) + + @with_patched_main_application + def test_run_stylesheet_reconfigure(self): + m = Main() + m.parse_arguments(["-", "--config", f"{__name__}.TestConfig"]) + m.window = m.create_main_window() + m.application = self.app + + def setpalette(color): + self.app.setPalette(QPalette(color)) + m._Main__reconfigure_stylesheet() + + setpalette(Qt.white) + sheet = m.window.styleSheet() + setpalette(Qt.black) + self.assertNotEqual(sheet, m.window.styleSheet()) diff --git a/orangecanvas/main.py b/orangecanvas/main.py index bb655d22b..468942500 100644 --- a/orangecanvas/main.py +++ b/orangecanvas/main.py @@ -1,7 +1,6 @@ """ """ import argparse - import os import sys import gc @@ -9,7 +8,7 @@ import pickle import shlex import warnings -from typing import List, Optional, IO, Any +from typing import List, Optional, IO, Any, Iterable from urllib.request import getproxies from contextlib import ExitStack, closing @@ -176,6 +175,7 @@ def setup_application(self): # sys.argv[0] must be in QApplication's argv list. self.application = CanvasApplication(sys.argv[:1] + self.arguments) self.application.setWindowIcon(self.config.application_icon()) + self.application.applicationPaletteChanged.connect(self.__reconfigure_stylesheet) # Update the arguments self.arguments = self.application.arguments()[1:] fix_set_proxy_env() @@ -289,7 +289,7 @@ def create_main_window(self) -> CanvasMainWindow: """Create the (initial) main window.""" return CanvasMainWindow() - window: CanvasMainWindow + window: Optional[CanvasMainWindow] = None def setup_main_window(self): stylesheet = self.main_window_stylesheet() @@ -377,6 +377,16 @@ def tear_down_sys_redirections(self): if self.__stdout__ is not None: sys.stdout = self.__stdout__ + def _main_windows(self) -> Iterable[CanvasMainWindow]: + first = self.window + return *((first,) if first else ()), *CanvasMainWindow._instances + + def __reconfigure_stylesheet(self) -> None: + ssheet = self.main_window_stylesheet() + for inst in self._main_windows(): + if inst.styleSheet() != ssheet: + inst.setStyleSheet(ssheet) + def fix_win_pythonw_std_stream(): """