[client_icons] Only show icons in tooltips

- Only show icons in tooltips
- Adapt to Gajim changes
This commit is contained in:
lovetox
2020-04-30 23:18:11 +02:00
parent 09830a24d9
commit 71d19e8b60
3 changed files with 68 additions and 218 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>.
from collections import UserDict from collections import UserDict
from collections import namedtuple from collections import namedtuple

View File

@@ -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 <http://www.gnu.org/licenses/>.
import logging import logging
from pathlib import Path from pathlib import Path
from functools import partial from functools import partial
from gi.repository import Gtk 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 app
from gajim.common import caps_cache
from gajim.gtk.util import load_icon from gajim.gtk.util import load_icon
from gajim.plugins import GajimPlugin from gajim.plugins import GajimPlugin
@@ -16,8 +28,6 @@ from gajim.plugins.plugins_i18n import _
from clients_icons import clients from clients_icons import clients
from clients_icons.config_dialog import ClientsIconsConfigDialog from clients_icons.config_dialog import ClientsIconsConfigDialog
from nbxmpp import JID
log = logging.getLogger('gajim.p.client_icons') log = logging.getLogger('gajim.p.client_icons')
@@ -27,15 +37,7 @@ class ClientsIconsPlugin(GajimPlugin):
' and in groupchats.') ' and in groupchats.')
self.config_dialog = partial(ClientsIconsConfigDialog, self) self.config_dialog = partial(ClientsIconsConfigDialog, self)
self.events_handlers = {
'caps-update': (
ged.POSTGUI, self._on_caps_update),
}
self.gui_extension_points = { self.gui_extension_points = {
'roster_draw_contact': (
self.connect_with_roster_draw_contact,
None),
'roster_tooltip_populate': ( 'roster_tooltip_populate': (
self.connect_with_roster_tooltip_populate, self.connect_with_roster_tooltip_populate,
None), None),
@@ -45,11 +47,8 @@ class ClientsIconsPlugin(GajimPlugin):
} }
self.config_default_values = { self.config_default_values = {
'show_in_roster': (True, ''),
'show_in_tooltip': (True, ''), 'show_in_tooltip': (True, ''),
'show_unknown_icon': (True, ''), 'show_unknown_icon': (True, ''),
'pos_in_list': ('0', ''),
'show_facebook': (True, ''),
} }
_icon_theme = Gtk.IconTheme.get_default() _icon_theme = Gtk.IconTheme.get_default()
@@ -57,16 +56,29 @@ class ClientsIconsPlugin(GajimPlugin):
_icon_theme.append_search_path(str(Path(__file__).parent)) _icon_theme.append_search_path(str(Path(__file__).parent))
@staticmethod @staticmethod
def get_client_identity_name(contact): def _get_client_identity_name(disco_info):
identities = contact.client_caps.get_cache_lookup_strategy()( for identity in disco_info.identities:
caps_cache.capscache).identities if identity.category == 'client':
if identities: return identity.name
for entry in identities:
if entry.category == 'client': def _get_image_and_client_name(self, contact, widget):
return entry.name 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 @staticmethod
def is_groupchat(contact): def _is_groupchat(contact):
if hasattr(contact, 'is_groupchat'): if hasattr(contact, 'is_groupchat'):
return contact.is_groupchat return contact.is_groupchat
return False return False
@@ -108,9 +120,12 @@ class ClientsIconsPlugin(GajimPlugin):
if not self.config['show_in_tooltip']: if not self.config['show_in_tooltip']:
return return
# Check if clients info already attached to tooltip result = self._get_image_and_client_name(contact, tooltip_grid)
node = contact.client_caps._node if result is None:
image, client_name = self.get_icon(node, contact, tooltip_grid) return
image, client_name = result
label = Gtk.Label(label=client_name) label = Gtk.Label(label=client_name)
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
@@ -127,9 +142,11 @@ class ClientsIconsPlugin(GajimPlugin):
tooltip_grid): tooltip_grid):
if not self.config['show_in_tooltip']: if not self.config['show_in_tooltip']:
return return
if len(contacts) == 1 and contacts[0].jid in app.get_our_jids(): if len(contacts) == 1 and contacts[0].jid in app.get_our_jids():
return return
if self.is_groupchat(contacts[0]):
if self._is_groupchat(contacts[0]):
return return
# Put contacts in dict, where key is priority # Put contacts in dict, where key is priority
@@ -157,11 +174,14 @@ class ClientsIconsPlugin(GajimPlugin):
vcard_current_row = 0 vcard_current_row = 0
for priority in contact_keys: for priority in contact_keys:
for acontact in contacts_dict[priority]: for acontact in contacts_dict[priority]:
caps = acontact.client_caps._node
caps_image, client_name = self.get_icon( result = self._get_image_and_client_name(acontact, tooltip_grid)
caps, acontact, tooltip_grid) if result is None:
caps_image.set_valign(Gtk.Align.START) continue
grid.attach(caps_image, 1, vcard_current_row, 1, 1) 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 = Gtk.Label(label=client_name)
label.set_valign(Gtk.Align.START) label.set_valign(Gtk.Align.START)
label.set_halign(Gtk.Align.START) label.set_halign(Gtk.Align.START)
@@ -188,161 +208,3 @@ class ClientsIconsPlugin(GajimPlugin):
Gtk.PositionType.BOTTOM, 1, 1) Gtk.PositionType.BOTTOM, 1, 1)
tooltip_grid.attach_next_to(grid, label, tooltip_grid.attach_next_to(grid, label,
Gtk.PositionType.RIGHT, 1, 1) 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

View File

@@ -15,8 +15,6 @@
from gi.repository import Gtk from gi.repository import Gtk
from gajim.common import app
from gajim.gtk.settings import SettingsDialog from gajim.gtk.settings import SettingsDialog
from gajim.gtk.const import Setting from gajim.gtk.const import Setting
from gajim.gtk.const import SettingKind from gajim.gtk.const import SettingKind
@@ -28,15 +26,8 @@ from gajim.plugins.plugins_i18n import _
class ClientsIconsConfigDialog(SettingsDialog): class ClientsIconsConfigDialog(SettingsDialog):
def __init__(self, plugin, parent): def __init__(self, plugin, parent):
icon_position = [
('0', _('Before Avatar')),
('1', _('After Status Icon'))]
self.plugin = plugin self.plugin = plugin
settings = [ 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'), Setting(SettingKind.SWITCH, _('Show Icons in Tooltip'),
SettingType.VALUE, self.plugin.config['show_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'], SettingType.VALUE, self.plugin.config['show_unknown_icon'],
callback=self._on_setting, data='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'), SettingsDialog.__init__(self, parent, _('Clients Icons Configuration'),
@@ -62,12 +44,3 @@ class ClientsIconsConfigDialog(SettingsDialog):
def _on_setting(self, value, data): def _on_setting(self, value, data):
self.plugin.config[data] = value 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)