diff options
author | Philipp Hörist <philipp@hoerist.com> | 2022-09-14 22:02:02 +0300 |
---|---|---|
committer | Philipp Hörist <philipp@hoerist.com> | 2022-09-17 10:16:54 +0300 |
commit | 13dc0166e157d9d74c74187b0319e79df9e6630d (patch) | |
tree | 850c92451d4a809ef9b53b12313a8972e459c0e4 | |
parent | ad5a9075678d9f63d461dadc597ed8e18b29a5b9 (diff) |
refactor: Merge ScrolledView into ConversationViewrefactor_view
-rw-r--r-- | gajim/gtk/control.py | 67 | ||||
-rw-r--r-- | gajim/gtk/conversation/scrolled.py | 203 | ||||
-rw-r--r-- | gajim/gtk/conversation/view.py | 262 |
3 files changed, 250 insertions, 282 deletions
diff --git a/gajim/gtk/control.py b/gajim/gtk/control.py index ba7d17b5e..ab4adab5d 100644 --- a/gajim/gtk/control.py +++ b/gajim/gtk/control.py @@ -48,8 +48,8 @@ from gajim.common.modules.contacts import GroupchatParticipant from gajim.common.modules.contacts import GroupchatContact from gajim.common.modules.httpupload import HTTPFileTransfer from gajim.common.storage.archive import ConversationRow +from gajim.gtk.conversation.view import ConversationView -from gajim.gui.conversation.scrolled import ScrolledView from gajim.gui.conversation.jump_to_end_button import JumpToEndButton from gajim.gui.builder import get_builder from gajim.gui.groupchat_roster import GroupchatRoster @@ -69,15 +69,13 @@ class ChatControl(EventHelper): self._ui = get_builder('chat_control.ui') - self._scrolled_view = ScrolledView() + self._scrolled_view = ConversationView() self._scrolled_view.connect('autoscroll-changed', self._on_autoscroll_changed) self._scrolled_view.connect('request-history', self._fetch_n_lines_history, 20) self._ui.conv_view_overlay.add(self._scrolled_view) - self.conversation_view = self._scrolled_view.get_view() - self._groupchat_state = GroupchatState() self._ui.conv_view_overlay.add_overlay(self._groupchat_state) @@ -136,7 +134,6 @@ class ChatControl(EventHelper): self._contact = None self._client = None - self.reset_view() self._scrolled_view.clear() self._groupchat_state.clear() self._roster.clear() @@ -199,7 +196,7 @@ class ChatControl(EventHelper): muc_data = self._client.get_module('MUC').get_muc_data( str(contact.jid)) if muc_data is not None and muc_data.subject is not None: - self.conversation_view.add_muc_subject( + self._scrolled_view.add_muc_subject( muc_data.subject, muc_data.last_subject_timestamp) def _register_events(self) -> None: @@ -245,9 +242,9 @@ class ChatControl(EventHelper): contact = self.client.get_module('Contacts').get_contact(event.fjid) if isinstance(contact, BareContact): return - self.conversation_view.add_user_status(self.contact.name, - contact.show.value, - contact.status) + self._scrolled_view.add_user_status(self.contact.name, + contact.show.value, + contact.status) def _on_message_sent(self, event: events.MessageSent) -> None: if not self._is_event_processable(event): @@ -267,7 +264,7 @@ class ChatControl(EventHelper): displaymarking = None if event.correct_id: - self.conversation_view.correct_message( + self._scrolled_view.correct_message( event.correct_id, event.message, self.get_our_nick()) return @@ -363,7 +360,7 @@ class ChatControl(EventHelper): if not self._is_event_processable(event): return - self.conversation_view.correct_message( + self._scrolled_view.correct_message( event.correct_id, event.msgtxt, event.nickname) def _on_message_moderated(self, event: events.MessageModerated) -> None: @@ -374,32 +371,32 @@ class ChatControl(EventHelper): self.contact.account, event.moderation.moderator_jid, event.moderation.reason) - self.conversation_view.show_message_retraction( + self._scrolled_view.show_message_retraction( event.moderation.stanza_id, text) def _on_receipt_received(self, event: events.ReceiptReceived) -> None: if not self._is_event_processable(event): return - self.conversation_view.show_receipt(event.receipt_id) + self._scrolled_view.show_receipt(event.receipt_id) def _on_displayed_received(self, event: events.DisplayedReceived) -> None: if not self._is_event_processable(event): return - self.conversation_view.set_read_marker(event.marker_id) + self._scrolled_view.set_read_marker(event.marker_id) def _on_message_error(self, event: events.MessageError) -> None: if not self._is_event_processable(event): return - self.conversation_view.show_error(event.message_id, event.error) + self._scrolled_view.show_error(event.message_id, event.error) def _on_call_stopped(self, event: events.CallStopped) -> None: if not self._is_event_processable(event): return - self.conversation_view.update_call_rows() + self._scrolled_view.update_call_rows() def _on_jingle_request_received(self, event: events.JingleRequestReceived @@ -439,7 +436,7 @@ class ChatControl(EventHelper): self._jump_to_end_button.reset_unread_count() def _on_autoscroll_changed(self, - _widget: ScrolledView, + _widget: ConversationView, autoscroll: bool ) -> None: @@ -480,17 +477,17 @@ class ChatControl(EventHelper): return self._scrolled_view.get_lower_complete() def add_command_output(self, text: str, is_error: bool) -> None: - self.conversation_view.add_command_output(text, is_error) + self._scrolled_view.add_command_output(text, is_error) def add_info_message(self, text: str, timestamp: Optional[float] = None ) -> None: - self.conversation_view.add_info_message(text, timestamp) + self._scrolled_view.add_info_message(text, timestamp) def add_file_transfer(self, transfer: HTTPFileTransfer) -> None: - self.conversation_view.add_file_transfer(transfer) + self._scrolled_view.add_file_transfer(transfer) def add_jingle_file_transfer(self, event: Union[ @@ -499,11 +496,11 @@ class ChatControl(EventHelper): None] ) -> None: if self._allow_add_message(): - self.conversation_view.add_jingle_file_transfer(event) + self._scrolled_view.add_jingle_file_transfer(event) def add_call_message(self, event: events.JingleRequestReceived) -> None: if self._allow_add_message(): - self.conversation_view.add_call_message(event=event) + self._scrolled_view.add_call_message(event=event) def _add_message(self, text: str, @@ -521,7 +518,7 @@ class ChatControl(EventHelper): additional_data = AdditionalDataDict() if self._allow_add_message(): - self.conversation_view.add_message( + self._scrolled_view.add_message( text, kind, name, @@ -547,7 +544,7 @@ class ChatControl(EventHelper): return self._scrolled_view.get_autoscroll() def scroll_to_message(self, log_line_id: int, timestamp: float) -> None: - row = self.conversation_view.get_row_by_log_line_id(log_line_id) + row = self._scrolled_view.get_row_by_log_line_id(log_line_id) if row is None: # Clear view and reload conversation around timestamp self._scrolled_view.block_signals(True) @@ -558,7 +555,7 @@ class ChatControl(EventHelper): self.add_messages(at_after) GLib.idle_add( - self.conversation_view.scroll_to_message_and_highlight, + self._scrolled_view.scroll_to_message_and_highlight, log_line_id) GLib.idle_add(self._scrolled_view.block_signals, False) @@ -571,9 +568,9 @@ class ChatControl(EventHelper): self._scrolled_view.block_signals(True) if before: - row = self.conversation_view.get_first_message_row() + row = self._scrolled_view.get_first_message_row() else: - row = self.conversation_view.get_last_message_row() + row = self._scrolled_view.get_last_message_row() if row is None: timestamp = time.time() @@ -598,7 +595,7 @@ class ChatControl(EventHelper): self._scrolled_view.set_history_complete(before, True) # if self._scrolled_view.get_autoscroll(): - # if self.conversation_view.reduce_message_count(before): + # if self._scrolled_view.reduce_message_count(before): # self._scrolled_view.set_history_complete(before, False) assert self._contact is not None @@ -645,13 +642,13 @@ class ChatControl(EventHelper): if msg.kind in (KindConstant.FILE_TRANSFER_INCOMING, KindConstant.FILE_TRANSFER_OUTGOING): if msg.additional_data.get_value('gajim', 'type') == 'jingle': - self.conversation_view.add_jingle_file_transfer( + self._scrolled_view.add_jingle_file_transfer( db_message=msg) continue if msg.kind in (KindConstant.CALL_INCOMING, KindConstant.CALL_OUTGOING): - self.conversation_view.add_call_message(db_message=msg) + self._scrolled_view.add_call_message(db_message=msg) continue if not msg.message: @@ -683,7 +680,7 @@ class ChatControl(EventHelper): message_text = get_retraction_text( self.contact.account, retracted_by, reason) - self.conversation_view.add_message( + self._scrolled_view.add_message( message_text, kind, contact_name, @@ -1041,7 +1038,7 @@ class ChatControl(EventHelper): if not event.is_self: if self.contact.is_joined: - self.conversation_view.add_muc_user_joined(event) + self._scrolled_view.add_muc_user_joined(event) return status_codes = event.status_codes or [] @@ -1083,7 +1080,7 @@ class ChatControl(EventHelper): if StatusCode.REMOVED_ERROR in status_codes: # Handle 333 before 307, some MUCs add both - self.conversation_view.add_muc_user_left(event, error=True) + self._scrolled_view.add_muc_user_left(event, error=True) return reason = event.reason @@ -1118,7 +1115,7 @@ class ChatControl(EventHelper): message = message.format(nick=nick, by=actor, reason=reason) else: - self.conversation_view.add_muc_user_left(event) + self._scrolled_view.add_muc_user_left(event) return self.add_info_message(message, event.timestamp) @@ -1158,4 +1155,4 @@ class ChatControl(EventHelper): if (app.settings.get('show_subject_on_join') or not contact.is_joining): - self.conversation_view.add_muc_subject(subject) + self._scrolled_view.add_muc_subject(subject) diff --git a/gajim/gtk/conversation/scrolled.py b/gajim/gtk/conversation/scrolled.py deleted file mode 100644 index 2542a5c7c..000000000 --- a/gajim/gtk/conversation/scrolled.py +++ /dev/null @@ -1,203 +0,0 @@ -# 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 __future__ import annotations - -from typing import Any -from typing import Optional - -from gi.repository import Gtk -from gi.repository import GObject - -from gajim.common.types import ChatContactT - -from .view import ConversationView - - -class ScrolledView(Gtk.ScrolledWindow): - - __gsignals__ = { - 'request-history': ( - GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, - None, - (bool, ) - ), - 'autoscroll-changed': ( - GObject.SignalFlags.RUN_LAST, - None, - (bool,) - ) - } - - def __init__(self) -> None: - Gtk.ScrolledWindow.__init__(self) - - self.set_overlay_scrolling(False) - self.get_style_context().add_class('scrolled-no-border') - self.get_style_context().add_class('no-scroll-indicator') - self.get_style_context().add_class('scrollbar-style') - self.set_shadow_type(Gtk.ShadowType.IN) - self.set_vexpand(True) - - self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) - - # This is a workaround: as soon as a line break occurs in Gtk.TextView - # with word-char wrapping enabled, a hyphen character is automatically - # inserted before the line break. This triggers the hscrollbar to show, - # see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2384 - # Using set_hscroll_policy(Gtk.Scrollable.Policy.NEVER) would cause bad - # performance during resize, and prevent the window from being shrunk - # horizontally under certain conditions (applies to GroupchatControl) - self.get_hscrollbar().hide() - - self._current_upper: float = 0 - self._autoscroll: bool = True - self._request_history_at_upper: Optional[float] = None - self._upper_complete: bool = False - self._lower_complete: bool = False - self._requesting: Optional[str] = None - self._block_signals = False - - vadjustment = self.get_vadjustment() - vadjustment.connect('notify::upper', self._on_adj_upper_changed) - vadjustment.connect('notify::value', self._on_adj_value_changed) - - self._view = ConversationView() - self.add(self._view) - self.set_focus_vadjustment(Gtk.Adjustment()) - - def clear(self) -> None: - self._block_signals = True - self._reset() - self._view.clear() - - def switch_contact(self, contact: ChatContactT) -> None: - self._block_signals = True - self._reset() - self._view.switch_contact(contact) - self._block_signals = False - self._emit('request-history', True) - - def get_autoscroll(self) -> bool: - return self._autoscroll - - def get_view(self) -> ConversationView: - return self._view - - def block_signals(self, value: bool) -> None: - self._block_signals = value - - def _emit(self, signal_name: str, *args: Any) -> None: - if not self._block_signals: - self.emit(signal_name, *args) - - def _reset(self) -> None: - self._current_upper = 0 - self._request_history_at_upper = None - self._upper_complete = False - self._lower_complete = False - self._requesting = None - self.set_history_complete(True, False) - - def reset(self) -> None: - self._reset() - self._view.reset() - - def set_history_complete(self, before: bool, complete: bool) -> None: - if before: - self._upper_complete = complete - self._view.set_history_complete(complete) - else: - self._lower_complete = complete - - def get_lower_complete(self) -> bool: - return self._lower_complete - - def _on_adj_upper_changed(self, - adj: Gtk.Adjustment, - _pspec: GObject.ParamSpec) -> None: - - upper = adj.get_upper() - diff = upper - self._current_upper - - if diff != 0: - self._current_upper = upper - if self._autoscroll: - adj.set_value(adj.get_upper() - adj.get_page_size()) - else: - # Workaround - # https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 - self.set_kinetic_scrolling(True) - if self._requesting == 'before': - adj.set_value(adj.get_value() + diff) - - if upper == adj.get_page_size(): - # There is no scrollbar - if not self._block_signals: - self._emit('request-history', True) - self._lower_complete = True - self._autoscroll = True - self._emit('autoscroll-changed', self._autoscroll) - - self._requesting = None - - def _on_adj_value_changed(self, - adj: Gtk.Adjustment, - _pspec: GObject.ParamSpec) -> None: - - if self._requesting is not None: - return - - bottom = adj.get_upper() - adj.get_page_size() - if (bottom - adj.get_value()) < 1: - self._autoscroll = True - self._emit('autoscroll-changed', self._autoscroll) - else: - self._autoscroll = False - self._emit('autoscroll-changed', self._autoscroll) - - if self._upper_complete: - self._request_history_at_upper = None - if self._lower_complete: - return - - if self._request_history_at_upper == adj.get_upper(): - # Abort here if we already did a history request and the upper - # did not change. This can happen if we scroll very fast and the - # value changes while the request has not been fulfilled. - return - - self._request_history_at_upper = None - - distance = adj.get_page_size() * 2 - if adj.get_value() < distance: - # Load messages when we are near the top - if self._upper_complete: - return - self._request_history_at_upper = adj.get_upper() - # Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 - self.set_kinetic_scrolling(False) - if not self._block_signals: - self._emit('request-history', True) - self._requesting = 'before' - elif (adj.get_upper() - (adj.get_value() + adj.get_page_size()) < - distance): - # ..or near the bottom - if self._lower_complete: - return - # Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 - self.set_kinetic_scrolling(False) - if not self._block_signals: - self._emit('request-history', False) - self._requesting = 'after' diff --git a/gajim/gtk/conversation/view.py b/gajim/gtk/conversation/view.py index 6b23939fa..d8daf6147 100644 --- a/gajim/gtk/conversation/view.py +++ b/gajim/gtk/conversation/view.py @@ -28,6 +28,7 @@ from datetime import timedelta from gi.repository import GLib from gi.repository import Gtk +from gi.repository import GObject from nbxmpp.errors import StanzaError from nbxmpp.modules.security_labels import Displaymarking @@ -64,13 +65,47 @@ from .rows.user_status import UserStatus log = logging.getLogger('gajim.gui.conversation_view') -class ConversationView(Gtk.ListBox): - def __init__(self) -> None: - Gtk.ListBox.__init__(self) - self.set_selection_mode(Gtk.SelectionMode.NONE) - self.set_sort_func(self._sort_func) +class ConversationView(Gtk.ScrolledWindow): - self._contact = None + __gsignals__ = { + 'request-history': ( + GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, + None, + (bool, ) + ), + 'autoscroll-changed': ( + GObject.SignalFlags.RUN_LAST, + None, + (bool,) + ) + } + + def __init__(self) -> None: + Gtk.ScrolledWindow.__init__(self) + + self.set_overlay_scrolling(False) + self.get_style_context().add_class('scrolled-no-border') + self.get_style_context().add_class('no-scroll-indicator') + self.get_style_context().add_class('scrollbar-style') + self.set_shadow_type(Gtk.ShadowType.IN) + self.set_vexpand(True) + + self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + + # This is a workaround: as soon as a line break occurs in Gtk.TextView + # with word-char wrapping enabled, a hyphen character is automatically + # inserted before the line break. This triggers the hscrollbar to show, + # see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2384 + # Using set_hscroll_policy(Gtk.Scrollable.Policy.NEVER) would cause bad + # performance during resize, and prevent the window from being shrunk + # horizontally under certain conditions (applies to GroupchatControl) + self.get_hscrollbar().hide() + + self._list_box = Gtk.ListBox() + self._list_box.set_selection_mode(Gtk.SelectionMode.NONE) + self._list_box.set_sort_func(self._sort_func) + + self._contact: Optional[ChatContactT] = None self._client = None # Keeps track of the number of rows shown in ConversationView @@ -86,24 +121,49 @@ class ConversationView(Gtk.ListBox): self._read_marker_row = None self._scroll_hint_row = None - @property - def contact(self) -> types.ChatContactT: - assert self._contact is not None - return self._contact + self._current_upper: float = 0 + self._autoscroll: bool = True + self._request_history_at_upper: Optional[float] = None + self._upper_complete: bool = False + self._lower_complete: bool = True + self._requesting: Optional[str] = None + self._block_signals = False - def clear(self) -> None: - self._contact = None - self._client = None + self._signal_handlers_enabled = False + + self.add(self._list_box) + self.set_focus_vadjustment(Gtk.Adjustment()) + + def _enable_signal_handlers(self, enable: bool) -> None: + if self._signal_handlers_enabled == enable: + return + vadjustment = self.get_vadjustment() + + if enable: + vadjustment.connect('notify::upper', self._on_adj_upper_changed) + vadjustment.connect('notify::value', self._on_adj_value_changed) + else: + vadjustment.disconnect_by_func(self._on_adj_upper_changed) + vadjustment.disconnect_by_func(self._on_adj_value_changed) + + self._signal_handlers_enabled = enable + + def clear(self) -> None: app.settings.disconnect_signals(self) + self._enable_signal_handlers(False) + self._reset() - self.reset() + self._contact = None + self._client = None def switch_contact(self, contact: ChatContactT) -> None: self._contact = contact self._client = app.get_client(contact.account) - self.reset() + self._enable_signal_handlers(False) + self._block_signals = True + self._reset() app.settings.disconnect_signals(self) @@ -117,11 +177,30 @@ class ConversationView(Gtk.ListBox): account=contact.account, jid=contact.jid) - def get_row_at_index(self, index: int) -> BaseRow: - return cast(BaseRow, Gtk.ListBox.get_row_at_index(self, index)) + self._block_signals = False + self._enable_signal_handlers(True) + self._emit('request-history', True) - def reset(self) -> None: - for row in self.get_children(): + def get_autoscroll(self) -> bool: + return self._autoscroll + + def block_signals(self, value: bool) -> None: + self._block_signals = value + + def _emit(self, signal_name: str, *args: Any) -> None: + if not self._block_signals: + log.debug('emit %s, %s', signal_name, args) + self.emit(signal_name, *args) + + def _reset(self) -> None: + self._current_upper = 0 + self._request_history_at_upper = None + self._upper_complete = False + self._lower_complete = True + self._requesting = None + self.set_history_complete(True, False) + + for row in self._list_box.get_children(): row.destroy() self._row_count = 0 @@ -134,30 +213,125 @@ class ConversationView(Gtk.ListBox): # These need to be present if ConversationView is reset # without switch_contact being invoked self._read_marker_row = ReadMarkerRow(self._contact) - self.add(self._read_marker_row) + self._list_box.add(self._read_marker_row) self._scroll_hint_row = ScrollHintRow(self._contact.account) - self.add(self._scroll_hint_row) + self._list_box.add(self._scroll_hint_row) + + def reset(self) -> None: + assert self._contact is not None + self.switch_contact(self._contact) + + def set_history_complete(self, before: bool, complete: bool) -> None: + if before: + self._upper_complete = complete + if self._scroll_hint_row is None: + return + self._scroll_hint_row.set_history_complete(complete) + else: + self._lower_complete = complete + + def get_lower_complete(self) -> bool: + return self._lower_complete + + def _on_adj_upper_changed(self, + adj: Gtk.Adjustment, + _pspec: GObject.ParamSpec) -> None: + + upper = adj.get_upper() + diff = upper - self._current_upper + + if diff != 0: + self._current_upper = upper + if self._autoscroll: + adj.set_value(adj.get_upper() - adj.get_page_size()) + else: + # Workaround + # https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 + self.set_kinetic_scrolling(True) + if self._requesting == 'before': + adj.set_value(adj.get_value() + diff) + + if upper == adj.get_page_size(): + # There is no scrollbar + if not self._block_signals: + self._emit('request-history', True) + self._lower_complete = True + self._autoscroll = True + self._emit('autoscroll-changed', self._autoscroll) + + self._requesting = None + + def _on_adj_value_changed(self, + adj: Gtk.Adjustment, + _pspec: GObject.ParamSpec) -> None: + + if self._requesting is not None: + return + + bottom = adj.get_upper() - adj.get_page_size() + + self._autoscroll = bottom - adj.get_value() < 1 + self._emit('autoscroll-changed', self._autoscroll) + + if self._upper_complete: + self._request_history_at_upper = None + if self._lower_complete: + return + + if self._request_history_at_upper == adj.get_upper(): + # Abort here if we already did a history request and the upper + # did not change. This can happen if we scroll very fast and the + # value changes while the request has not been fulfilled. + return + + self._request_history_at_upper = None + + distance = adj.get_page_size() * 2 + if adj.get_value() < distance: + # Load messages when we are near the top + if self._upper_complete: + return + self._request_history_at_upper = adj.get_upper() + # Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 + self.set_kinetic_scrolling(False) + if not self._block_signals: + self._emit('request-history', True) + self._requesting = 'before' + + elif (adj.get_upper() - (adj.get_value() + adj.get_page_size()) < + distance): + # ..or near the bottom + if self._lower_complete: + return + # Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 + self.set_kinetic_scrolling(False) + if not self._block_signals: + self._emit('request-history', False) + self._requesting = 'after' + + @property + def contact(self) -> types.ChatContactT: + assert self._contact is not None + return self._contact + + def _get_row_at_index(self, index: int) -> BaseRow: + return cast(BaseRow, self._list_box.get_row_at_index(index)) def get_first_message_row(self) -> Optional[MessageRow]: - for row in self.get_children(): + for row in self._list_box.get_children(): if isinstance(row, MessageRow): return row return None def get_last_message_row(self) -> Optional[MessageRow]: - children = self.get_children() + children = self._list_box.get_children() children.reverse() for row in children: if isinstance(row, MessageRow): return row return None - def set_history_complete(self, complete: bool) -> None: - if self._scroll_hint_row is None: - return - self._scroll_hint_row.set_history_complete(complete) - @staticmethod def _sort_func(row1: BaseRow, row2: BaseRow) -> int: if row1.timestamp == row2.timestamp: @@ -293,7 +467,7 @@ class ConversationView(Gtk.ListBox): self._insert_message(message_row) def _insert_message(self, message: BaseRow) -> None: - self.add(message) + self._list_box.add(message) self._add_date_row(message.timestamp) self._check_for_merge(message) assert self._read_marker_row is not None @@ -311,9 +485,9 @@ class ConversationView(Gtk.ListBox): date_row = DateRow(self.contact.account, start_of_day) self._active_date_rows.add(start_of_day) - self.add(date_row) + self._list_box.add(date_row) - row = self.get_row_at_index(date_row.get_index() + 1) + row = self._get_row_at_index(date_row.get_index() + 1) if row is None: return @@ -340,7 +514,7 @@ class ConversationView(Gtk.ListBox): index = message.get_index() while index != 0: index -= 1 - row = self.get_row_at_index(index) + row = self._get_row_at_index(index) if row is None: return None @@ -361,7 +535,7 @@ class ConversationView(Gtk.ListBox): index = message.get_index() while True: index += 1 - row = self.get_row_at_index(index) + row = self._get_row_at_index(index) if row is None: return @@ -382,7 +556,7 @@ class ConversationView(Gtk.ListBox): def reduce_message_count(self, before: bool) -> bool: success = False - row_count = len(self.get_children()) + row_count = len(self._list_box.get_children()) while row_count > self._max_row_count: if before: if self._reduce_messages_before(): @@ -399,8 +573,8 @@ class ConversationView(Gtk.ListBox): success = False # We want to keep relevant DateRows when removing rows - row1 = self.get_row_at_index(2) - row2 = self.get_row_at_index(3) + row1 = self._get_row_at_index(2) + row2 = self._get_row_at_index(3) if row1.type == 'date' and row2.type == 'date': # First two rows are date rows, @@ -422,12 +596,12 @@ class ConversationView(Gtk.ListBox): return success def _reduce_messages_after(self) -> None: - row = self.get_row_at_index(len(self.get_children()) - 1) + row = self._get_row_at_index(len(self._list_box.get_children()) - 1) row.destroy() def scroll_to_message_and_highlight(self, log_line_id: int) -> None: highlight_row = None - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): row.get_style_context().remove_class( 'conversation-search-highlight') if row.log_line_id == log_line_id: @@ -443,7 +617,7 @@ class ConversationView(Gtk.ListBox): return self._message_id_row_map.get(id_) def get_row_by_log_line_id(self, log_line_id: int) -> Optional[MessageRow]: - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): if not isinstance(row, MessageRow): continue if row.log_line_id == log_line_id: @@ -451,7 +625,7 @@ class ConversationView(Gtk.ListBox): return None def get_row_by_stanza_id(self, stanza_id: str) -> Optional[MessageRow]: - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): if not isinstance(row, MessageRow): continue if row.stanza_id == stanza_id: @@ -459,7 +633,7 @@ class ConversationView(Gtk.ListBox): return None def iter_rows(self) -> Generator[BaseRow, None, None]: - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): yield row def remove_rows_by_type(self, row_type: str) -> None: @@ -468,7 +642,7 @@ class ConversationView(Gtk.ListBox): row.destroy() def update_call_rows(self) -> None: - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): if isinstance(row, CallRow): row.update() @@ -489,7 +663,7 @@ class ConversationView(Gtk.ListBox): self._read_marker_row.set_timestamp(timestamp) def update_avatars(self) -> None: - for row in cast(list[BaseRow], self.get_children()): + for row in cast(list[BaseRow], self._list_box.get_children()): if isinstance(row, MessageRow): row.update_avatar() @@ -538,5 +712,5 @@ class ConversationView(Gtk.ListBox): self.remove_rows_by_type('muc-user-status') def remove(self, widget: Gtk.Widget) -> None: - super().remove(widget) + self._list_box.remove(widget) widget.destroy() |