diff options
Diffstat (limited to 'poezio/theming.py')
-rwxr-xr-x | poezio/theming.py | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/poezio/theming.py b/poezio/theming.py index bbf2fb64..187d07c5 100755 --- a/poezio/theming.py +++ b/poezio/theming.py @@ -1,9 +1,10 @@ +#!/usr/bin/env python3 # Copyright 2010-2011 Florent Le Coz <louiz@louiz.org> # # This file is part of Poezio. # # Poezio is free software: you can redistribute it and/or modify -# it under the terms of the zlib license. See the COPYING file. +# it under the terms of the GPL-3.0+ license. See the COPYING file. """ Define the variables (colors and some other stuff) that are used when drawing the interface. @@ -73,11 +74,11 @@ except ImportError: import curses import functools -import os -from typing import Dict, List, Union, Tuple, Optional +from typing import Dict, List, Union, Tuple, Optional, cast from pathlib import Path from os import path from poezio import colors, xdg +from datetime import datetime from importlib import machinery finder = machinery.PathFinder() @@ -143,6 +144,14 @@ class Theme: return sub_mapping[sub] if sub == keep else '' return sub_mapping.get(sub, '') + # Short date format (only show time) + SHORT_TIME_FORMAT = '%H:%M:%S' + SHORT_TIME_FORMAT_LENGTH = len(datetime.now().strftime(SHORT_TIME_FORMAT)) + + # Long date format (show date and time) + LONG_TIME_FORMAT = '%Y-%m-%d %H:%M:%S' + LONG_TIME_FORMAT_LENGTH = len(datetime.now().strftime(LONG_TIME_FORMAT)) + # Message text color COLOR_NORMAL_TEXT = (-1, -1) COLOR_INFORMATION_TEXT = (5, -1) # TODO @@ -178,12 +187,13 @@ class Theme: CHAR_CHATSTATE_COMPOSING = 'X' CHAR_CHATSTATE_PAUSED = 'p' - # These characters are used for the affiliation in the user list - # in a MUC + # These characters are used for the affiliation wherever needed, e.g., in + # the user list in a MUC, or when displaying affiliation lists. CHAR_AFFILIATION_OWNER = '~' CHAR_AFFILIATION_ADMIN = '&' CHAR_AFFILIATION_MEMBER = '+' CHAR_AFFILIATION_NONE = '-' + CHAR_AFFILIATION_OUTCAST = '!' # XML Tab CHAR_XML_IN = 'IN ' @@ -224,6 +234,15 @@ class Theme: COLOR_TAB_ATTENTION = (7, 1) COLOR_TAB_DISCONNECTED = (7, 8) + # If autocolor_tab_names is set to true, the following modes are used to + # distinguish tabs with normal and important messages. + MODE_TAB_NORMAL = '' + MODE_TAB_IMPORTANT = 'r' # reverse video mode + + # This is the mode used for the tab name in the info bar of MUC and 1:1 + # chat tabs. + MODE_TAB_NAME = 'r' + COLOR_VERTICAL_TAB_NORMAL = (4, -1) COLOR_VERTICAL_TAB_NONEMPTY = (4, -1) COLOR_VERTICAL_TAB_JOINED = (82, -1) @@ -281,7 +300,7 @@ class Theme: (224, -1), (225, -1), (226, -1), (227, -1)] # XEP-0392 consistent color generation palette placeholder # it’s generated on first use when accessing the ccg_palette property - CCG_PALETTE = None # type: Optional[Dict[float, int]] + CCG_PALETTE: Optional[Dict[float, int]] = None CCG_Y = 0.5**0.45 # yapf: enable @@ -315,7 +334,9 @@ class Theme: COLOR_COLUMN_HEADER_SEL = (4, 36) # Strings for special messages (like join, quit, nick change, etc) - # Special messages + CHAR_BEFORE_NICK_ME = '* ' + CHAR_AFTER_NICK_ME = ' ' + CHAR_AFTER_NICK = '> ' CHAR_JOIN = '--->' CHAR_QUIT = '<---' CHAR_KICK = '-!-' @@ -358,7 +379,7 @@ class Theme: # Info messages color (the part before the ">") INFO_COLORS = { 'info': (5, -1), - 'error': (16, 1), + 'error': (9, 7, 'b'), 'warning': (1, -1), 'roster': (2, -1), 'help': (10, -1), @@ -371,7 +392,7 @@ class Theme: } @property - def ccg_palette(self): + def ccg_palette(self) -> Optional[Dict[float, int]]: prepare_ccolor_palette(self) return self.CCG_PALETTE @@ -383,8 +404,7 @@ theme = Theme() # Each time we use a color tuple, we check if it has already been used. # If not we create a new color_pair and keep it in that dict, to use it # the next time. -curses_colors_dict = { -} # type: Dict[Union[Tuple[int, int], Tuple[int, int, str]], int] +curses_colors_dict: Dict[Union[Tuple[int, int], Tuple[int, int, str]], int] = {} # yapf: disable @@ -408,7 +428,7 @@ table_256_to_16 = [ ] # yapf: enable -load_path = [] # type: List[str] +load_path: List[str] = [] def color_256_to_16(color): @@ -441,13 +461,14 @@ def to_curses_attr( returns a valid curses attr that can be passed directly to attron() or attroff() """ # extract the color from that tuple + colors: Union[Tuple[int, int], Tuple[int, int, str]] if len(color_tuple) == 3: colors = (color_tuple[0], color_tuple[1]) else: colors = color_tuple bold = False - if curses.COLORS != 256: + if curses.COLORS < 256: # We are not in a term supporting 256 colors, so we convert # colors to numbers between -1 and 8 colors = (color_256_to_16(colors[0]), color_256_to_16(colors[1])) @@ -466,7 +487,7 @@ def to_curses_attr( curses_colors_dict[colors] = pair curses_pair = curses.color_pair(pair) if len(color_tuple) == 3: - additional_val = color_tuple[2] + _, _, additional_val = cast(Tuple[int, int, str], color_tuple) if 'b' in additional_val or bold is True: curses_pair = curses_pair | curses.A_BOLD if 'u' in additional_val: @@ -476,6 +497,8 @@ def to_curses_attr( curses, 'A_ITALIC') else curses.A_REVERSE) if 'a' in additional_val: curses_pair = curses_pair | curses.A_BLINK + if 'r' in additional_val: + curses_pair = curses_pair | curses.A_REVERSE return curses_pair @@ -498,7 +521,7 @@ def update_themes_dir(option: Optional[str] = None, load_path.append(default_dir) # import from the user-defined prefs - themes_dir_str = config.get('themes_dir') + themes_dir_str = config.getstr('themes_dir') themes_dir = Path(themes_dir_str).expanduser( ) if themes_dir_str else xdg.DATA_HOME / 'themes' try: @@ -544,7 +567,7 @@ def prepare_ccolor_palette(theme: Theme) -> None: def reload_theme() -> Optional[str]: - theme_name = config.get('theme') + theme_name = config.getstr('theme') global theme if theme_name == 'default' or not theme_name.strip(): theme = Theme() @@ -552,10 +575,10 @@ def reload_theme() -> Optional[str]: new_theme = None exc = None try: - loader = finder.find_module(theme_name, load_path) - if not loader: + spec = finder.find_spec(theme_name, path=load_path) + if not spec or not spec.loader: return 'Failed to load the theme %s' % theme_name - new_theme = loader.load_module() + new_theme = spec.loader.load_module(theme_name) except Exception as e: log.error('Failed to load the theme %s', theme_name, exc_info=True) exc = e @@ -564,7 +587,7 @@ def reload_theme() -> Optional[str]: return 'Failed to load theme: %s' % exc if hasattr(new_theme, 'theme'): - theme = new_theme.theme + theme = new_theme.theme # type: ignore prepare_ccolor_palette(theme) return None return 'No theme present in the theme file' |