Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim-plugins.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'clients_icons/clients_icons.py')
-rw-r--r--clients_icons/clients_icons.py418
1 files changed, 154 insertions, 264 deletions
diff --git a/clients_icons/clients_icons.py b/clients_icons/clients_icons.py
index 38dc4b6..80f9124 100644
--- a/clients_icons/clients_icons.py
+++ b/clients_icons/clients_icons.py
@@ -1,41 +1,36 @@
-import os
import logging
+from pathlib import Path
from gi.repository import Gtk
-from gi.repository import GdkPixbuf
+from nbxmpp import JID
-from clients_icons.clients import CLIENTS, LIBPURPLE_CLIENTS
+from clients_icons import clients
+
+from gajim.roster_window import Column
-from gajim.plugins.gui import GajimPluginConfigDialog
from gajim.plugins import GajimPlugin
-from gajim.plugins.helpers import log_calls
+from gajim.plugins.gui import GajimPluginConfigDialog
+from gajim.plugins.plugins_i18n import _
+
from gajim.common import ged
from gajim.common import app
from gajim.common import caps_cache
-# Since Gajim 1.1.0 _() has to be imported
-try:
- from gajim.common.i18n import _
-except ImportError:
- pass
-log = logging.getLogger('gajim.plugin_system.clients_icons')
+from gajim.gtk.util import load_icon
-class ClientsIconsPlugin(GajimPlugin):
+log = logging.getLogger('gajim.plugin_system.client_icons')
- @log_calls('ClientsIconsPlugin')
+
+class ClientsIconsPlugin(GajimPlugin):
def init(self):
self.description = _('Shows client icons in roster'
' and in groupchats.')
self.pos_list = [_('after statusicon'), _('before avatar')]
self.events_handlers = {
- 'caps-presence-received': (ged.POSTGUI,
- self.caps_presence_received),
- 'gc-presence-received': (ged.POSTGUI,
- self.gc_presence_received),
- 'caps-disco-received': (ged.POSTGUI,
- self.caps_disco_received), }
+ 'caps-update': (ged.POSTGUI, self._on_caps_update),
+ }
self.gui_extension_points = {
'groupchat_control': (self.connect_with_groupchat_control,
self.disconnect_from_groupchat_control),
@@ -44,42 +39,28 @@ class ClientsIconsPlugin(GajimPlugin):
'gc_tooltip_populate': (self.connect_with_gc_tooltip_populate, None),
}
self.config_default_values = {
- 'show_in_roster': (True, ''),
- 'show_in_groupchats': (True, ''),
- 'show_in_tooltip': (True, ''),
- 'show_unknown_icon': (True, ''),
- 'pos_in_list': (0, ''),
- 'show_facebook': (True, ''),}
+ 'show_in_roster': (True, ''),
+ 'show_in_groupchats': (True, ''),
+ 'show_in_tooltip': (True, ''),
+ 'show_unknown_icon': (True, ''),
+ 'pos_in_list': (0, ''),
+ 'show_facebook': (True, ''),
+ }
+
+ _icon_theme = Gtk.IconTheme.get_default()
+ if _icon_theme is not None:
+ _icon_theme.append_search_path(str(Path(__file__).parent))
self.config_dialog = ClientsIconsPluginConfigDialog(self)
- icon_path = os.path.join(self.local_file_path('icons'), 'unknown.png')
- self.default_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
- icon_path, 16, 16)
- self.icon_cache = {}
- @log_calls('ClientsIconsPlugin')
- def get_client_name(self, contact, client_name):
+ @staticmethod
+ def get_client_identity_name(contact):
identities = contact.client_caps.get_cache_lookup_strategy()(
caps_cache.capscache).identities
if identities:
- log.debug('get_client_name, identities: %s', str(identities))
for entry in identities:
if entry['category'] == 'client':
- client_name = entry.get('name', client_name)
- break
- return client_name
-
- def get_client_icon_by_name(self, client_name):
- client_icon = None
- name_splits = client_name.split()
- name_splits = reversed([" ".join(name_splits[:(i+1)]) for i in range(len(name_splits))])
- for name in name_splits:
- if not client_icon:
- log.debug("get_client_icon_by_name, searching for name fragment '%s'..." % name)
- client_icon = CLIENTS.get(name, (None,))[0]
- if client_icon:
- break
- return client_icon
+ return entry.get('name')
@staticmethod
def is_groupchat(contact):
@@ -87,14 +68,10 @@ class ClientsIconsPlugin(GajimPlugin):
return contact.is_groupchat()
return False
- @log_calls('ClientsIconsPlugin')
def add_tooltip_row(self, tooltip, contact, tooltip_grid):
caps = contact.client_caps._node
- log.debug('connect_with_gc_tooltip_populate, caps: %s', caps)
- caps_image, client_name = self.get_icon(caps, contact)
- client_name = self.get_client_name(contact, client_name)
+ caps_image, client_name = self.get_icon(caps, contact, tooltip_grid)
caps_image.set_halign(Gtk.PositionType.RIGHT)
- log.debug('connect_with_gc_tooltip_populate, client_name: %s', client_name)
# fill clients table
self.table = Gtk.Grid()
@@ -122,27 +99,25 @@ class ClientsIconsPlugin(GajimPlugin):
tooltip_grid.attach_next_to(self.table, label,
Gtk.PositionType.RIGHT, 1, 1)
- @log_calls('ClientsIconsPlugin')
def connect_with_gc_tooltip_populate(self, tooltip, contact, tooltip_grid):
if not self.config['show_in_tooltip']:
return
# Check if clients info already attached to tooltip
- has_attached = False
- for child in tooltip_grid.get_children():
- if child.get_name() == 'client_icons_grid':
- caps = contact.client_caps._node
- caps_image, client_name = self.get_icon(caps, contact)
- child.remove(child.get_child_at(1, 1))
- child.attach(caps_image, 1, 1, 1, 1)
- child.get_child_at(2, 1).set_markup(client_name)
- child.show_all()
- if child.get_name() == 'client_icons_label':
- child.show()
- has_attached = True
- if not has_attached:
- self.add_tooltip_row(tooltip, contact, tooltip_grid)
-
- @log_calls('ClientsIconsPlugin')
+
+ node = contact.client_caps._node
+ image, client_name = self.get_icon(node, contact, tooltip_grid)
+ label = Gtk.Label(label=client_name)
+
+ box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+ box.add(image)
+ box.add(label)
+ box.show_all()
+
+ tooltip_grid.insert_next_to(tooltip._ui.affiliation,
+ Gtk.PositionType.BOTTOM)
+ tooltip_grid.attach_next_to(box, tooltip._ui.affiliation,
+ Gtk.PositionType.BOTTOM, 1, 1)
+
def connect_with_roster_tooltip_populate(self, tooltip, contacts, tooltip_grid):
if not self.config['show_in_tooltip']:
return
@@ -155,6 +130,8 @@ class ClientsIconsPlugin(GajimPlugin):
num_resources = 0
contacts_dict = {}
for contact in contacts:
+ if contact.show == 'offline':
+ return
if contact.resource:
num_resources += 1
if int(contact.priority) in contacts_dict:
@@ -165,97 +142,50 @@ class ClientsIconsPlugin(GajimPlugin):
contact_keys.reverse()
# fill clients table
- self.table = Gtk.Grid()
- self.table.insert_row(0)
- self.table.insert_row(0)
- self.table.insert_column(0)
- self.table.set_property('column-spacing', 2)
+ table = Gtk.Grid()
+ table.insert_row(0)
+ table.insert_row(0)
+ table.insert_column(0)
+ table.set_property('column-spacing', 2)
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)
- client_name = self.get_client_name(acontact, client_name)
- caps_image.set_alignment(0, 0)
- self.table.attach(caps_image, 1, vcard_current_row, 1, 1)
- label = Gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup(client_name)
- self.table.attach(label, 2, vcard_current_row, 1, 1)
+ caps_image, client_name = self.get_icon(caps, acontact, tooltip_grid)
+ caps_image.set_valign(Gtk.Align.START)
+ table.attach(caps_image, 1, vcard_current_row, 1, 1)
+ label = Gtk.Label(label=client_name)
+ label.set_valign(Gtk.Align.START)
+ label.set_xalign(0)
+ table.attach(label, 2, vcard_current_row, 1, 1)
vcard_current_row += 1
- self.table.show_all()
+ table.show_all()
+ table.set_valign(Gtk.Align.START)
# set label
label = Gtk.Label()
- label.set_alignment(0, 0)
+ label.set_halign(Gtk.Align.END)
+ label.set_valign(Gtk.Align.START)
if num_resources > 1:
- label.set_markup(_('Clients:'))
+ label.set_text(_('Clients:'))
else:
- if contact.show == 'offline':
- return
- label.set_markup(_('Client:'))
+ label.set_text(_('Client:'))
label.show()
# set clients table to tooltip
- tooltip_grid.insert_next_to(tooltip.resource_label,
+ tooltip_grid.insert_next_to(tooltip._ui.resource_label,
Gtk.PositionType.BOTTOM)
- tooltip_grid.attach_next_to(label, tooltip.resource_label,
+ tooltip_grid.attach_next_to(label, tooltip._ui.resource_label,
Gtk.PositionType.BOTTOM, 1, 1)
- tooltip_grid.attach_next_to(self.table, label,
+ tooltip_grid.attach_next_to(table, label,
Gtk.PositionType.RIGHT, 1, 1)
- def get_icon(self, caps, contact):
- client_name = _('Unknown')
- caps_ = None
- if caps:
- # libpurple returns pidgin.im/ only, we have to look for resource name
- if 'pidgin.im/' in caps:
- caps = 'libpurple'
- for client in LIBPURPLE_CLIENTS:
- if client in contact.resource.lower():
- caps = LIBPURPLE_CLIENTS[client]
-
- if 'sleekxmpp.com'in caps:
- caps = 'httр://sleekxmpp.com/ver/1.1.11'
- caps_from_jid = self.check_jid(contact.jid)
- if caps_from_jid:
- caps = caps_from_jid
- caps_ = caps.split('#')[0].split()
-
- client_name = self.get_client_name(contact, client_name)
- client_icon = self.get_client_icon_by_name(client_name)
-
- if caps_ and not client_icon:
- client_icon = CLIENTS.get(caps_[0].split()[0], (None,))[0]
- client_name = CLIENTS.get(caps_[0].split()[0], ('', _('Unknown')))[1]
-
- if not client_icon:
- return Gtk.Image.new_from_pixbuf(self.default_pixbuf), _('Unknown')
- else:
- icon_path = os.path.join(self.local_file_path('icons'), client_icon)
- if icon_path in self.icon_cache:
- return Gtk.Image.new_from_pixbuf(self.icon_cache[icon_path]), \
- client_name
- else:
- pb = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_path, 16, 16)
- self.icon_cache[icon_path] = pb
- return Gtk.Image.new_from_pixbuf(pb), client_name
-
- def check_jid(self, jid):
- caps = None
- if 'facebook.com' in jid and self.config['show_facebook']:
- caps = 'facebook.com'
- elif '@vk.com' in jid and self.config['show_facebook']:
- caps = 'vk.com'
- elif jid == 'juick@juick.com':
- caps = 'http://juick.com/caps'
- elif jid == 'psto@psto.net':
- caps = 'psto@psto.net'
- elif jid == 'rss@isida-bot.com':
- caps = 'rss@isida-bot.com'
- return caps
-
- @log_calls('ClientsIconsPlugin')
+ 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
@@ -268,22 +198,19 @@ class ClientsIconsPlugin(GajimPlugin):
return
for iter_ in child_iters:
if roster.model[iter_][self.renderer_num] is None:
- caps = contact.client_caps._node
- if not caps:
- caps = self.check_jid(jid)
- self.set_icon(roster.model, iter_, self.renderer_num, caps, contact)
+ node = contact.client_caps._node
+ self.set_icon(roster.model, iter_, self.renderer_num, node, contact)
- @log_calls('ClientsIconsPlugin')
def connect_with_groupchat_control(self, chat_control):
chat_control.nb_ext_renderers += 1
- chat_control.columns += [GdkPixbuf.Pixbuf]
+ chat_control.columns += [str]
self.groupchats_tree_is_transformed = True
self.chat_control = chat_control
col = Gtk.TreeViewColumn()
self.muc_renderer_num = 4 + chat_control.nb_ext_renderers
client_icon_rend = (
'client_icon', Gtk.CellRendererPixbuf(), False,
- 'pixbuf', self.muc_renderer_num,
+ 'icon_name', self.muc_renderer_num,
self.tree_cell_data_func, chat_control)
# remove old column
chat_control.list_treeview.remove_column(
@@ -310,14 +237,10 @@ class ClientsIconsPlugin(GajimPlugin):
chat_control.account, chat_control.room_jid):
gc_contact = app.contacts.get_gc_contact(
chat_control.account, chat_control.room_jid, nick)
- iter_ = chat_control.add_contact_to_roster(
- nick, gc_contact.show, gc_contact.role,
- gc_contact.affiliation, gc_contact.status, gc_contact.jid)
+ iter_ = chat_control.add_contact_to_roster(nick)
if not self.config['show_in_groupchats']:
- log.debug("not showing in groupchats...")
continue
caps = gc_contact.client_caps._node
- log.debug("caps: %s" % str(caps))
self.set_icon(
chat_control.model, iter_,
self.muc_renderer_num, caps, gc_contact)
@@ -325,7 +248,6 @@ class ClientsIconsPlugin(GajimPlugin):
# Recalculate column width for ellipsizin
chat_control.list_treeview.columns_autosize()
- @log_calls('ClientsIconsPlugin')
def disconnect_from_groupchat_control(self, gc_control):
gc_control.nb_ext_renderers -= 1
col = gc_control.list_treeview.get_column(0)
@@ -345,7 +267,6 @@ class ClientsIconsPlugin(GajimPlugin):
gc_control.list_treeview.set_model(gc_control.model)
gc_control.draw_roster()
- @log_calls('ClientsIconsPlugin')
def activate(self):
self.active = None
roster = app.interface.roster
@@ -355,8 +276,8 @@ class ClientsIconsPlugin(GajimPlugin):
self.renderer = Gtk.CellRendererPixbuf()
client_icon_rend = (
'client_icon', self.renderer, False,
- 'pixbuf', self.renderer_num,
- roster._fill_pep_pixbuf_renderer, self.renderer_num)
+ '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
@@ -371,11 +292,33 @@ class ClientsIconsPlugin(GajimPlugin):
roster.fill_column(col)
roster.tree.insert_column(col, 0)
# redraw roster
- roster.columns += [GdkPixbuf.Pixbuf]
+ roster.columns += [str]
self.active = True
roster.setup_and_draw_roster()
- @log_calls('ClientsIconsPlugin')
+ 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
@@ -393,139 +336,86 @@ class ClientsIconsPlugin(GajimPlugin):
self.renderer_num + 1:]
roster.setup_and_draw_roster()
- def caps_disco_received(self, iq_obj):
- log.debug("caps disco received...")
- if not self.config['show_in_roster']:
- return
- roster = app.interface.roster
- contact = app.contacts.get_contact_from_full_jid(
- iq_obj.conn.name, iq_obj.jid)
- if self.is_groupchat(contact):
+ def _on_caps_update(self, event):
+ if event.conn.name == 'Local':
+ # zeroconf
return
+
+ contact = self._get_contact_or_gc_contact_for_jid(event.conn.name, event.fjid)
if contact is None:
- room_jid, nick = app.get_room_and_nick_from_fjid(iq_obj.fjid)
- contact = app.contacts.get_gc_contact(iq_obj.conn.name, room_jid, nick)
- if contact:
- gc_control = app.interface.msg_win_mgr.get_gc_control(
- iq_obj.jid, iq_obj.conn.name)
- iter_ = gc_control.get_contact_iter(nick)
- self.set_icon(gc_control.model, iter_,
- self.muc_renderer_num, None, contact)
- return
- if not contact:
- return
- child_iters = roster._get_contact_iter(
- iq_obj.jid, iq_obj.conn.name, contact, roster.model)
- if not child_iters:
return
- for iter_ in child_iters:
- caps = contact.client_caps._node
- caps_ = self.check_jid(iq_obj.jid)
- if caps_:
- caps = caps_
- self.set_icon(roster.model, iter_, self.renderer_num, caps, contact)
- def caps_presence_received(self, iq_obj):
- log.debug("caps presence received...")
+ if contact.is_gc_contact:
+ self._draw_gc_contact(event, contact)
+ else:
+ self._draw_roster_contact(event, contact)
+
+ def _draw_roster_contact(self, event, contact):
if not self.config['show_in_roster']:
return
- roster = app.interface.roster
- contact = app.contacts.get_contact_with_highest_priority(
- iq_obj.conn.name, iq_obj.jid)
- if not contact or self.is_groupchat(contact):
- return
- if iq_obj.resource == 'local':
- # zeroconf
+ if contact.is_groupchat():
return
-
- iters = roster._get_contact_iter(iq_obj.jid, iq_obj.conn.name, contact,
+ roster = app.interface.roster
+ iters = roster._get_contact_iter(event.jid, event.conn.name, contact,
roster.model)
iter_ = iters[0]
- if contact.show == 'error':
- self.set_icon(roster.model, iter_, self.renderer_num, None, contact)
+ # highest contact changed
+ caps = contact.client_caps._node
+ if not caps:
return
- # highest contact changed
if roster.model[iter_][self.renderer_num] is not None:
- caps = contact.client_caps._node
- if caps:
- log.debug('caps_presence_received, caps: %s', caps)
- self.set_icon(roster.model, iter_, self.renderer_num, caps, contact)
- return
-
- caps = None
- tag = iq_obj.stanza.getTags('c')
- if tag:
- caps = tag[0].getAttr('node')
- if caps:
- if 'pidgin.im/' in caps:
- caps = 'libpurple'
- for client in LIBPURPLE_CLIENTS:
- if client in contact.resource.lower():
- caps = LIBPURPLE_CLIENTS[client]
- if 'sleekxmpp.com'in caps:
- caps = 'httр://sleekxmpp.com/ver/1.1.11'
-
- caps_from_jid = self.check_jid(iq_obj.jid)
- if caps_from_jid:
- caps = caps_from_jid
+ 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 gc_presence_received(self, iq_obj):
- log.debug("gc presence received...")
+ def _draw_gc_contact(self, event, contact):
if not self.config['show_in_groupchats']:
return
- contact = app.contacts.get_gc_contact(
- iq_obj.conn.name, iq_obj.presence_obj.jid, iq_obj.nick)
- if not contact:
+
+ control = app.interface.msg_win_mgr.get_gc_control(contact.room_jid,
+ event.conn.name)
+ if control is None:
return
- caps = None
- tag = iq_obj.stanza.getTags('c')
- if tag:
- caps = tag[0].getAttr('node')
- if caps:
- log.debug('gc_presence_received, caps: %s', caps)
- if 'pidgin.im/' in caps:
- caps = 'libpurple'
- if 'sleekxmpp.com' in caps:
- caps = 'httр://sleekxmpp.com/ver/1.1.11'
- iter_ = iq_obj.gc_control.get_contact_iter(iq_obj.nick)
- model = iq_obj.gc_control.model
- if model[iter_][self.muc_renderer_num] is not None:
+ iter_ = control.get_contact_iter(contact.name)
+ if control.model[iter_][self.muc_renderer_num] is not None:
+ return
+ caps = contact.client_caps._node
+ if not caps:
return
- self.set_icon(model, iter_, self.muc_renderer_num, caps, contact)
+ self.set_icon(control.model, iter_, self.muc_renderer_num, caps, contact)
- def set_icon(self, model, iter_, pos, caps, contact):
- client_icon = self.get_client_icon_by_name(
- self.get_client_name(contact, _('Unknown')))
+ def _get_contact_or_gc_contact_for_jid(self, account, fjid):
+ contact = app.contacts.get_contact_from_full_jid(account, fjid)
- if caps and not client_icon:
- caps_ = caps.split('#')[0].split()
- if caps_:
- log.debug('set_icon, caps_: %s', caps_)
- client_icon = CLIENTS.get(caps_[0].split()[0], (None,))[0]
+ 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
- if not client_icon:
- if self.config['show_unknown_icon']:
- model[iter_][pos] = self.default_pixbuf
- else:
- icon_path = os.path.join(self.local_file_path('icons'), client_icon)
- if icon_path in self.icon_cache:
- model[iter_][pos] = self.icon_cache[icon_path]
- else:
- pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_path, 16, 16)
- model[iter_][pos] = pixbuf
- self.icon_cache[icon_path] = pixbuf
+ model[iter_][pos] = icon_name
def tree_cell_data_func(self, column, renderer, model, iter_, control):
if not model.iter_parent(iter_):
renderer.set_property('visible', False)
return
- elif model[iter_][self.muc_renderer_num]:
+
+ if model[iter_][self.muc_renderer_num]:
renderer.set_property('visible', True)
contact = app.contacts.get_gc_contact(