Philipp Hörist pushed to branch master at gajim / gajim
Commits: b56ee020 by lovetox at 2022-06-23T20:56:51+02:00 refactor: Rename ChatStack
- - - - - d982f6b8 by lovetox at 2022-06-23T21:01:53+02:00 refactor: Change layout of chat page
Add new Chat Stack to aid in the upcoming refactor
- - - - -
4 changed files:
- gajim/gtk/chat_page.py - gajim/gtk/chat_stack.py - + gajim/gtk/control_stack.py - pyrightconfig.json
Changes:
===================================== gajim/gtk/chat_page.py ===================================== @@ -35,6 +35,7 @@ from .chat_list import ChatList from .chat_list_stack import ChatListStack from .chat_stack import ChatStack +from .control_stack import ControlStack from .search_view import SearchView from .types import ControlT
@@ -60,6 +61,8 @@ def __init__(self): self._chat_stack = ChatStack() self._ui.right_grid_overlay.add(self._chat_stack)
+ self._control_stack = self._chat_stack.get_control_stack() + self._search_view = SearchView() self._search_view.connect('hide-search', self._on_search_hide)
@@ -118,8 +121,8 @@ def set_startup_finished(self) -> None: def get_chat_list_stack(self) -> ChatListStack: return self._chat_list_stack
- def get_chat_stack(self) -> ChatStack: - return self._chat_stack + def get_control_stack(self) -> ControlStack: + return self._control_stack
@staticmethod def _on_start_chat_clicked(_button: Gtk.Button) -> None: @@ -148,12 +151,12 @@ def _on_chat_selected(self, account: str, jid: JID) -> None:
- self._chat_stack.show_chat(account, jid) + self._control_stack.show_chat(account, jid) self._search_view.set_context(account, jid) self.emit('chat-selected', workspace_id, account, jid)
def _on_chat_unselected(self, _chat_list_stack: ChatListStack) -> None: - self._chat_stack.clear() + self._control_stack.clear() self._search_view.set_context(None, None)
def _on_search_history(self, @@ -182,7 +185,7 @@ def _on_chat_list_changed(self, self._ui.search_entry.set_text('')
def process_event(self, event: ApplicationEvent): - self._chat_stack.process_event(event) + self._control_stack.process_event(event) self._chat_list_stack.process_event(event)
def add_chat_list(self, workspace_id: str) -> None: @@ -227,15 +230,15 @@ def add_chat_for_workspace(self, return
if type_ == 'groupchat': - self._chat_stack.add_group_chat(account, jid) + self._control_stack.add_group_chat(account, jid) elif type_ == 'pm': if not self._startup_finished: # TODO: Currently we can’t load private chats at start # because the Contacts dont exist yet return - self._chat_stack.add_private_chat(account, jid) + self._control_stack.add_private_chat(account, jid) else: - self._chat_stack.add_chat(account, jid) + self._control_stack.add_chat(account, jid) self._chat_list_stack.add_chat(workspace_id, account, jid, type_, pinned)
@@ -279,7 +282,7 @@ def remove_chat(self, account: str, jid: JID) -> None:
def _on_chat_removed(self, _chat_list: ChatList, account: str, jid: JID, type_: str) -> None: - self._chat_stack.remove_chat(account, jid) + self._control_stack.remove_chat(account, jid) if type_ == 'groupchat': client = app.get_client(account) client.get_module('MUC').leave(jid) @@ -290,10 +293,10 @@ def remove_chats_for_account(self, account: str) -> None: chat_list.unselect_all()
self._chat_list_stack.remove_chats_for_account(account) - self._chat_stack.remove_chats_for_account(account) + self._control_stack.remove_chats_for_account(account)
def get_control(self, account: str, jid: JID) -> Optional[ControlT]: - return self._chat_stack.get_control(account, jid) + return self._control_stack.get_control(account, jid)
def get_active_control(self) -> Optional[ControlT]: chat = self._chat_list_stack.get_selected_chat() @@ -302,11 +305,11 @@ def get_active_control(self) -> Optional[ControlT]: return self.get_control(chat.account, chat.jid)
def is_chat_loaded(self, account: str, jid: JID) -> bool: - return self._chat_stack.is_chat_loaded(account, jid) + return self._control_stack.is_chat_loaded(account, jid)
def get_controls(self, account: Optional[str] ) -> Generator[ControlT, None, None]: - return self._chat_stack.get_controls(account) + return self._control_stack.get_controls(account)
def hide_search(self) -> bool: if self._search_revealer.get_reveal_child():
===================================== gajim/gtk/chat_stack.py ===================================== @@ -12,26 +12,11 @@ # 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 -from typing import Optional -from typing import Generator - import logging
-from gi.repository import GLib from gi.repository import Gtk
-from nbxmpp import JID - -from gajim.common import app -from gajim.common import ged -from gajim.common.i18n import _ - -from .controls.chat import ChatControl -from .controls.groupchat import GroupchatControl -from .controls.private import PrivateChatControl - -from .types import ControlT +from .control_stack import ControlStack from .util import EventHelper
log = logging.getLogger('gajim.gui.chatstack') @@ -45,133 +30,14 @@ def __init__(self): self.set_vexpand(True) self.set_hexpand(True)
- self.add_named(ChatPlaceholderBox(), 'empty') - - self.register_events([ - ('account-enabled', ged.GUI2, self._on_account_changed), - ('account-disabled', ged.GUI2, self._on_account_changed), - ]) - - self.show_all() - self._controls: dict[tuple[str, JID], ControlT] = {} - self._current_control = None - - def get_control(self, account: str, jid: JID) -> Optional[ControlT]: - try: - return self._controls[(account, jid)] - except KeyError: - return None - - def get_controls(self, account: Optional[str] - ) -> Generator[ControlT, None, None]: - if account is None: - for control in self._controls.values(): - yield control - return - - for key, control in self._controls.items(): - if key[0] == account: - yield control - - def add_chat(self, account: str, jid: JID) -> None: - if self._controls.get((account, jid)) is not None: - # Control is already in the Stack - return - - chat_control = ChatControl(account, jid) - self._controls[(account, jid)] = chat_control - self.add_named(chat_control.widget, f'{account}:{jid}') - chat_control.widget.show_all() - - def add_group_chat(self, account: str, jid: JID) -> None: - if self._controls.get((account, jid)) is not None: - return - - control = GroupchatControl(account, jid) - self._controls[(account, jid)] = control - self.add_named(control.widget, f'{account}:{jid}') - control.widget.show_all() - - def add_private_chat(self, account: str, jid: JID) -> None: - control = PrivateChatControl(account, jid) - self._controls[(account, jid)] = control - self.add_named(control.widget, f'{account}:{jid}') - control.widget.show_all() + self._control_stack = ControlStack()
- def remove_chat(self, account: str, jid: JID) -> None: - control = self._controls.pop((account, jid)) - self.remove(control.widget) - control.shutdown() + box = Gtk.Box() + box.add(self._control_stack)
- def show_chat(self, account: str, jid: JID) -> None: - new_name = f'{account}:{jid}' - current_name = self.get_visible_child_name() - assert current_name is not None + self.add_named(box, 'controls')
- if current_name == new_name: - return - - control = self.get_control(account, jid) - if control is None: - log.warning('No Control found for %s, %s', account, jid) - return - - if self._current_control is not None: - self._current_control.set_control_active(False) - self._current_control.reset_view() - - control.set_control_active(True) - self._current_control = control - - self.set_visible_child_name(new_name) - GLib.idle_add(control.focus) - - def is_chat_loaded(self, account: str, jid: JID) -> bool: - control = self.get_control(account, jid) - if control is None: - return False - return control.is_chat_loaded - - def clear(self) -> None: - self.set_visible_child_name('empty') - self._current_control = None - - def process_event(self, event: Any) -> None: - control = self.get_control(event.account, event.jid) - if control is None: - return - control.process_event(event) - - def remove_chats_for_account(self, account: str) -> None: - for chat_account, jid in list(self._controls.keys()): - if chat_account != account: - continue - self.remove_chat(account, jid) - - def _on_account_changed(self, *args: Any) -> None: - for control in self._controls.values(): - control.update_account_badge() - - -class ChatPlaceholderBox(Gtk.Box): - def __init__(self): - Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, - spacing=18) - self.set_valign(Gtk.Align.CENTER) - pixbuf = Gtk.IconTheme.load_icon_for_scale( - Gtk.IconTheme.get_default(), - 'org.gajim.Gajim-symbolic', - 100, - self.get_scale_factor(), - Gtk.IconLookupFlags.FORCE_SIZE) - image = Gtk.Image.new_from_pixbuf(pixbuf) - image.get_style_context().add_class('dim-label') - self.add(image) - - button = Gtk.Button(label=_('Start Chatting…')) - button.set_halign(Gtk.Align.CENTER) - button.connect('clicked', self._on_start_chatting) - self.add(button) + self.show_all()
- def _on_start_chatting(self, _button: Gtk.Button) -> None: - app.app.activate_action('start-chat', GLib.Variant('s', '')) + def get_control_stack(self) -> ControlStack: + return self._control_stack
===================================== gajim/gtk/control_stack.py ===================================== @@ -0,0 +1,177 @@ +# This file is part of Gajim. +# +# Gajim is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; version 3 only. +# +# Gajim is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# 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 +from typing import Optional +from typing import Generator + +import logging + +from gi.repository import GLib +from gi.repository import Gtk + +from nbxmpp import JID + +from gajim.common import app +from gajim.common import ged +from gajim.common.i18n import _ + +from .controls.chat import ChatControl +from .controls.groupchat import GroupchatControl +from .controls.private import PrivateChatControl + +from .types import ControlT +from .util import EventHelper + +log = logging.getLogger('gajim.gui.controlstack') + + +class ControlStack(Gtk.Stack, EventHelper): + def __init__(self): + Gtk.Stack.__init__(self) + EventHelper.__init__(self) + + self.set_vexpand(True) + self.set_hexpand(True) + + self.add_named(ChatPlaceholderBox(), 'empty') + + self.register_events([ + ('account-enabled', ged.GUI2, self._on_account_changed), + ('account-disabled', ged.GUI2, self._on_account_changed), + ]) + + self.show_all() + self._controls: dict[tuple[str, JID], ControlT] = {} + self._current_control = None + + def get_control(self, account: str, jid: JID) -> Optional[ControlT]: + try: + return self._controls[(account, jid)] + except KeyError: + return None + + def get_controls(self, account: Optional[str] + ) -> Generator[ControlT, None, None]: + if account is None: + for control in self._controls.values(): + yield control + return + + for key, control in self._controls.items(): + if key[0] == account: + yield control + + def add_chat(self, account: str, jid: JID) -> None: + if self._controls.get((account, jid)) is not None: + # Control is already in the Stack + return + + chat_control = ChatControl(account, jid) + self._controls[(account, jid)] = chat_control + self.add_named(chat_control.widget, f'{account}:{jid}') + chat_control.widget.show_all() + + def add_group_chat(self, account: str, jid: JID) -> None: + if self._controls.get((account, jid)) is not None: + return + + control = GroupchatControl(account, jid) + self._controls[(account, jid)] = control + self.add_named(control.widget, f'{account}:{jid}') + control.widget.show_all() + + def add_private_chat(self, account: str, jid: JID) -> None: + control = PrivateChatControl(account, jid) + self._controls[(account, jid)] = control + self.add_named(control.widget, f'{account}:{jid}') + control.widget.show_all() + + def remove_chat(self, account: str, jid: JID) -> None: + control = self._controls.pop((account, jid)) + self.remove(control.widget) + control.shutdown() + + def show_chat(self, account: str, jid: JID) -> None: + new_name = f'{account}:{jid}' + current_name = self.get_visible_child_name() + assert current_name is not None + + if current_name == new_name: + return + + control = self.get_control(account, jid) + if control is None: + log.warning('No Control found for %s, %s', account, jid) + return + + if self._current_control is not None: + self._current_control.set_control_active(False) + self._current_control.reset_view() + + control.set_control_active(True) + self._current_control = control + + self.set_visible_child_name(new_name) + GLib.idle_add(control.focus) + + def is_chat_loaded(self, account: str, jid: JID) -> bool: + control = self.get_control(account, jid) + if control is None: + return False + return control.is_chat_loaded + + def clear(self) -> None: + self.set_visible_child_name('empty') + self._current_control = None + + def process_event(self, event: Any) -> None: + control = self.get_control(event.account, event.jid) + if control is None: + return + control.process_event(event) + + def remove_chats_for_account(self, account: str) -> None: + for chat_account, jid in list(self._controls.keys()): + if chat_account != account: + continue + self.remove_chat(account, jid) + + def _on_account_changed(self, *args: Any) -> None: + for control in self._controls.values(): + control.update_account_badge() + + +class ChatPlaceholderBox(Gtk.Box): + def __init__(self): + Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, + spacing=18) + self.set_valign(Gtk.Align.CENTER) + pixbuf = Gtk.IconTheme.load_icon_for_scale( + Gtk.IconTheme.get_default(), + 'org.gajim.Gajim-symbolic', + 100, + self.get_scale_factor(), + Gtk.IconLookupFlags.FORCE_SIZE) + image = Gtk.Image.new_from_pixbuf(pixbuf) + image.get_style_context().add_class('dim-label') + self.add(image) + + button = Gtk.Button(label=_('Start Chatting…')) + button.set_halign(Gtk.Align.CENTER) + button.connect('clicked', self._on_start_chatting) + self.add(button) + + def _on_start_chatting(self, _button: Gtk.Button) -> None: + app.app.activate_action('start-chat', GLib.Variant('s', ''))
===================================== pyrightconfig.json ===================================== @@ -62,6 +62,7 @@ "gajim/gtk/chat_list.py", "gajim/gtk/chat_page.py", "gajim/gtk/chat_stack.py", + "gajim/gtk/control_stack.py", "gajim/gtk/const.py", "gajim/gtk/contact_info.py", "gajim/gtk/contacts_flowbox.py",
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/0ae36837eb957626fa497c8409059dc4...