Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits: 146a12fd by wurstsalat at 2021-09-10T17:40:06+02:00 XMLConsole: Add Disco Info preset
- - - - - 6ec7078f by wurstsalat at 2021-09-10T18:05:59+02:00 Discovery: Fix disco_contact
- - - - - 1665a2dd by wurstsalat at 2021-09-10T18:36:24+02:00 Transports: Improve detection and avatars
- - - - -
10 changed files:
- gajim/common/modules/contacts.py - gajim/common/modules/discovery.py - gajim/data/gui/xml_console.ui - gajim/gtk/avatar.py - gajim/gtk/chat_list.py - gajim/gtk/contact_info.py - gajim/gtk/groupchat_info.py - gajim/gtk/roster.py - gajim/gtk/tooltips.py - gajim/gtk/xml_console.py
Changes:
===================================== gajim/common/modules/contacts.py ===================================== @@ -248,11 +248,37 @@ def get_avatar(self,
show = self.show if add_show else None
+ transport_icon = None + if self.is_gateway: + show = None + disco_info = app.storage.cache.get_last_disco_info(self._jid) + if disco_info.gateway_type == 'sms': + transport_icon = 'gajim-agent-sms' + if disco_info.gateway_type == 'irc': + transport_icon = 'gajim-agent-irc' + else: + for resource_contact in self.iter_resources(): + if resource_contact.identity_type == 'sms': + transport_icon = 'gajim-agent-sms' + break + if pixbuf: return app.interface.avatar_storage.get_pixbuf( - self, size, scale, show, default=default, style=style) + self, + size, + scale, + show, + default=default, + transport_icon=transport_icon, + style=style) return app.interface.avatar_storage.get_surface( - self, size, scale, show, default=default, style=style) + self, + size, + scale, + show, + default=default, + transport_icon=transport_icon, + style=style)
def update_presence(self, presence_data): for contact in self._resources.values(): @@ -281,14 +307,11 @@ def is_in_roster(self): return item is not None
@property - def is_transport(self): + def is_gateway(self): disco_info = app.storage.cache.get_last_disco_info(self._jid) if disco_info is None: return False - for identity in disco_info.identities: - if identity.category == 'gateway': - return True - return False + return disco_info.is_gateway
@property def ask(self): @@ -329,6 +352,18 @@ def supports(self, requested_feature): return False return CommonContact.supports(self, requested_feature)
+ @property + def identity_type(self): + disco_info = app.storage.cache.get_last_disco_info(self._jid) + if disco_info is None: + return None + + for identity in disco_info.identities: + if identity.type is not None: + return identity.type + + return None + @property def is_available(self): return self._presence.available @@ -399,11 +434,19 @@ def avatar_sha(self): return app.storage.cache.get_muc(self._jid, 'avatar')
def get_avatar(self, size, scale): + transport_icon = None + disco_info = self.get_disco() + if disco_info is not None: + for identity in disco_info.identities: + if identity.type == 'irc': + transport_icon = 'gajim-agent-irc' + break return app.interface.avatar_storage.get_muc_surface( self._account, self._jid, size, - scale) + scale, + transport_icon=transport_icon)
def _on_user_signal(self, contact, signal_name, *args): self.notify(signal_name, contact, *args)
===================================== gajim/common/modules/discovery.py ===================================== @@ -241,19 +241,16 @@ def disco_muc(self, def disco_contact(self, contact): _task = yield
- fjid = contact.get_full_jid() - - result = yield self.disco_info(fjid) + result = yield self.disco_info(contact.jid) if is_error(result): raise result
- self._log.info('Disco Info received: %s', fjid) + self._log.info('Disco Info received: %s', contact.jid)
app.storage.cache.set_last_disco_info(result.jid, result, cache_only=True)
- contact = self._con.get_module('Contacts').get_contact(result.jid) contact.notify('caps-update')
===================================== gajim/data/gui/xml_console.ui ===================================== @@ -1,31 +1,31 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.36.0 --> +<!-- Generated with glade 3.38.2 --> <interface> <requires lib="gtk+" version="3.22"/> <object class="GtkHeaderBar" id="headerbar"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="title" translatable="yes">XML Console</property> - <property name="show_close_button">True</property> + <property name="show-close-button">True</property> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">utilities-terminal-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">utilities-terminal-symbolic</property> </object> </child> <child> <object class="GtkToggleButton" id="search_toggle"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="margin_start">6</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="margin-start">6</property> <signal name="toggled" handler="_on_search_toggled" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">system-search-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">system-search-symbolic</property> </object> </child> </object> @@ -35,22 +35,22 @@ </child> </object> <object class="GtkPopover" id="popover"> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="valign">start</property> <child> <object class="GtkListBox"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="selection_mode">none</property> + <property name="can-focus">False</property> + <property name="selection-mode">none</property> <signal name="row-activated" handler="_on_row_activated" swapped="no"/> <child> <object class="GtkListBoxRow"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label">Message</property> </object> </child> @@ -59,11 +59,11 @@ <child> <object class="GtkListBoxRow"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label">Presence</property> </object> </child> @@ -72,16 +72,29 @@ <child> <object class="GtkListBoxRow"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label">Iq</property> </object> </child> </object> </child> + <child> + <object class="GtkListBoxRow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label">Disco Info</property> + </object> + </child> + </object> + </child> </object> </child> <style> @@ -90,45 +103,45 @@ </object> <object class="GtkBox" id="box"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkPaned" id="paned"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> <property name="vexpand">True</property> <property name="orientation">vertical</property> <child> <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkRevealer" id="search_revealer"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="transition_type">none</property> - <property name="transition_duration">100</property> + <property name="can-focus">False</property> + <property name="transition-type">none</property> + <property name="transition-duration">100</property> <child> <object class="GtkToolbar"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="show_arrow">False</property> + <property name="show-arrow">False</property> <property name="icon_size">2</property> <child> <object class="GtkToolItem"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_end">6</property> + <property name="can-focus">False</property> + <property name="margin-end">6</property> <child> <object class="GtkSearchEntry" id="search_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="primary_icon_name">edit-find-symbolic</property> - <property name="primary_icon_activatable">False</property> - <property name="primary_icon_sensitive">False</property> - <property name="placeholder_text" translatable="yes">Start Search...</property> + <property name="can-focus">True</property> + <property name="primary-icon-name">edit-find-symbolic</property> + <property name="primary-icon-activatable">False</property> + <property name="primary-icon-sensitive">False</property> + <property name="placeholder-text" translatable="yes">Start Search...</property> <signal name="activate" handler="_on_search_activate" swapped="no"/> </object> </child> @@ -141,9 +154,9 @@ <child> <object class="GtkToolButton" id="search_forward"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="icon_name">go-down-symbolic</property> + <property name="can-focus">False</property> + <property name="use-underline">True</property> + <property name="icon-name">go-down-symbolic</property> <signal name="clicked" handler="_on_search_clicked" swapped="no"/> </object> <packing> @@ -154,9 +167,9 @@ <child> <object class="GtkToolButton" id="search_backward"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="icon_name">go-up-symbolic</property> + <property name="can-focus">False</property> + <property name="use-underline">True</property> + <property name="icon-name">go-up-symbolic</property> <signal name="clicked" handler="_on_search_clicked" swapped="no"/> </object> <packing> @@ -175,19 +188,19 @@ </child> <child> <object class="GtkScrolledWindow" id="scrolled"> - <property name="height_request">400</property> + <property name="height-request">400</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> <child> <object class="GtkTextView" id="textview"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> <property name="editable">False</property> - <property name="left_margin">6</property> - <property name="right_margin">6</property> - <property name="top_margin">6</property> - <property name="bottom_margin">6</property> + <property name="left-margin">6</property> + <property name="right-margin">6</property> + <property name="top-margin">6</property> + <property name="bottom-margin">6</property> </object> </child> </object> @@ -205,14 +218,14 @@ </child> <child> <object class="GtkScrolledWindow" id="scrolled_input"> - <property name="height_request">150</property> - <property name="can_focus">True</property> - <property name="no_show_all">True</property> - <property name="shadow_type">in</property> + <property name="height-request">150</property> + <property name="can-focus">True</property> + <property name="no-show-all">True</property> + <property name="shadow-type">in</property> <child> <object class="GtkTextView" id="input_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> </object> </child> </object> @@ -232,19 +245,19 @@ <object class="GtkActionBar" id="actionbar"> <property name="name">actionbar</property> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <child> <object class="GtkButton"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Filter</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes">Filter</property> <signal name="clicked" handler="_on_filter_options" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">applications-system-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">applications-system-symbolic</property> </object> </child> </object> @@ -255,15 +268,15 @@ <child> <object class="GtkButton"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Clear</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes">Clear</property> <signal name="clicked" handler="_on_clear" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">edit-clear-all-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">edit-clear-all-symbolic</property> </object> </child> </object> @@ -274,14 +287,14 @@ <child> <object class="GtkToggleButton"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> <signal name="toggled" handler="_on_input" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">document-edit-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">document-edit-symbolic</property> </object> </child> </object> @@ -291,16 +304,16 @@ </child> <child> <object class="GtkButton" id="paste"> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="no_show_all">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="no-show-all">True</property> <signal name="clicked" handler="_on_paste_last" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Paste Last Input</property> - <property name="icon_name">insert-text-symbolic</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes">Paste Last Input</property> + <property name="icon-name">insert-text-symbolic</property> </object> </child> </object> @@ -310,10 +323,10 @@ </child> <child> <object class="GtkMenuButton" id="menubutton"> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="no_show_all">True</property> - <property name="tooltip_text" translatable="yes">Presets</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="no-show-all">True</property> + <property name="tooltip-text" translatable="yes">Presets</property> <property name="popover">popover</property> <child> <placeholder/> @@ -332,14 +345,14 @@ <child> <object class="GtkButton" id="send"> <property name="label" translatable="yes">_Send</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="no_show_all">True</property> - <property name="use_underline">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="no-show-all">True</property> + <property name="use-underline">True</property> <signal name="clicked" handler="_on_send" swapped="no"/> </object> <packing> - <property name="pack_type">end</property> + <property name="pack-type">end</property> <property name="position">0</property> </packing> </child> @@ -347,7 +360,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="pack_type">end</property> + <property name="pack-type">end</property> <property name="position">1</property> </packing> </child>
===================================== gajim/gtk/avatar.py ===================================== @@ -31,6 +31,7 @@
from .const import DEFAULT_WORKSPACE_COLOR from .util import load_pixbuf +from .util import load_icon from .util import text_to_color from .util import scale_with_ratio from .util import get_css_show_class @@ -148,6 +149,27 @@ def add_status_to_avatar(surface, show): return context.get_target()
+def get_icon_avatar(size, scale, icon_name): + if scale is not None: + size = size * scale + + width = size + height = size + + surface = cairo.ImageSurface(cairo.Format.ARGB32, width, height) + context = cairo.Context(surface) + + pixbuf = load_icon(icon_name, scale=scale, size=size, pixbuf=True) + Gdk.cairo_set_source_pixbuf( + context, + pixbuf, + 0, + 0) + context.paint() + + return context.get_target() + + @lru_cache(maxsize=128) def get_show_circle(show, size, scale): if not isinstance(show, str): @@ -276,8 +298,10 @@ def get_pixbuf(self, scale, show=None, default=False, + transport_icon=None, style='circle'): - surface = self.get_surface(contact, size, scale, show, default, style) + 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, @@ -286,9 +310,18 @@ def get_surface(self, scale, show=None, default=False, + transport_icon=None, style='circle'):
jid = contact.jid + + if transport_icon is not None: + surface = get_icon_avatar(size, scale, transport_icon) + if show is not None: + surface = add_status_to_avatar(surface, show) + self._cache[jid][(size, scale, show)] = surface + return surface + if not default: surface = self._cache[jid].get((size, scale, show)) if surface is not None: @@ -318,7 +351,14 @@ def get_muc_surface(self, size, scale, default=False, + transport_icon=None, style='circle'): + + if transport_icon is not None: + surface = get_icon_avatar(size, scale, transport_icon) + self._cache[jid][(size, scale)] = surface + return surface + if not default: surface = self._cache[jid].get((size, scale)) if surface is not None:
===================================== gajim/gtk/chat_list.py ===================================== @@ -372,6 +372,7 @@ def __init__(self, workspace_id, account, jid, type_, pinned): self.contact.connect('presence-update', self._on_presence_update) self.contact.connect('chatstate-update', self._on_chatstate_update) self.contact.connect('nickname-update', self._on_nickname_update) + self.contact.connect('caps-update', self._on_avatar_update) self.contact.connect('avatar-update', self._on_avatar_update)
self._timestamp = None
===================================== gajim/gtk/contact_info.py ===================================== @@ -79,7 +79,7 @@ def __init__(self, account, contact, page=None): if contact.is_in_roster: self._ui.edit_name_button.show() self._fill_groups_page() - if contact.is_transport: + if contact.is_gateway: side_bar_switcher.hide_row('settings') side_bar_switcher.hide_row('devices') else:
===================================== gajim/gtk/groupchat_info.py ===================================== @@ -161,9 +161,10 @@ def set_from_disco_info(self, info): self._ui.name.set_visible(True)
# Set avatar - surface = app.interface.avatar_storage.get_muc_surface( - self._account, - info.jid, + client = app.get_client(self._account) + contact = client.get_module('Contacts').get_contact( + info.jid, groupchat=True) + surface = contact.get_avatar( AvatarSize.GROUP_INFO, self.get_scale_factor()) self._ui.avatar_image.set_from_surface(surface)
===================================== gajim/gtk/roster.py ===================================== @@ -277,7 +277,7 @@ def _on_block_contact(self, _action, param): def _on_remove_contact(self, _action, param): jid = param.get_string() selected_contact = self._client.get_module('Contacts').get_contact(jid) - if selected_contact.is_transport: + if selected_contact.is_gateway: # Check for transport users in roster and warn about removing the # transport if there are any has_transport_contacts = False @@ -346,7 +346,7 @@ def _on_focus_out(treeview, _param): def _show_contact_menu(self, jid, treeview, event): contact = self._client.get_module('Contacts').get_contact(jid) menu = get_roster_menu( - self._account, jid, transport=contact.is_transport) + self._account, jid, transport=contact.is_gateway)
rectangle = Gdk.Rectangle() rectangle.x = event.x @@ -573,9 +573,7 @@ def _draw_contact_row(self, ref, contact): self._store[iter_][Column.TEXT] = name
surface = contact.get_avatar( - AvatarSize.ROSTER, - self.get_scale_factor(), - add_show=bool(not contact.is_transport)) + AvatarSize.ROSTER, self.get_scale_factor()) self._store[iter_][Column.AVATAR] = surface
def _get_total_user_count(self):
===================================== gajim/gtk/tooltips.py ===================================== @@ -152,10 +152,7 @@ def _populate_grid(self, contact): scale = self._ui.tooltip_grid.get_scale_factor()
# Avatar - surface = contact.get_avatar( - AvatarSize.TOOLTIP, - scale, - add_show=bool(not contact.is_transport)) + surface = contact.get_avatar(AvatarSize.TOOLTIP, scale) self._ui.avatar.set_from_surface(surface) self._ui.avatar.show()
===================================== gajim/gtk/xml_console.py ===================================== @@ -154,6 +154,11 @@ def _on_row_activated(self, _listbox, row): '<iq to="" type="" xmlns="jabber:client">\n' '<query xmlns=""></query>\n' '</iq>') + elif text == 'Disco Info': + input_text = ( + '<iq to="" type="get" xmlns="jabber:client">\n' + '<query xmlns="http://jabber.org/protocol/disco#info"></query>\n' + '</iq>')
if input_text is not None: buffer_ = self._ui.input_entry.get_buffer()
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/819efbefd60cd86afcc807f3dc1e71e4...