diff --git a/clients_icons/clients.py b/clients_icons/clients.py
index 0eefd30..29936e6 100644
--- a/clients_icons/clients.py
+++ b/clients_icons/clients.py
@@ -1,3 +1,18 @@
+# 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 .
+
from collections import UserDict
from collections import namedtuple
diff --git a/clients_icons/clients_icons.py b/clients_icons/clients_icons.py
index 99c4fcf..6ae728d 100644
--- a/clients_icons/clients_icons.py
+++ b/clients_icons/clients_icons.py
@@ -1,13 +1,25 @@
+# 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 .
+
import logging
from pathlib import Path
from functools import partial
from gi.repository import Gtk
-from gajim.roster_window import Column
-from gajim.common import ged
from gajim.common import app
-from gajim.common import caps_cache
from gajim.gtk.util import load_icon
from gajim.plugins import GajimPlugin
@@ -16,8 +28,6 @@ from gajim.plugins.plugins_i18n import _
from clients_icons import clients
from clients_icons.config_dialog import ClientsIconsConfigDialog
-from nbxmpp import JID
-
log = logging.getLogger('gajim.p.client_icons')
@@ -27,15 +37,7 @@ class ClientsIconsPlugin(GajimPlugin):
' and in groupchats.')
self.config_dialog = partial(ClientsIconsConfigDialog, self)
- self.events_handlers = {
- 'caps-update': (
- ged.POSTGUI, self._on_caps_update),
- }
-
self.gui_extension_points = {
- 'roster_draw_contact': (
- self.connect_with_roster_draw_contact,
- None),
'roster_tooltip_populate': (
self.connect_with_roster_tooltip_populate,
None),
@@ -45,11 +47,8 @@ class ClientsIconsPlugin(GajimPlugin):
}
self.config_default_values = {
- 'show_in_roster': (True, ''),
'show_in_tooltip': (True, ''),
'show_unknown_icon': (True, ''),
- 'pos_in_list': ('0', ''),
- 'show_facebook': (True, ''),
}
_icon_theme = Gtk.IconTheme.get_default()
@@ -57,16 +56,29 @@ class ClientsIconsPlugin(GajimPlugin):
_icon_theme.append_search_path(str(Path(__file__).parent))
@staticmethod
- def get_client_identity_name(contact):
- identities = contact.client_caps.get_cache_lookup_strategy()(
- caps_cache.capscache).identities
- if identities:
- for entry in identities:
- if entry.category == 'client':
- return entry.name
+ def _get_client_identity_name(disco_info):
+ for identity in disco_info.identities:
+ if identity.category == 'client':
+ return identity.name
+
+ def _get_image_and_client_name(self, contact, widget):
+ disco_info = app.logger.get_last_disco_info(contact.get_full_jid())
+ if disco_info is None:
+ return None
+
+ if disco_info.node is None:
+ return None
+
+ node = disco_info.node.split('#')[0]
+ client_name = self._get_client_identity_name(disco_info)
+
+ log.info('Lookup client: %s %s', client_name, node)
+ client_name, icon_name = clients.get_data(client_name, node)
+ surface = load_icon(icon_name, widget=widget)
+ return Gtk.Image.new_from_surface(surface), client_name
@staticmethod
- def is_groupchat(contact):
+ def _is_groupchat(contact):
if hasattr(contact, 'is_groupchat'):
return contact.is_groupchat
return False
@@ -108,9 +120,12 @@ class ClientsIconsPlugin(GajimPlugin):
if not self.config['show_in_tooltip']:
return
- # Check if clients info already attached to tooltip
- node = contact.client_caps._node
- image, client_name = self.get_icon(node, contact, tooltip_grid)
+ result = self._get_image_and_client_name(contact, tooltip_grid)
+ if result is None:
+ return
+
+ image, client_name = result
+
label = Gtk.Label(label=client_name)
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
@@ -127,9 +142,11 @@ class ClientsIconsPlugin(GajimPlugin):
tooltip_grid):
if not self.config['show_in_tooltip']:
return
+
if len(contacts) == 1 and contacts[0].jid in app.get_our_jids():
return
- if self.is_groupchat(contacts[0]):
+
+ if self._is_groupchat(contacts[0]):
return
# Put contacts in dict, where key is priority
@@ -157,11 +174,14 @@ class ClientsIconsPlugin(GajimPlugin):
vcard_current_row = 0
for priority in contact_keys:
for acontact in contacts_dict[priority]:
- caps = acontact.client_caps._node
- caps_image, client_name = self.get_icon(
- caps, acontact, tooltip_grid)
- caps_image.set_valign(Gtk.Align.START)
- grid.attach(caps_image, 1, vcard_current_row, 1, 1)
+
+ result = self._get_image_and_client_name(acontact, tooltip_grid)
+ if result is None:
+ continue
+ image, client_name = result
+
+ image.set_valign(Gtk.Align.START)
+ grid.attach(image, 1, vcard_current_row, 1, 1)
label = Gtk.Label(label=client_name)
label.set_valign(Gtk.Align.START)
label.set_halign(Gtk.Align.START)
@@ -188,161 +208,3 @@ class ClientsIconsPlugin(GajimPlugin):
Gtk.PositionType.BOTTOM, 1, 1)
tooltip_grid.attach_next_to(grid, label,
Gtk.PositionType.RIGHT, 1, 1)
-
- def get_icon(self, node, contact, widget):
- identity_name = self.get_client_identity_name(contact)
- client_name, icon_name = clients.get_data(identity_name, node)
- surface = load_icon(icon_name, widget=widget)
- return Gtk.Image.new_from_surface(surface), client_name
-
- def connect_with_roster_draw_contact(self, roster, jid, account, contact):
- if not self.active:
- return
- if not self.config['show_in_roster']:
- return
- if self.is_groupchat(contact):
- return
- child_iters = roster._get_contact_iter(
- jid, account, contact, roster.model)
- if not child_iters:
- return
- for iter_ in child_iters:
- if roster.model[iter_][self.renderer_num] is None:
- node = contact.client_caps._node
- self.set_icon(
- roster.model, iter_, self.renderer_num, node, contact)
-
- def activate(self):
- self.active = None
- roster = app.interface.roster
- col = Gtk.TreeViewColumn()
- roster.nb_ext_renderers += 1
- self.renderer_num = 11 + roster.nb_ext_renderers
- self.renderer = Gtk.CellRendererPixbuf()
- client_icon_rend = (
- 'client_icon', self.renderer, False,
- 'icon_name', self.renderer_num,
- self._roster_icon_renderer, self.renderer_num)
-
- # Remove old column
- roster.tree.remove_column(roster.tree.get_column(0))
-
- # Add new renderer in renderers list
- position_list = ['name', 'avatar']
- position = position_list[int(self.config['pos_in_list'])]
- for renderer in roster.renderers_list:
- if renderer[0] == position:
- break
- num = roster.renderers_list.index(renderer)
- roster.renderers_list.insert(num, client_icon_rend)
-
- # Fill and append column
- roster.fill_column(col)
- roster.tree.insert_column(col, 0)
-
- # Redraw roster
- roster.columns += [str]
- self.active = True
- roster.setup_and_draw_roster()
-
- def _roster_icon_renderer(self, column, renderer, model, titer, data=None):
- try:
- type_ = model[titer][Column.TYPE]
- except TypeError:
- return
-
- # Allocate space for the icon only if needed
- if model[titer][data] is None:
- renderer.set_property('visible', False)
- else:
- renderer.set_property('visible', True)
-
- if type_ == 'account':
- app.interface.roster._set_account_row_background_color(renderer)
- renderer.set_property('xalign', 1)
- elif type_:
- if (not model[titer][Column.JID] or
- not model[titer][Column.ACCOUNT]):
- # This can append at the moment we add the row
- return
- jid = model[titer][Column.JID]
- account = model[titer][Column.ACCOUNT]
- app.interface.roster._set_contact_row_background_color(
- renderer, jid, account)
-
- def deactivate(self):
- self.active = None
- roster = app.interface.roster
- roster.nb_ext_renderers -= 1
- col = roster.tree.get_column(0)
- roster.tree.remove_column(col)
- col = Gtk.TreeViewColumn()
- for renderer in roster.renderers_list:
- if renderer[0] == 'client_icon':
- roster.renderers_list.remove(renderer)
- break
- roster.fill_column(col)
- roster.tree.insert_column(col, 0)
- roster.columns = roster.columns[:self.renderer_num] + roster.columns[
- self.renderer_num + 1:]
- roster.setup_and_draw_roster()
-
- def _on_caps_update(self, event):
- # Zeroconf
- if event.account == 'Local':
- return
-
- contact = self._get_contact_or_gc_contact_for_jid(
- event.account, event.fjid)
- if contact is None:
- return
-
- if contact.is_gc_contact:
- return
- self._draw_roster_contact(event, contact)
-
- def _draw_roster_contact(self, event, contact):
- if not self.config['show_in_roster']:
- return
-
- if contact.is_groupchat:
- return
- roster = app.interface.roster
- iters = roster._get_contact_iter(
- event.jid, event.account, contact, roster.model)
- iter_ = iters[0]
-
- # Highest contact changed
- caps = contact.client_caps._node
- if not caps:
- return
-
- if roster.model[iter_][self.renderer_num] is not None:
- self.set_icon(
- roster.model, iter_, self.renderer_num, caps, contact)
- return
-
- for iter_ in iters:
- self.set_icon(
- roster.model, iter_, self.renderer_num, caps, contact)
-
- def _get_contact_or_gc_contact_for_jid(self, account, fjid):
- contact = app.contacts.get_contact_from_full_jid(account, fjid)
-
- if contact is None:
- fjid = JID(fjid)
- room_jid, resource = fjid.getStripped(), fjid.getResource()
- contact = app.contacts.get_gc_contact(account, room_jid, resource)
- return contact
-
- def set_icon(self, model, iter_, pos, node, contact):
- identity_name = self.get_client_identity_name(contact)
- _client_name, icon_name = clients.get_data(identity_name, node)
- if 'unknown' in icon_name:
- if node is not None:
- log.warning('Unknown client: %s %s', identity_name, node)
- if not self.config['show_unknown_icon']:
- model[iter_][pos] = None
- return
-
- model[iter_][pos] = icon_name
diff --git a/clients_icons/config_dialog.py b/clients_icons/config_dialog.py
index 3dcdda7..042c0b6 100644
--- a/clients_icons/config_dialog.py
+++ b/clients_icons/config_dialog.py
@@ -15,8 +15,6 @@
from gi.repository import Gtk
-from gajim.common import app
-
from gajim.gtk.settings import SettingsDialog
from gajim.gtk.const import Setting
from gajim.gtk.const import SettingKind
@@ -28,15 +26,8 @@ from gajim.plugins.plugins_i18n import _
class ClientsIconsConfigDialog(SettingsDialog):
def __init__(self, plugin, parent):
- icon_position = [
- ('0', _('Before Avatar')),
- ('1', _('After Status Icon'))]
-
self.plugin = plugin
settings = [
- Setting(SettingKind.SWITCH, _('Show Icons in Contact List'),
- SettingType.VALUE, self.plugin.config['show_in_roster'],
- callback=self._on_setting, data='show_in_roster'),
Setting(SettingKind.SWITCH, _('Show Icons in Tooltip'),
SettingType.VALUE, self.plugin.config['show_in_tooltip'],
@@ -46,15 +37,6 @@ class ClientsIconsConfigDialog(SettingsDialog):
SettingType.VALUE, self.plugin.config['show_unknown_icon'],
callback=self._on_setting, data='show_unknown_icon'),
- Setting(SettingKind.SWITCH, _('Show Icon for Transports'),
- SettingType.VALUE, self.plugin.config['show_facebook'],
- desc=_('Icons for facebook.com and vk.com'),
- callback=self._on_setting, data='show_facebook'),
-
- Setting(SettingKind.COMBO, _('Icon Position'),
- SettingType.VALUE, self.plugin.config['pos_in_list'],
- callback=self._on_setting, data='pos_in_list',
- props={'combo_items': icon_position}),
]
SettingsDialog.__init__(self, parent, _('Clients Icons Configuration'),
@@ -62,12 +44,3 @@ class ClientsIconsConfigDialog(SettingsDialog):
def _on_setting(self, value, data):
self.plugin.config[data] = value
- self._redraw_all()
-
- def _redraw_all(self):
- self.plugin.deactivate()
- self.plugin.activate()
- for gc_control in app.interface.msg_win_mgr.get_controls('gc'):
- self.plugin.disconnect_from_groupchat_control(gc_control)
- for gc_control in app.interface.msg_win_mgr.get_controls('gc'):
- self.plugin.connect_with_groupchat_control(gc_control)