Source code for qdarktheme.main

"""Main file of qdarktheme."""
from __future__ import annotations

import json
import re
import sys
from pathlib import Path

from qdarktheme.util import OPERATORS, compare_v, get_logger, get_qdarktheme_root_path, multi_replace

_logger = get_logger(__name__)


class _SvgFileNotFoundError(FileNotFoundError):

    pass


[docs]def get_themes() -> tuple[str, ...]: """Return available theme list. Returns: Available themes. """ from qdarktheme.themes import THEMES return THEMES
def _get_qt_version() -> str: from qdarktheme.qtpy import __version__ as qt_version if qt_version is None: _logger.warning( "Failed to detect Qt version. -> Load stylesheet as the latest version." + "\nMaybe you need to install qt-binding. Available Qt-binding packages: PySide6, PyQt6, PyQt5, PySide2." ) return "10.0.0" # Fairly future version for always setting latest version. return qt_version def _parse_env_patch(stylesheet: str) -> dict[str, str]: """Parse `$env_patch{...}` symbol in template stylesheet. Template stylesheet has `$env_patch{...}` symbol. This symbol has json string and resolve the differences of the style between qt versions. The json keys: * version - the qt version and qualifier. Available qualifiers: [==, !=, >=, <=, >, <]. * value - the qt stylesheet string Args: stylesheet: The qt stylesheet string. Raises: SyntaxError: If the version operator in version key of `$env_patch{...}` is wrong. Returns: The dictionary. Key is the text of $env_patch{...} symbol. Value is the value of the `value` key in $env_patch. """ replacements = {} for match in re.finditer(r"\$env_patch\{[\s\S]*?\}", stylesheet): match_text = match.group() json_text = match_text.replace("$env_patch", "") env_property: dict[str, str] = json.loads(json_text) for operator in OPERATORS.keys(): if operator in env_property["version"]: version = env_property["version"].replace(operator, "") qt_version = _get_qt_version() replacements[match_text] = env_property["value"] if compare_v(qt_version, operator, version) else "" break else: raise SyntaxError( f"invalid character in qualifier. Available qualifiers {list(OPERATORS.keys())}" ) from None return replacements
[docs]def load_stylesheet(theme: str = "dark") -> str: """Load the style sheet which looks like flat design. There are two themes, dark theme and light theme. Args: theme: The name of the theme. Available theme are "dark" and "light". Raises: TypeError: If the arg of theme name is wrong. Returns: The stylesheet string for the given theme. Examples: Set stylesheet to your Qt application. 1. Dark Theme:: app = QApplication([]) app.setStyleSheet(qdarktheme.load_stylesheet()) # or app.setStyleSheet(qdarktheme.load_stylesheet("dark")) 2. Light Theme:: app = QApplication([]) app.setStyleSheet(qdarktheme.load_stylesheet("light")) """ if theme not in get_themes(): raise TypeError("The argument [theme] can only be specified as 'dark' or 'light'.") from None if theme == "dark": from qdarktheme.themes.dark.stylesheet import STYLE_SHEET else: from qdarktheme.themes.light.stylesheet import STYLE_SHEET # Append Qt version patches replacements = _parse_env_patch(STYLE_SHEET) stylesheet = multi_replace(STYLE_SHEET, replacements) from qdarktheme.qtpy import QtImportError qt_version = _get_qt_version() try: # In mac os, if the qt version is 5.13 or lower, the svg icon of Qt resource file cannot be read correctly. if compare_v(qt_version, "<", "5.13.0"): raise _SvgFileNotFoundError() if theme == "dark": from qdarktheme.themes.dark import rc_icons as _ elif theme == "light": from qdarktheme.themes.light import rc_icons as _ # noqa: F401 icon_path = ":qdarktheme" except (AttributeError, QtImportError, _SvgFileNotFoundError): # Qt resource system has been removed in PyQt6. So in PyQt6, load the icon from a physical file. # PyInstaller's one file option uses temp dir(_MEIPASS). if hasattr(sys, "_MEIPASS"): module_path = Path(sys._MEIPASS) / "qdarktheme" # type: ignore icon_path = module_path.as_posix() else: icon_path = get_qdarktheme_root_path().as_posix() # Replace the ${path} variable by real path value return stylesheet.replace("${path}", icon_path)
[docs]def load_palette(theme: str = "dark"): """Load the QPalette for the dark or light theme. Args: theme: The name of the theme. Available theme are "dark" and "light". Raises: TypeError: If the arg name of theme is wrong. Returns: QPalette: The QPalette for the given theme. Examples: Set QPalette to your Qt application. 1. Dark Theme:: app = QApplication([]) app.setPalette(qdarktheme.load_palette()) # or app.setPalette(qdarktheme.load_palette("dark")) 2. Light Theme:: app = QApplication([]) app.setPalette(qdarktheme.load_palette("light")) """ if theme not in get_themes(): raise TypeError("The argument [theme] can only be specified as 'dark' or 'light'.") from None if theme == "dark": from qdarktheme.themes.dark.palette import PALETTE else: from qdarktheme.themes.light.palette import PALETTE return PALETTE