Philipp Hörist pushed to branch master at gajim / gajim
Commits: cb8b56c2 by lovetox at 2021-12-08T21:31:32+01:00 Avatar: Add type annotations
- - - - - ef536737 by lovetox at 2021-12-08T21:31:53+01:00 StatusSelector: Add type annotations
- - - - - d1028e5b by lovetox at 2021-12-08T21:32:27+01:00 Avatar: Remove unused method
- - - - - 24686eed by lovetox at 2021-12-08T21:35:12+01:00 Remove obsolete Contact code
- - - - -
5 changed files:
- gajim/common/modules/chatstates.py - gajim/common/modules/ping.py - gajim/common/types.py - gajim/gtk/avatar.py - gajim/gtk/status_selector.py
Changes:
===================================== gajim/common/modules/chatstates.py ===================================== @@ -32,7 +32,6 @@ from gajim.common.structs import OutgoingMessage from gajim.common.modules.base import BaseModule
-from gajim.common.types import ContactT from gajim.common.types import ConnectionT
@@ -184,13 +183,13 @@ def get_remote_chatstate(self, jid): return self._remote_chatstate.get(jid)
@ensure_enabled - def set_active(self, contact: ContactT) -> None: + def set_active(self, contact) -> None: if contact.settings.get('send_chatstate') == 'disabled': return self._last_mouse_activity[contact.jid] = time.time() self._chatstates[contact.jid] = State.ACTIVE
- def get_active_chatstate(self, contact: ContactT) -> Optional[str]: + def get_active_chatstate(self, contact) -> Optional[str]: # determines if we add 'active' on outgoing messages if contact.settings.get('send_chatstate') == 'disabled': return None @@ -207,7 +206,7 @@ def get_active_chatstate(self, contact: ContactT) -> Optional[str]: return 'active'
@ensure_enabled - def block_chatstates(self, contact: ContactT, block: bool) -> None: + def block_chatstates(self, contact, block: bool) -> None: # Block sending chatstates to a contact # Used for example if we cycle through the MUC nick list, which # produces a lot of buffer 'changed' signals from the input textview. @@ -218,7 +217,7 @@ def block_chatstates(self, contact: ContactT, block: bool) -> None: self._blocked.remove(contact.jid)
@ensure_enabled - def set_chatstate_delayed(self, contact: ContactT, state: State) -> None: + def set_chatstate_delayed(self, contact, state: State) -> None: # Used when we go from Composing -> Active after deleting all text # from the Textview. We delay the Active state because maybe the # User starts writing again. @@ -227,7 +226,7 @@ def set_chatstate_delayed(self, contact: ContactT, state: State) -> None: 2, self.set_chatstate, contact, state)
@ensure_enabled - def set_chatstate(self, contact: ContactT, state: State) -> None: + def set_chatstate(self, contact, state: State) -> None: # Don’t send chatstates to ourself if self._con.get_own_jid().bare_match(contact.jid): return @@ -298,7 +297,7 @@ def _send_chatstate(self, contact, chatstate): self._con.send_message(message)
@ensure_enabled - def set_mouse_activity(self, contact: ContactT, was_paused: bool) -> None: + def set_mouse_activity(self, contact, was_paused: bool) -> None: if contact.settings.get('send_chatstate') == 'disabled': return self._last_mouse_activity[contact.jid] = time.time() @@ -309,7 +308,7 @@ def set_mouse_activity(self, contact: ContactT, was_paused: bool) -> None: self.set_chatstate(contact, State.ACTIVE)
@ensure_enabled - def set_keyboard_activity(self, contact: ContactT) -> None: + def set_keyboard_activity(self, contact) -> None: self._last_keyboard_activity[contact.jid] = time.time()
def remove_delay_timeout(self, contact):
===================================== gajim/common/modules/ping.py ===================================== @@ -25,7 +25,6 @@ from gajim.common import app from gajim.common.nec import NetworkEvent from gajim.common.types import ConnectionT -from gajim.common.types import ContactsT from gajim.common.modules.base import BaseModule from gajim.common.modules.util import as_task
@@ -43,7 +42,7 @@ def __init__(self, con: ConnectionT) -> None: self.handlers = []
@as_task - def send_ping(self, contact: ContactsT) -> Generator: + def send_ping(self, contact) -> Generator: _task = yield
if not app.account_is_available(self._account):
===================================== gajim/common/types.py ===================================== @@ -38,9 +38,11 @@ # pylint: disable=unused-import from gajim.common.client import Client from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf - from gajim.common.contacts import Contact - from gajim.common.contacts import GC_Contact - from gajim.common.contacts import LegacyContactsAPI + from gajim.common.modules.contacts import CommonContact + from gajim.common.modules.contacts import BareContact + from gajim.common.modules.contacts import ResourceContact + from gajim.common.modules.contacts import GroupchatContact + from gajim.common.modules.contacts import GroupchatParticipant from gajim.common.nec import NetworkEvent from gajim.common.nec import NetworkEventsController
@@ -53,8 +55,6 @@ InterfaceT = Union['Interface']
ConnectionT = Union['Client', 'ConnectionZeroconf'] -ContactsT = Union['Contact', 'GC_Contact'] -ContactT = Union['Contact'] CSSConfigT = Union['CSSConfig']
# PEP
===================================== gajim/gtk/avatar.py ===================================== @@ -12,22 +12,28 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import Optional, Union + import logging import hashlib from math import pi from functools import lru_cache from collections import defaultdict +from pathlib import Path
from gi.repository import Gdk from gi.repository import GdkPixbuf import cairo +from nbxmpp.protocol import JID
+from gajim.common import types from gajim.common import app from gajim.common import configpaths from gajim.common.helpers import Singleton from gajim.common.helpers import get_groupchat_name from gajim.common.const import AvatarSize from gajim.common.const import StyleAttr +from gajim.common.modules.contacts import Contacts
from .const import DEFAULT_WORKSPACE_COLOR from .util import load_pixbuf @@ -42,7 +48,18 @@ log = logging.getLogger('gajim.gui.avatar')
-def generate_avatar(letters, color, size, scale): +AvatarCacheT = dict[JID, dict[tuple[int, int, Optional[str]], + cairo.ImageSurface]] + +ContactT = Union[types.BareContact, + types.GroupchatContact, + types.GroupchatParticipant] + +def generate_avatar(letters: str, + color: tuple[float, float, float], + size: int, + scale: int) -> cairo.ImageSurface: + # Get color for nickname with XEP-0392 color_r, color_g, color_b = color
@@ -84,7 +101,12 @@ def generate_avatar(letters, color, size, scale):
@lru_cache(maxsize=None) -def generate_default_avatar(letter, color_string, size, scale, style='circle'): +def generate_default_avatar(letter: str, + color_string: str, + size: int, + scale: int, + style: str = 'circle') -> cairo.ImageSurface: + color = text_to_color(color_string) surface = generate_avatar(letter, color, size, scale) surface = clip(surface, style) @@ -93,14 +115,21 @@ def generate_default_avatar(letter, color_string, size, scale, style='circle'):
@lru_cache(maxsize=None) -def make_workspace_avatar(letter, color, size, scale, style='round-corners'): +def make_workspace_avatar(letter: str, + color: tuple[float, float, float], + size: int, + scale: int, + style: str = 'round-corners') -> cairo.ImageSurface: + surface = generate_avatar(letter, color, size, scale) surface = clip(surface, style) surface.set_device_scale(scale, scale) return surface
-def add_status_to_avatar(surface, show): +def add_status_to_avatar(surface: cairo.ImageSurface, + show) -> cairo.ImageSurface: + width = surface.get_width() height = surface.get_height()
@@ -149,7 +178,10 @@ def add_status_to_avatar(surface, show): return context.get_target()
-def get_icon_avatar(size, scale, icon_name): +def get_icon_avatar(size: int, + scale: int, + icon_name: str) -> cairo.ImageSurface: + if scale is not None: size = size * scale
@@ -171,7 +203,7 @@ def get_icon_avatar(size, scale, icon_name):
@lru_cache(maxsize=128) -def get_show_circle(show, size, scale): +def get_show_circle(show, size: int, scale: int) -> cairo.ImageSurface: if not isinstance(show, str): show = show.value
@@ -203,7 +235,7 @@ def get_show_circle(show, size, scale): return context.get_target()
-def fit(surface: cairo.Surface, size: int) -> cairo.Surface: +def fit(surface: cairo.ImageSurface, size: int) -> cairo.ImageSurface: width = surface.get_width() height = surface.get_height() if width == height: @@ -226,7 +258,7 @@ def fit(surface: cairo.Surface, size: int) -> cairo.Surface: return context.get_target()
-def square(surface, size): +def square(surface: cairo.ImageSurface, size: int) -> cairo.ImageSurface: width = surface.get_width() height = surface.get_height() if width == height: @@ -250,7 +282,7 @@ def square(surface, size): return context.get_target()
-def clip(surface, mode): +def clip(surface: cairo.ImageSurface, mode: str) -> cairo.ImageSurface: if mode == 'circle': return clip_circle(surface) if mode == 'round-corners': @@ -258,7 +290,7 @@ def clip(surface, mode): raise ValueError('clip mode unknown: %s' % mode)
-def clip_circle(surface): +def clip_circle(surface: cairo.ImageSurface) -> cairo.ImageSurface: new_surface = cairo.ImageSurface(cairo.Format.ARGB32, surface.get_width(), surface.get_height()) @@ -280,7 +312,7 @@ def clip_circle(surface): return context.get_target()
-def round_corners(surface): +def round_corners(surface: cairo.ImageSurface) -> cairo.ImageSurface: new_surface = cairo.ImageSurface(cairo.Format.ARGB32, surface.get_width(), surface.get_height()) @@ -308,7 +340,7 @@ def round_corners(surface): return context.get_target()
-def convert_to_greyscale(surface): +def convert_to_greyscale(surface: cairo.ImageSurface) -> cairo.ImageSurface: context = cairo.Context(surface) context.set_operator(cairo.Operator.HSL_COLOR) context.set_source_rgb(1, 1, 1) @@ -323,31 +355,32 @@ def convert_to_greyscale(surface):
class AvatarStorage(metaclass=Singleton): def __init__(self): - self._cache = defaultdict(dict) + self._cache: AvatarCacheT = defaultdict(dict)
- def invalidate_cache(self, jid): + def invalidate_cache(self, jid: JID) -> None: self._cache.pop(jid, None)
def get_pixbuf(self, - contact, - size, - scale, - show=None, - default=False, - transport_icon=None, - style='circle'): + contact: ContactT, + size: int, + scale: int, + show: Optional[str] = None, + default: bool = False, + transport_icon: Optional[str] = None, + style: str = 'circle') -> cairo.ImageSurface: + surface = self.get_surface( contact, size, scale, show, default, transport_icon, style) return Gdk.pixbuf_get_from_surface(surface, 0, 0, size, size)
def get_surface(self, - contact, - size, - scale, - show=None, - default=False, - transport_icon=None, - style='circle'): + contact: ContactT, + size: int, + scale: int, + show: Optional[str] = None, + default: bool = False, + transport_icon: Optional[str] = None, + style: str = 'circle') -> cairo.ImageSurface:
jid = contact.jid
@@ -382,13 +415,13 @@ def get_surface(self, return surface
def get_muc_surface(self, - account, - jid, - size, - scale, - default=False, - transport_icon=None, - style='circle'): + account: str, + jid: JID, + size: int, + scale: int, + default: bool = False, + transport_icon: Optional[str] = None, + style: str = 'circle') -> Optional[cairo.ImageSurface]:
if transport_icon is not None: surface = get_icon_avatar(size, scale, transport_icon) @@ -416,7 +449,11 @@ def get_muc_surface(self, self._cache[jid][(size, scale)] = surface return surface
- def get_workspace_surface(self, workspace_id, size, scale): + def get_workspace_surface(self, + workspace_id: str, + size: int, + scale: int) -> Optional[cairo.ImageSurface]: + surface = self._cache[workspace_id].get((size, scale)) if surface is not None: return surface @@ -438,18 +475,8 @@ def get_workspace_surface(self, workspace_id, size, scale): self._cache[workspace_id][(size, scale)] = surface return surface
- def prepare_for_publish(self, path): - success, data = self._load_for_publish(path) - if not success: - return None, None - - sha = self.save_avatar(data) - if sha is None: - return None, None - return data, sha - @staticmethod - def _load_for_publish(path): + def _load_for_publish(path: str) -> Optional[tuple[bool, bytes]]: pixbuf = load_pixbuf(path) if pixbuf is None: return None @@ -466,7 +493,7 @@ def _load_for_publish(path): return pixbuf.save_to_bufferv('png', [], [])
@staticmethod - def save_avatar(data): + def save_avatar(data: bytes) -> Optional[str]: """ Save an avatar to the harddisk
@@ -488,13 +515,17 @@ def save_avatar(data): return sha
@staticmethod - def get_avatar_path(filename): + def get_avatar_path(filename: str) -> Optional[Path]: path = configpaths.get('AVATAR') / filename if not path.is_file(): return None return path
- def surface_from_filename(self, filename, size, scale): + def surface_from_filename(self, + filename: str, + size: int, + scale: int) -> Optional[cairo.ImageSurface]: + size = size * scale path = self.get_avatar_path(filename) if path is None: @@ -507,7 +538,11 @@ def surface_from_filename(self, filename, size, scale): surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale) return fit(surface, size)
- def _load_surface_from_storage(self, filename, size, scale): + def _load_surface_from_storage(self, + filename: str, + size: int, + scale: int) -> Optional[cairo.ImageSurface]: + size = size * scale path = self.get_avatar_path(filename) if path is None: @@ -519,7 +554,12 @@ def _load_surface_from_storage(self, filename, size, scale): surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale) return fit(surface, size)
- def _get_avatar_from_storage(self, contact, size, scale, style): + def _get_avatar_from_storage(self, + contact: ContactT, + size: int, + scale: int, + style: str) -> Optional[cairo.ImageSurface]: + avatar_sha = contact.avatar_sha if avatar_sha is None: return None @@ -530,7 +570,7 @@ def _get_avatar_from_storage(self, contact, size, scale, style): return clip(surface, style)
@staticmethod - def _generate_letter(name): + def _generate_letter(name: str) -> str: for letter in name: if letter.isalpha(): return letter.capitalize()
===================================== gajim/gtk/status_selector.py ===================================== @@ -12,6 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import Any, Optional + from gi.repository import Gtk from gi.repository import Pango
@@ -28,7 +30,7 @@
class StatusSelector(Gtk.MenuButton): - def __init__(self, account=None, compact=False): + def __init__(self, account: Optional[str] = None, compact: bool = False): Gtk.MenuButton.__init__(self) self.set_direction(Gtk.ArrowType.UP) self._account = account @@ -55,7 +57,7 @@ def __init__(self, account=None, compact=False):
app.ged.register_event_handler('our-show', ged.POSTGUI, self.update)
- def _create_popover(self): + def _create_popover(self) -> None: popover_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) popover_box.get_style_context().add_class('margin-3') popover_items = [ @@ -98,12 +100,12 @@ def _create_popover(self): self._status_popover.add(popover_box) self.set_popover(self._status_popover)
- def _on_change_status(self, button): + def _on_change_status(self, button: Gtk.Button) -> None: self._status_popover.popdown() new_status = button.get_name() app.interface.change_status(status=new_status, account=self._account)
- def update(self, *args, **kwargs): + def update(self, *args: Any, **kwargs: Any) -> None: if self._account is None: show = get_global_show() else:
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/d2d217b6932cbd3d7c1eaa60e800a47f...