Philipp Hörist pushed to branch unify-control at gajim / gajim
Commits: 7d4e2c9c by lovetox at 2022-08-08T23:20:36+02:00 other: Observable: Add multi_disconnect()
- - - - - 92188873 by lovetox at 2022-08-08T23:27:10+02:00 other: Observable: Add disconnect_signal()
- - - - - 41d327d2 by lovetox at 2022-08-08T23:28:33+02:00 refactor: ChatControl: Remove handlers for client state-changed
- - - - - e12bd5d4 by lovetox at 2022-08-08T23:29:00+02:00 other: Contacts: Add get_participants()
- - - - - 19e86bdf by lovetox at 2022-08-08T23:29:31+02:00 refactor: GroupchatRoster: Make it work
- - - - -
4 changed files:
- gajim/common/helpers.py - gajim/common/modules/contacts.py - gajim/gtk/control.py - gajim/gtk/groupchat_roster.py
Changes:
===================================== gajim/common/helpers.py ===================================== @@ -1229,19 +1229,46 @@ def __init__(self, log_: Union[logging.Logger, LogAdapter, None] = None): self._log = log_ self._callbacks: types.ObservableCbDict = defaultdict(list)
- def disconnect_signals(self) -> None: - self._callbacks = defaultdict(list) + def __disconnect(self, + obj: Any, + signals: Optional[set[str]] = None + ) -> None: + + def _remove(handlers: list[weakref.WeakMethod[types.AnyCallableT]] + ) -> None:
- def disconnect_all_from_obj(self, obj: Any) -> None: - for handlers in self._callbacks.values(): for handler in list(handlers): func = handler() if func is None or func.__self__ is obj: handlers.remove(handler)
+ if signals is None: + for handlers in self._callbacks.values(): + _remove(handlers) + + else: + for signal in signals: + _remove(self._callbacks.get(signal, [])) + + def disconnect_signals(self) -> None: + self._callbacks = defaultdict(list) + + def multi_disconnect(self, + obj: Any, + signals: Optional[set[str]] + ) -> None: + + self.__disconnect(obj, signals) + + def disconnect_all_from_obj(self, obj: Any) -> None: + self.__disconnect(obj) + def disconnect(self, obj: Any) -> None: self.disconnect_all_from_obj(obj)
+ def disconnect_signal(self, obj: Any, signal: str) -> None: + self.__disconnect(obj, {signal}) + def connect_signal(self, signal_name: str, func: types.AnyCallableT) -> None:
===================================== gajim/common/modules/contacts.py ===================================== @@ -669,6 +669,11 @@ def get_resource(self, resource: str) -> GroupchatParticipant: contact = self.add_resource(resource) return contact
+ def get_participants(self) -> Iterator[GroupchatParticipant]: + for contact in self._resources.values(): + if contact.is_available: + yield contact + @property def name(self) -> str: client = app.get_client(self._account)
===================================== gajim/gtk/control.py ===================================== @@ -119,8 +119,6 @@ def __init__(self) -> None:
self._subject_text_cache: dict[JID, str] = {}
- # self._set_control_inactive() - self.widget = cast(Gtk.Box, self._ui.get_object('control_box')) self.widget.show_all()
@@ -133,6 +131,8 @@ def has_active_chat(self) -> bool: return self.contact is not None
def clear(self) -> None: + log.info('Clear') + if self.contact is not None: self.contact.disconnect_all_from_obj(self)
@@ -149,6 +149,7 @@ def switch_contact(self, contact: Union[BareContact, GroupchatContact, GroupchatParticipant]) -> None:
+ log.info('Switch to %s (%s)', contact.jid, contact.account) if self.contact is not None: self.contact.disconnect_all_from_obj(self)
@@ -179,7 +180,6 @@ def switch_contact(self, contact: Union[BareContact,
elif isinstance(self.contact, GroupchatContact): self.contact.multi_connect({ - 'state-changed': self._on_muc_state_changed, 'user-joined': self._on_user_joined, 'user-left': self._on_user_left, 'user-affiliation-changed': self._on_user_affiliation_changed, @@ -791,17 +791,6 @@ def _on_user_status_show_changed(self, status=status) self.add_info_message(message)
- def _on_muc_state_changed(self, - _contact: GroupchatContact, - _signal_name: str - ) -> None: - - if self.contact.is_joined: - self._set_control_active() - - elif self.contact.is_not_joined: - self._set_control_inactive() - def _on_muc_disco_update(self, event: events.MucDiscoUpdate) -> None: pass
@@ -969,18 +958,6 @@ def _on_room_config_changed(self, for change in changes: self.add_info_message(change)
- def _set_control_active(self) -> None: - assert self.roster is not None - self.roster.initial_draw() - self.conversation_view.update_avatars() - - def _set_control_inactive(self) -> None: - assert self.roster is not None - self.roster.enable_sort(False) - self.roster.reset() - - self._client.get_module('Chatstate').remove_delay_timeout(self.contact) - def rejoin(self) -> None: self._client.get_module('MUC').join(self.contact.jid)
===================================== gajim/gtk/groupchat_roster.py ===================================== @@ -18,6 +18,7 @@ from typing import Optional
import locale +import logging from enum import IntEnum
from gi.repository import Gdk @@ -44,6 +45,9 @@ from .util import EventHelper
+log = logging.getLogger('gajim.gui.groupchat_roster') + + AffiliationRoleSortOrder = { 'owner': 0, 'admin': 1, @@ -61,6 +65,17 @@ class Column(IntEnum): NICK_OR_GROUP = 4
+CONTACT_SIGNALS = { + 'user-affiliation-changed', + 'user-avatar-update', + 'user-joined', + 'user-left', + 'user-nickname-changed', + 'user-role-changed', + 'user-status-show-changed', +} + + class GroupchatRoster(Gtk.ScrolledWindow, EventHelper):
__gsignals__ = { @@ -107,36 +122,33 @@ def __init__(self) -> None: ])
def clear(self) -> None: - if self._contact is not None: - self._contact.disconnect_all_from_obj(self) - + log.info('Clear') + if self._contact is None: + return + self._unload_roster() + self._contact.disconnect_signal(self, 'state-changed') self._contact = None - self.reset()
def switch_contact(self, contact: types.ChatContactT) -> None: - self.clear() + if self._contact is not None: + self.clear()
if not isinstance(contact, GroupchatContact): return
- contact.connect('user-avatar-update', self._on_user_avatar_update) - contact.connect('user-joined', self._on_user_joined) - contact.connect('user-left', self._on_user_left) - contact.connect('user-affiliation-changed', self._update_contact) - contact.connect('user-role-changed', self._update_contact) - contact.connect('user-nickname-changed', self._on_user_nickname_changed) - contact.connect('user-status-show-changed', - self._on_user_status_show_changed) + log.info('Switch to %s (%s)', contact.jid, contact.account) + + contact.connect('state-changed', self._on_muc_state_changed)
self._contact = contact
+ if self._contact.is_joined: + self._load_roster() + @staticmethod def _on_focus_out(treeview: Gtk.TreeView, _param: Gdk.EventFocus) -> None: treeview.get_selection().unselect_all()
- def _set_model(self) -> None: - self._roster.set_model(self._store) - def _query_tooltip(self, widget: Gtk.Widget, x_pos: int, @@ -393,6 +405,17 @@ def destroy(popover: Gtk.Popover) -> None: popover.connect('closed', destroy) popover.popup()
+ def _on_muc_state_changed(self, + contact: GroupchatContact, + _signal_name: str + ) -> None: + + if contact.is_joined: + self._load_roster() + + elif contact.is_not_joined: + self._unload_roster() + def _tree_compare_iters(self, model: Gtk.TreeModel, iter1: Gtk.TreeIter, @@ -436,15 +459,40 @@ def enable_sort(self, enable: bool) -> None:
self._store.set_sort_column_id(column, Gtk.SortType.ASCENDING)
- def invalidate_sort(self) -> None: - self.enable_sort(False) - self.enable_sort(True) + def _load_roster(self) -> None: + log.info('Load Roster') + self._contact.multi_connect({ + 'user-affiliation-changed': self._update_contact, + 'user-avatar-update': self._on_user_avatar_update, + 'user-joined': self._on_user_joined, + 'user-left': self._on_user_left, + 'user-nickname-changed': self._on_user_nickname_changed, + 'user-role-changed': self._update_contact, + 'user-status-show-changed': self._on_user_status_show_changed, + }) + + for participant in self._contact.get_participants(): + self._add_contact(participant)
- def initial_draw(self) -> None: self.enable_sort(True) - self._set_model() + self._roster.set_model(self._store) self._roster.expand_all()
+ def _unload_roster(self) -> None: + log.info('Unload Roster') + self._contact.multi_disconnect(self, CONTACT_SIGNALS) + + self._roster.set_model(None) + self._store.clear() + self.enable_sort(False) + + self._contact_refs = {} + self._group_refs = {} + + def invalidate_sort(self) -> None: + self.enable_sort(False) + self.enable_sort(True) + def _redraw(self) -> None: self._roster.set_model(None) self._roster.set_model(self._store) @@ -530,8 +578,3 @@ def _get_total_user_count(self) -> int:
def _on_theme_update(self, _event: ApplicationEvent) -> None: self._redraw() - - def reset(self) -> None: - self._contact_refs = {} - self._group_refs = {} - self._store.clear()
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/31b3831a3cb84faf8713bbe90ef30ec8...