Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: f187e303 by wurstsalat at 2022-12-10T17:41:38+01:00 cq: Add stubs for css_parser
- - - - -
6 changed files:
- gajim/gtk/css_config.py - pyproject.toml - + typings/css_parser/__init__.pyi - + typings/css_parser/css.pyi - + typings/css_parser/serialize.pyi - + typings/css_parser/stylesheets.pyi
Changes:
===================================== gajim/gtk/css_config.py ===================================== @@ -25,14 +25,18 @@ from pathlib import Path import sys
+import css_parser +from css_parser.css import CSSStyleSheet +from css_parser.css import CSSStyleRule + from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Pango -import css_parser
from gajim.common import app from gajim.common import configpaths -from gajim.common.const import StyleAttr, CSSPriority +from gajim.common.const import StyleAttr +from gajim.common.const import CSSPriority from gajim.common.dbus.system_style import SystemStyleListener
from .const import Theme @@ -77,16 +81,16 @@ def __init__(self) -> None: css_parser.ser.prefs.keepEmptyRules = False
# Holds the currently selected theme in the Theme Editor - self._pre_css: Optional[css_parser.css.CSSStyleSheet] = None + self._pre_css: Optional[CSSStyleSheet] = None self._pre_css_path: Optional[Path] = None
# Holds the default theme, its used if values are not found # in the selected theme - self._default_css: Optional[css_parser.css.CSSStyleSheet] = None + self._default_css: Optional[CSSStyleSheet] = None self._default_css_path: Optional[Path] = None
# Holds the currently selected theme - self._css: Optional[css_parser.css.CSSStyleSheet] = None + self._css: Optional[CSSStyleSheet] = None self._css_path: Optional[Path] = None
# User Theme CSS Provider @@ -97,8 +101,10 @@ def __init__(self) -> None: self._dynamic_dict: dict[str, str] = {} self.refresh()
+ screen = Gdk.Screen.get_default() + assert screen is not None Gtk.StyleContext.add_provider_for_screen( - Gdk.Screen.get_default(), + screen, self._dynamic_provider, CSSPriority.APPLICATION)
@@ -118,7 +124,7 @@ def __init__(self) -> None: self._activate_theme()
Gtk.StyleContext.add_provider_for_screen( - Gdk.Screen.get_default(), + screen, self._provider, CSSPriority.USER_THEME)
@@ -180,7 +186,9 @@ def _activate_css(self, css: str, priority: CSSPriority) -> None: try: provider = Gtk.CssProvider() provider.load_from_data(bytes(css.encode('utf-8'))) - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), + screen = Gdk.Screen.get_default() + assert screen is not None + Gtk.StyleContext.add_provider_for_screen(screen, provider, priority) self._load_selected() @@ -198,7 +206,9 @@ def _apply_windows_font_size() -> None: ''' provider = Gtk.CssProvider() provider.load_from_data(bytes(css.encode('utf-8'))) - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), + screen = Gdk.Screen.get_default() + assert screen is not None + Gtk.StyleContext.add_provider_for_screen(screen, provider, CSSPriority.PRE_APPLICATION)
@@ -265,6 +275,9 @@ def _write(self, pre: bool) -> None: if pre: path = self._pre_css_path css = self._pre_css + + assert path is not None + assert css is not None with open(path, 'w', encoding='utf-8') as file: file.write(css.cssText.decode('utf-8'))
@@ -275,12 +288,14 @@ def _write(self, pre: bool) -> None:
def set_value(self, selector: str, - attr: StyleAttr, + attr: Union[str, StyleAttr], value: Union[str, Pango.FontDescription], pre: bool = False ) -> None: + if attr == StyleAttr.FONT: # forward to set_font() for convenience + assert isinstance(value, Pango.FontDescription) self.set_font(selector, value, pre) return
@@ -290,6 +305,8 @@ def set_value(self, css = self._css if pre: css = self._pre_css + + assert css is not None for rule in css: if rule.type != rule.STYLE_RULE: continue @@ -303,7 +320,7 @@ def set_value(self,
# The rule was not found, so we add it to this theme log.info('Set %s %s %s', selector, attr, value) - rule = css_parser.css.CSSStyleRule(selectorText=selector) + rule = CSSStyleRule(selectorText=selector) rule.style[attr] = value css.add(rule) self._write(pre) @@ -318,6 +335,7 @@ def set_font(self, css = self._pre_css family, size, style, weight = self._get_attr_from_description( description) + assert css is not None for rule in css: if rule.type != rule.STYLE_RULE: continue @@ -338,7 +356,7 @@ def set_font(self, # The rule was not found, so we add it to this theme log.info('Set Font for: %s %s %s %s %s', selector, family, size, style, weight) - rule = css_parser.css.CSSStyleRule(selectorText=selector) + rule = CSSStyleRule(selectorText=selector) rule.style['font-family'] = family rule.style['font-style'] = style rule.style['font-size'] = f'{size}pt' @@ -349,6 +367,7 @@ def set_font(self, def _get_attr_from_description(self, description: Pango.FontDescription ) -> tuple[Optional[str], float, str, int]: + size = description.get_size() / Pango.SCALE style = self._get_string_from_pango_style(description.get_style()) weight = self._pango_to_css_weight(int(description.get_weight())) @@ -357,8 +376,10 @@ def _get_attr_from_description(self,
def _get_default_rule(self, selector: str, - _attr: StyleAttr - ) -> Optional[css_parser.css.CSSStyleRule]: + _attr: str + ) -> Optional[CSSStyleRule]: + + assert self._default_css is not None for rule in self._default_css: if rule.type != rule.STYLE_RULE: continue @@ -376,7 +397,9 @@ def get_font(self, else: css = self._css try: - return self._get_from_cache(selector, 'fontdescription') + font_desc = self._get_from_cache(selector, 'fontdescription') + if isinstance(font_desc, Pango.FontDescription): + return font_desc except KeyError: pass
@@ -408,6 +431,7 @@ def _get_description_from_css(self, style: Optional[str], weight: Optional[str] ) -> Optional[Pango.FontDescription]: + if family is None: return None desc = Pango.FontDescription() @@ -440,9 +464,10 @@ def _get_string_from_pango_style(style: Pango.Style) -> str:
def get_value(self, selector: str, - attr: StyleAttr, + attr: Union[str, StyleAttr], pre: bool = False ) -> Union[str, Pango.FontDescription, None]: + if attr == StyleAttr.FONT: # forward to get_font() for convenience return self.get_font(selector, pre) @@ -482,9 +507,10 @@ def get_value(self,
def remove_value(self, selector: str, - attr: StyleAttr, + attr: Union[str, StyleAttr], pre: bool = False ) -> None: + if attr == StyleAttr.FONT: # forward to remove_font() for convenience self.remove_font(selector, pre) @@ -496,6 +522,8 @@ def remove_value(self, css = self._css if pre: css = self._pre_css + + assert css is not None for rule in css: if rule.type != rule.STYLE_RULE: continue @@ -510,6 +538,7 @@ def remove_font(self, selector: str, pre: bool = False) -> None: if pre: css = self._pre_css
+ assert css is not None for rule in css: if rule.type != rule.STYLE_RULE: continue @@ -566,6 +595,7 @@ def rename_theme(self, old_theme: str, new_theme: str) -> bool: def _activate_theme(self) -> None: log.info('Activate theme') self._invalidate_cache() + assert self._css is not None self._provider.load_from_data(self._css.cssText)
def add_new_theme(self, theme: str) -> bool: @@ -588,15 +618,17 @@ def remove_theme(self, theme: str) -> None:
def _add_to_cache(self, selector: str, - attr: StyleAttr, + attr: str, value: Union[str, Pango.FontDescription, None] ) -> None: + self._cache[selector + attr] = value
def _get_from_cache(self, selector: str, - attr: StyleAttr + attr: str ) -> Union[str, Pango.FontDescription, None]: + return self._cache[selector + attr]
def _invalidate_cache(self) -> None:
===================================== pyproject.toml ===================================== @@ -91,6 +91,7 @@ include = [ "gajim/gtk/contacts_flowbox.py", "gajim/gtk/control.py", "gajim/gtk/conversation/*", + "gajim/gtk/css_config.py", "gajim/gtk/dialogs.py", "gajim/gtk/emoji_data_gtk.py", "gajim/gtk/exception.py",
===================================== typings/css_parser/__init__.pyi ===================================== @@ -0,0 +1,18 @@ +from __future__ import annotations + +from typing import Optional +from typing import Union + +from pathlib import Path + +from . import css as css +from . import serialize as serialize +from . import stylesheets as stylesheets +from .stylesheets import MediaList +from .serialize import CSSSerializer + + +ser: CSSSerializer + + +def parseFile(filename: Union[str, Path], href: Optional[str] = ..., media: Union[MediaList, list[str], str, None] = ..., title: Optional[str] = ..., validate: Optional[bool] = ...) -> None: ...
===================================== typings/css_parser/css.pyi ===================================== @@ -0,0 +1,34 @@ +from __future__ import annotations + +from typing import Any + + +class CSSRule: + + STYLE_RULE: int + + +class CSSStyleSheet: + + cssText: bytes + + def __iter__(self) -> CSSStyleRule: ... + def add(self, rule: CSSStyleRule) -> None: ... + + +class CSSStyleRule(CSSRule): + + style: CSSStyleDeclaration + type: int + selectorText: str + + def __init__(self, selectorText: str) -> None: ... + def __next__(self) -> CSSStyleRule: ... + + +class CSSStyleDeclaration: + + def __getitem__(self, cssname: str) -> str: ... + def __setitem__(self, cssname: str, value: Any) -> None: ... + def getPropertyValue(self, property: str) -> Any: ... + def removeProperty(self, property: str) -> None: ...
===================================== typings/css_parser/serialize.pyi ===================================== @@ -0,0 +1,11 @@ +from __future__ import annotations + + +class CSSSerializer: + + prefs: Preferences + + +class Preferences: + + keepEmptyRules: bool
===================================== typings/css_parser/stylesheets.pyi ===================================== @@ -0,0 +1,10 @@ +from __future__ import annotations + + +class MediaList: + ... + + +class StyleSheet: + + cssText: bytes
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/commit/f187e3034a12006ed1d47f360fb4021b2...