Philipp Hörist pushed to branch unify-control at gajim / gajim
Commits: 08381f70 by lovetox at 2022-08-09T09:50:32+02:00 fix: Call correct method
- - - - - dced843a by lovetox at 2022-08-09T10:34:27+02:00 refactor: GroupchatRoster
- - - - - 1d04c9bd by lovetox at 2022-08-09T10:35:35+02:00 fix: Banner: Fix roster toggle icon
- - - - -
6 changed files:
- gajim/data/gui/groupchat_roster.ui - gajim/gtk/builder.pyi - gajim/gtk/chat_banner.py - gajim/gtk/chat_page.py - gajim/gtk/control.py - gajim/gtk/groupchat_roster.py
Changes:
===================================== gajim/data/gui/groupchat_roster.ui ===================================== @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.1 --> +<!-- Generated with glade 3.38.2 --> <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkTreeStore" id="participant_store"> @@ -8,76 +8,67 @@ <column type="CairoGObjectSurface"/> <!-- column-name Text --> <column type="gchararray"/> - <!-- column-name Event --> - <column type="gboolean"/> <!-- column-name IsContact --> <column type="gboolean"/> <!-- column-name GroupOrNickname --> <column type="gchararray"/> </columns> </object> - <object class="GtkTreeView" id="roster_treeview"> + <object class="GtkScrolledWindow" id="scrolled"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="model">participant_store</property> - <property name="headers_visible">False</property> - <property name="expander_column">expander</property> - <property name="search_column">1</property> - <signal name="button-press-event" handler="_on_roster_button_press_event" swapped="no"/> - <signal name="focus-out-event" handler="_on_focus_out" swapped="no"/> - <signal name="row-activated" handler="_on_roster_row_activated" swapped="no"/> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> - </child> + <property name="can-focus">True</property> + <property name="hscrollbar-policy">never</property> + <property name="shadow-type">in</property> <child> - <object class="GtkTreeViewColumn" id="contact_column"> - <property name="sizing">fixed</property> - <property name="fixed_width">210</property> - <property name="title">avatar</property> - <property name="expand">True</property> + <object class="GtkTreeView" id="roster_treeview"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="model">participant_store</property> + <property name="headers-visible">False</property> + <property name="expander-column">expander</property> + <property name="search-column">1</property> + <signal name="button-press-event" handler="_on_roster_button_press_event" swapped="no"/> + <signal name="focus-out-event" handler="_on_focus_out" swapped="no"/> + <signal name="query-tooltip" handler="_query_tooltip" swapped="no"/> + <signal name="row-activated" handler="_on_roster_row_activated" swapped="no"/> <child> - <object class="GtkCellRendererPixbuf" id="avatar_renderer"> - <property name="width">40</property> - <property name="ypad">3</property> - <property name="xalign">0</property> + <object class="GtkTreeViewColumn" id="contact_column"> + <property name="sizing">fixed</property> + <property name="fixed-width">210</property> + <property name="title">avatar</property> + <property name="expand">True</property> + <child> + <object class="GtkCellRendererPixbuf" id="avatar_renderer"> + <property name="width">40</property> + <property name="ypad">3</property> + <property name="xalign">0</property> + </object> + <attributes> + <attribute name="visible">2</attribute> + <attribute name="surface">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="text_renderer"> + <property name="ellipsize">end</property> + </object> + <attributes> + <attribute name="markup">1</attribute> + </attributes> + </child> </object> - <attributes> - <attribute name="visible">3</attribute> - <attribute name="surface">0</attribute> - </attributes> </child> <child> - <object class="GtkCellRendererText" id="text_renderer"> - <property name="ellipsize">end</property> + <object class="GtkTreeViewColumn" id="expander"> + <property name="visible">False</property> + <property name="sizing">fixed</property> + <property name="title">expander</property> </object> - <attributes> - <attribute name="markup">1</attribute> - </attributes> </child> </object> </child> - <child> - <object class="GtkTreeViewColumn" id="event_column"> - <property name="sizing">fixed</property> - <property name="fixed_width">35</property> - <property name="title">event</property> - <child> - <object class="GtkCellRendererPixbuf" id="icon"> - <property name="xalign">0</property> - <property name="icon_name">gajim-event</property> - </object> - <attributes> - <attribute name="visible">2</attribute> - </attributes> - </child> - </object> - </child> - <child> - <object class="GtkTreeViewColumn" id="expander"> - <property name="visible">False</property> - <property name="sizing">fixed</property> - <property name="title">expander</property> - </object> - </child> + <style> + <class name="groupchat-roster"/> + </style> </object> </interface>
===================================== gajim/gtk/builder.pyi ===================================== @@ -210,11 +210,8 @@ class ChatBannerBuilder(Builder):
class ChatControlBuilder(Builder): control_box: Gtk.Box - overlay: Gtk.Overlay conv_view_box: Gtk.Box conv_view_overlay: Gtk.Overlay - roster_revealer: Gtk.Revealer - drop_area: Gtk.Box
class ChatListRowBuilder(Builder): @@ -493,12 +490,11 @@ class GroupchatOutcastBuilder(Builder):
class GroupchatRosterBuilder(Builder): participant_store: Gtk.TreeStore + scrolled: Gtk.ScrolledWindow roster_treeview: Gtk.TreeView contact_column: Gtk.TreeViewColumn avatar_renderer: Gtk.CellRendererPixbuf text_renderer: Gtk.CellRendererText - event_column: Gtk.TreeViewColumn - icon: Gtk.CellRendererPixbuf expander: Gtk.TreeViewColumn
===================================== gajim/gtk/chat_banner.py ===================================== @@ -312,8 +312,9 @@ def _on_toggle_roster_clicked(self, _button: Gtk.Button) -> None: app.settings.set('hide_groupchat_occupants_list', not state)
def _set_toggle_roster_button_icon(self, - show_roster: bool, + hide_roster: bool, *args: Any) -> None: - icon = 'go-next-symbolic' if show_roster else 'go-previous-symbolic' + + icon = 'go-next-symbolic' if not hide_roster else 'go-previous-symbolic' self._ui.toggle_roster_image.set_from_icon_name( icon, Gtk.IconSize.BUTTON)
===================================== gajim/gtk/chat_page.py ===================================== @@ -232,7 +232,7 @@ def add_chat_for_workspace(self, client.get_module('Contacts').add_group_chat_contact(jid)
elif type_ == 'pm': - client.get_module('Contacts').add_group_private_contact(jid) + client.get_module('Contacts').add_private_contact(jid)
if self.chat_exists(account, jid): if select:
===================================== gajim/gtk/control.py ===================================== @@ -98,16 +98,8 @@ def __init__(self) -> None: self.fetch_n_lines_history, 20)
self.roster = GroupchatRoster() - self.roster.connect('row-activated', self._on_roster_row_activated)
- self._show_roster_setting = app.settings.get( - 'hide_groupchat_occupants_list') - app.settings.connect_signal( - 'hide_groupchat_occupants_list', self._show_roster) - - self._roster_revealer = Gtk.Revealer() - self._roster_revealer.add(self.roster) - self._ui.conv_view_box.add(self._roster_revealer) + self._ui.conv_view_box.add(self.roster)
# Keeps track of whether the ConversationView is populated self._chat_loaded: bool = False @@ -163,10 +155,6 @@ def switch_contact(self, contact: Union[BareContact, self._groupchat_state.switch_contact(contact) self.roster.switch_contact(contact)
- show_roster = (isinstance(contact, GroupchatContact) and - self._show_roster_setting) - self._roster_revealer.set_reveal_child(show_roster) - self.encryption = self.get_encryption_state() self.conversation_view.encryption_enabled = self.encryption is not None
@@ -803,34 +791,6 @@ def invite(self, invited_jid: JID) -> None: self.add_info_message( _('%s has been invited to this group chat') % invited_contact.name)
- def _show_roster(self, show_roster: bool, *args: Any) -> None: - self._show_roster_setting = show_roster - transition = Gtk.RevealerTransitionType.SLIDE_RIGHT - if show_roster: - self._roster_revealer.set_no_show_all(False) - self._roster_revealer.show_all() - transition = Gtk.RevealerTransitionType.SLIDE_LEFT - self._roster_revealer.set_transition_type(transition) - self._roster_revealer.set_reveal_child(show_roster) - - def _on_roster_row_activated(self, - _roster: GroupchatRoster, - nick: str - ) -> None: - - disco = self.contact.get_disco() - muc_prefer_direct_msg = app.settings.get('muc_prefer_direct_msg') - if disco.muc_is_nonanonymous and muc_prefer_direct_msg: - participant = self.contact.get_resource(nick) - app.window.add_chat(self.account, - participant.real_jid, - 'contact', - select=True, - workspace='current') - else: - contact = self.contact.get_resource(nick) - app.window.add_private_chat(self.account, contact.jid, select=True) - def _on_room_voice_request(self, _contact: GroupchatContact, _signal_name: str,
===================================== gajim/gtk/groupchat_roster.py ===================================== @@ -24,7 +24,6 @@ from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib -from gi.repository import GObject from nbxmpp.const import Affiliation from nbxmpp.structs import MessageProperties
@@ -60,9 +59,8 @@ class Column(IntEnum): AVATAR = 0 TEXT = 1 - EVENT = 2 - IS_CONTACT = 3 - NICK_OR_GROUP = 4 + IS_CONTACT = 2 + NICK_OR_GROUP = 3
CONTACT_SIGNALS = { @@ -76,28 +74,17 @@ class Column(IntEnum): }
-class GroupchatRoster(Gtk.ScrolledWindow, EventHelper): - - __gsignals__ = { - 'row-activated': ( - GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, - None, - (str, )) - } - +class GroupchatRoster(Gtk.Revealer, EventHelper): def __init__(self) -> None: - Gtk.ScrolledWindow.__init__(self) + Gtk.Revealer.__init__(self) EventHelper.__init__(self) - self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) - self.get_style_context().add_class('groupchat-roster')
self._contact = None
self._tooltip = GCTooltip()
self._ui = get_builder('groupchat_roster.ui') - self._ui.roster_treeview.set_model(None) - self.add(self._ui.roster_treeview) + self.add(self._ui.scrolled)
self._contact_refs: dict[str, Gtk.TreeRowReference] = {} self._group_refs: dict[str, Gtk.TreeRowReference] = {} @@ -108,7 +95,6 @@ def __init__(self) -> None: self._roster = self._ui.roster_treeview self._roster.set_search_equal_func(self._search_func) self._roster.set_has_tooltip(True) - self._roster.connect('query-tooltip', self._query_tooltip)
self._ui.contact_column.set_fixed_width( app.settings.get('groupchat_roster_width')) @@ -117,10 +103,26 @@ def __init__(self) -> None:
self._ui.connect_signals(self)
+ app.settings.connect_signal( + 'hide_groupchat_occupants_list', self._hide_roster) + self.register_events([ ('theme-update', ged.GUI2, self._on_theme_update), ])
+ self.set_no_show_all(True) + self.set_reveal_child( + not app.settings.get('hide_groupchat_occupants_list')) + + def _hide_roster(self, hide_roster: bool, *args: Any) -> None: + transition = Gtk.RevealerTransitionType.SLIDE_RIGHT + if not hide_roster: + self.show_all() + transition = Gtk.RevealerTransitionType.SLIDE_LEFT + + self.set_transition_type(transition) + self.set_reveal_child(not hide_roster) + def clear(self) -> None: log.info('Clear') if self._contact is None: @@ -133,7 +135,9 @@ def switch_contact(self, contact: types.ChatContactT) -> None: if self._contact is not None: self.clear()
- if not isinstance(contact, GroupchatContact): + is_groupchat = isinstance(contact, GroupchatContact) + self.set_visible(is_groupchat) + if not is_groupchat: return
log.info('Switch to %s (%s)', contact.jid, contact.account) @@ -192,6 +196,7 @@ def _search_func(model: Gtk.TreeModel, search_text: str, iter_: Gtk.TreeIter ) -> bool: + return search_text.lower() not in model[iter_][1].lower()
def _get_group_iter(self, group_name: str) -> Optional[Gtk.TreeIter]: @@ -233,7 +238,7 @@ def _add_contact(self, contact: types.GroupchatParticipant) -> None: role_path = None if not group_iter: group_iter = self._store.append( - None, [None, group_text, None, False, group_name]) + None, [None, group_text, False, group_name]) role_path = self._store.get_path(group_iter) group_ref = Gtk.TreeRowReference(self._store, role_path) self._group_refs[group_name] = group_ref @@ -243,7 +248,7 @@ def _add_contact(self, contact: types.GroupchatParticipant) -> None: self.get_scale_factor())
iter_ = self._store.append(group_iter, - [surface, nick, None, True, nick]) + [surface, nick, True, nick]) self._contact_refs[nick] = Gtk.TreeRowReference( self._store, self._store.get_path(iter_))
@@ -260,6 +265,7 @@ def _on_user_left(self, user_contact: types.GroupchatParticipant, *args: Any ) -> None: + self._remove_contact(user_contact) self._draw_groups()
@@ -269,6 +275,7 @@ def _update_contact(self, user_contact: types.GroupchatParticipant, *args: Any ) -> None: + self._remove_contact(user_contact) self._add_contact(user_contact)
@@ -278,6 +285,7 @@ def _on_user_nickname_changed(self, user_contact: types.GroupchatParticipant, properties: MessageProperties ) -> None: + self._remove_contact(user_contact)
user_contact = contact.get_resource(properties.muc_user.nick) @@ -289,6 +297,7 @@ def _on_user_status_show_changed(self, user_contact: types.GroupchatParticipant, *args: Any ) -> None: + self._draw_contact(user_contact.name)
def _remove_contact(self, contact: types.GroupchatParticipant) -> None: @@ -323,6 +332,7 @@ def _text_cell_data_func(_column: Gtk.TreeViewColumn, iter_: Gtk.TreeIter, _user_data: Optional[object] ) -> None: + has_parent = bool(model.iter_parent(iter_)) style = 'contact' if has_parent else 'group'
@@ -346,6 +356,7 @@ def _on_roster_row_activated(self, path: Gtk.TreePath, _column: Gtk.TreeViewColumn ) -> None: + iter_ = self._store.get_iter(path) if self._store.iter_parent(iter_) is None: # This is a group row @@ -353,12 +364,28 @@ def _on_roster_row_activated(self, nick = self._store[iter_][Column.NICK_OR_GROUP] if self._contact.nickname == nick: return - self.emit('row-activated', nick) + + disco = self._contact.get_disco() + assert disco is not None + muc_prefer_direct_msg = app.settings.get('muc_prefer_direct_msg') + if disco.muc_is_nonanonymous and muc_prefer_direct_msg: + participant = self._contact.get_resource(nick) + app.window.add_chat(self._contact.account, + participant.real_jid, + 'contact', + select=True, + workspace='current') + else: + contact = self._contact.get_resource(nick) + app.window.add_private_chat(self._contact.account, + contact.jid, + select=True)
def _on_roster_button_press_event(self, treeview: Gtk.TreeView, event: Gdk.EventButton ) -> None: + if event.button not in (2, 3): return
@@ -385,8 +412,8 @@ def _on_roster_button_press_event(self, rec.height, rec.width = 1, 1 self._show_contact_menu(nick, rec)
- if event.button == 2: # middle click - self.emit('row-activated', nick) + # if event.button == 2: # middle click + # self.roster.emit('row-activated', nick)
def _show_contact_menu(self, nick: str, rect: Gdk.Rectangle) -> None: self_contact = self._contact.get_self() @@ -427,9 +454,6 @@ def _tree_compare_iters(self, ''' is_contact = model.iter_parent(iter1) if is_contact: - # Sort contacts with pending events to top - if model[iter1][Column.EVENT] != model[iter2][Column.EVENT]: - return -1 if model[iter1][Column.EVENT] else 1
nick1 = model[iter1][Column.NICK_OR_GROUP] nick2 = model[iter2][Column.NICK_OR_GROUP] @@ -507,8 +531,6 @@ def _draw_contact(self, nick: str) -> None:
self._draw_avatar(contact)
- self._store[iter_][Column.EVENT] = False - name = GLib.markup_escape_text(contact.name)
# Strike name if blocked @@ -562,12 +584,15 @@ def _draw_avatar(self, contact: types.GroupchatParticipant) -> None:
surface = contact.get_avatar(AvatarSize.ROSTER, self.get_scale_factor()) + self._store[iter_][Column.AVATAR] = surface
def _on_user_avatar_update(self, _contact: types.GroupchatContact, _signal_name: str, - user_contact: types.GroupchatParticipant): + user_contact: types.GroupchatParticipant + ) -> None: + self._draw_avatar(user_contact)
def _get_total_user_count(self) -> int:
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/19e86bdfdc6bd09e4947834a70d42722...