diff --git a/gajim/cell_renderer_image.py b/gajim/cell_renderer_image.py deleted file mode 100644 index e26c4f493..000000000 --- a/gajim/cell_renderer_image.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright (C) 2003-2014 Yann Leboulanger -# Copyright (C) 2005 Vincent Hanquez -# Copyright (C) 2005-2007 Nikos Kouremenos -# Copyright (C) 2006 Travis Shirk -# -# 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; version 3 only. -# -# 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 gi.repository import GLib -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GObject - -class CellRendererImage(Gtk.CellRendererPixbuf): - - __gproperties__ = { - 'image': (GObject.TYPE_OBJECT, 'Image', - 'Image', GObject.ParamFlags.READWRITE), - } - - def __init__(self, col_index, tv_index): - super(CellRendererImage, self).__init__() - self.image = None - self.col_index = col_index - self.tv_index = tv_index - self.iters = {} - - def do_set_property(self, pspec, value): - setattr(self, pspec.name, value) - - def do_get_property(self, pspec): - return getattr(self, pspec.name) - - def do_activate(self, *args, **kwargs): - """Renderers cannot be activated; always return True.""" - return True - - def do_editing_started(self, *args, **kwargs): - """Renderers cannot be edited; always return None.""" - return None - - def func(self, model, path, iter_, image_tree): - image, tree = image_tree - if model.get_value(iter_, self.tv_index) != image: - return - self.redraw = 1 - col = tree.get_column(self.col_index) - cell_area = tree.get_cell_area(path, col) - - tree.queue_draw_area(cell_area.x, cell_area.y, cell_area.width, - cell_area.height) - - def animation_timeout(self, tree, image): - if image.get_storage_type() != Gtk.ImageType.ANIMATION: - return - self.redraw = 0 - iter_ = self.iters[image] - timeval = GLib.TimeVal() - timeval.tv_sec = GLib.get_monotonic_time() / 1000000 - iter_.advance(timeval) - model = tree.get_model() - if model: - model.foreach(self.func, (image, tree)) - if self.redraw: - GLib.timeout_add(iter_.get_delay_time(), - self.animation_timeout, tree, image) - elif image in self.iters: - del self.iters[image] - - def do_render(self, ctx, widget, background_area, cell_area, flags): - if not self.image: - return - - if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: - if self.image not in self.iters: - if not isinstance(widget, Gtk.TreeView): - return - animation = self.image.get_animation() - timeval = GLib.TimeVal() - timeval.tv_sec = GLib.get_monotonic_time() / 1000000 - iter_ = animation.get_iter(timeval) - self.iters[self.image] = iter_ - GLib.timeout_add(iter_.get_delay_time(), self.animation_timeout, - widget, self.image) - - pix = self.iters[self.image].get_pixbuf() - elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: - pix = self.image.get_pixbuf() - else: - return - - calc_width = self.get_property('xpad') * 2 + pix.get_width() - calc_height = self.get_property('ypad') * 2 + pix.get_height() - - x_pos = cell_area.x + self.get_property('xalign') * \ - (cell_area.width - calc_width - self.get_property('xpad')) - y_pos = cell_area.y + self.get_property('yalign') * \ - (cell_area.height - calc_height - self.get_property('ypad')) - Gdk.cairo_set_source_pixbuf(ctx, pix, x_pos, y_pos) - ctx.paint() - - def do_get_preferred_height(self, widget): - """ - Return the height we need for this cell. - - Each cell is drawn individually and is only as wide as it needs - to be, we let the TreeViewColumn take care of making them all - line up. - """ - if not self.image: - return 0, 0 - if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: - animation = self.image.get_animation() - timeval = GLib.TimeVal() - timeval.tv_sec = GLib.get_monotonic_time() / 1000000 - pix = animation.get_iter(timeval).get_pixbuf() - elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: - pix = self.image.get_pixbuf() - else: - return 0, 0, 0, 0 - calc_height = self.get_property('ypad') * 2 + pix.get_height() - return calc_height, calc_height - - def do_get_preferred_width(self, widget): - """ - Return the width we need for this cell. - - Each cell is drawn individually and is only as wide as it needs - to be, we let the TreeViewColumn take care of making them all - line up. - """ - if not self.image: - return 0, 0 - if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: - animation = self.image.get_animation() - timeval = GLib.TimeVal() - timeval.tv_sec = GLib.get_monotonic_time() / 1000000 - pix = animation.get_iter(timeval).get_pixbuf() - elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: - pix = self.image.get_pixbuf() - else: - return 0, 0, 0, 0 - calc_width = self.get_property('xpad') * 2 + pix.get_width() - return calc_width, calc_width diff --git a/gajim/common/helpers.py b/gajim/common/helpers.py index bc6baff40..2a056cc78 100644 --- a/gajim/common/helpers.py +++ b/gajim/common/helpers.py @@ -824,8 +824,8 @@ def get_icon_name_to_show(contact, account=None): return 'event' if account and contact.jid in app.gc_connected[account]: if app.gc_connected[account][contact.jid]: - return 'muc_active' - return 'muc_inactive' + return 'muc-active' + return 'muc-inactive' if contact.jid.find('@') <= 0: # if not '@' or '@' starts the jid ==> agent return contact.show if contact.sub in ('both', 'to'): @@ -837,7 +837,7 @@ def get_icon_name_to_show(contact, account=None): return contact.show if contact.show in app.SHOW_LIST: return contact.show - return 'not in roster' + return 'notinroster' def get_full_jid_from_iq(iq_obj): """ diff --git a/gajim/gtk/util.py b/gajim/gtk/util.py index ff9367085..fb4df6742 100644 --- a/gajim/gtk/util.py +++ b/gajim/gtk/util.py @@ -25,6 +25,7 @@ import xml.etree.ElementTree as ET from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib +import cairo from gajim.common import app from gajim.common import configpaths @@ -284,3 +285,25 @@ def get_monitor_scale_factor() -> int: log.warning('Could not determine scale factor') return 1 return monitor.get_scale_factor() + + +def get_metacontact_surface(icon_name, expanded, scale): + icon_size = 16 + state_surface = _icon_theme.load_surface( + icon_name, icon_size, scale, None, 0) + if 'event' in icon_name: + return state_surface + + if expanded: + icon = get_icon_name('opened') + expanded_surface = _icon_theme.load_surface( + icon, icon_size, scale, None, 0) + else: + icon = get_icon_name('closed') + expanded_surface = _icon_theme.load_surface( + icon, icon_size, scale, None, 0) + ctx = cairo.Context(state_surface) + ctx.rectangle(0, 0, icon_size, icon_size) + ctx.set_source_surface(expanded_surface) + ctx.fill() + return state_surface diff --git a/gajim/roster_window.py b/gajim/roster_window.py index b4d3f3914..ee424bba8 100644 --- a/gajim/roster_window.py +++ b/gajim/roster_window.py @@ -48,7 +48,6 @@ from gajim import dialogs from gajim import vcard from gajim import gtkgui_helpers from gajim import gui_menu_builder -from gajim import cell_renderer_image from gajim import message_control from gajim.common import app @@ -84,6 +83,7 @@ from gajim.gtk.adhoc_commands import CommandWindow from gajim.gtk.util import get_icon_name from gajim.gtk.util import resize_window from gajim.gtk.util import move_window +from gajim.gtk.util import get_metacontact_surface log = logging.getLogger('gajim.roster') @@ -282,8 +282,7 @@ class RosterWindow: if self.regroup: # Merged accounts view show = helpers.get_global_show() - it = self.model.append(None, [ - app.interface.jabber_state_images['16'][show], + it = self.model.append(None, [get_icon_name(show), _('Merged accounts'), 'account', '', 'all', None, None, None, None, None, None, True] + [None] * self.nb_ext_renderers) self._iters['MERGED']['account'] = it @@ -295,8 +294,7 @@ class RosterWindow: if app.account_is_securely_connected(account): tls_pixbuf = 'changes-prevent' - it = self.model.append(None, [ - app.interface.jabber_state_images['16'][show], + it = self.model.append(None, [get_icon_name(show), GLib.markup_escape_text(account), 'account', our_jid, account, None, None, None, None, None, tls_pixbuf, True] + [None] * self.nb_ext_renderers) @@ -356,7 +354,7 @@ class RosterWindow: else: iter_parent = self._get_account_iter(account, self.model) iter_group = self.model.append(iter_parent, - [app.interface.jabber_state_images['16']['closed'], + [get_icon_name('closed'), GLib.markup_escape_text(group), 'group', group, account, None, None, None, None, None, None, False] + [None] * self.nb_ext_renderers) self.draw_group(group, account) @@ -1266,7 +1264,7 @@ class RosterWindow: # look if another resource has awaiting events for c in contact_instances: c_icon_name = helpers.get_icon_name_to_show(c, account) - if c_icon_name in ('event', 'muc_active', 'muc_inactive'): + if c_icon_name in ('event', 'muc-active', 'muc-inactive'): icon_name = c_icon_name break @@ -1303,32 +1301,27 @@ class RosterWindow: iterC = self.model.iter_next(iterC) if self.tree.row_expanded(path): - state_images = self.get_appropriate_state_images( - jid, size='opened', - icon_name=icon_name) + icon_name += ':opened' else: - state_images = self.get_appropriate_state_images( - jid, size='closed', - icon_name=icon_name) + icon_name += ':closed' - # Expand/collapse icon might differ per iter - # (group) - img = state_images[icon_name] - self.model[child_iter][Column.IMG] = img + theme_icon = get_icon_name(icon_name) + self.model[child_iter][Column.IMG] = theme_icon self.model[child_iter][Column.NAME] = name #TODO: compute visible visible = True self.model[child_iter][Column.VISIBLE] = visible else: # A normal contact or little brother - state_images = self.get_appropriate_state_images(jid, - icon_name=icon_name) + transport = app.get_transport_name_from_jid(jid) + if transport == 'jabber': + transport = None + theme_icon = get_icon_name(icon_name, transport=transport) visible = self.contact_is_visible(contact, account) # All iters have the same icon (no expand/collapse) - img = state_images[icon_name] for child_iter in child_iters: - self.model[child_iter][Column.IMG] = img + self.model[child_iter][Column.IMG] = theme_icon self.model[child_iter][Column.NAME] = name self.model[child_iter][Column.VISIBLE] = visible if visible: @@ -2095,8 +2088,7 @@ class RosterWindow: def set_state(self, account, state): child_iterA = self._get_account_iter(account, self.model) if child_iterA: - self.model[child_iterA][0] = \ - app.interface.jabber_state_images['16'][state] + self.model[child_iterA][0] = get_icon_name(state) if app.interface.systray_enabled: app.interface.systray.change_status(state) @@ -3861,8 +3853,7 @@ class RosterWindow: type_ = model[titer][Column.TYPE] if type_ == 'group': group = model[titer][Column.JID] - child_model[child_iter][Column.IMG] = \ - app.interface.jabber_state_images['16']['opened'] + child_model[child_iter][Column.IMG] = get_icon_name('opened') if self.rfilter_enabled: return for account in accounts: @@ -3924,8 +3915,7 @@ class RosterWindow: type_ = model[titer][Column.TYPE] if type_ == 'group': - child_model[child_iter][Column.IMG] = app.interface.\ - jabber_state_images['16']['closed'] + child_model[child_iter][Column.IMG] = get_icon_name('closed') if self.rfilter_enabled: return group = model[titer][Column.JID] @@ -4647,8 +4637,7 @@ class RosterWindow: show = app.SHOW_LIST[status] else: # accounts merged show = helpers.get_global_show() - self.model[child_iterA][Column.IMG] = app.interface.jabber_state_images[ - '16'][show] + self.model[child_iterA][Column.IMG] = get_icon_name(show) ################################################################################ ### Style and theme related methods @@ -4714,6 +4703,17 @@ class RosterWindow: """ When a row is added, set properties for icon renderer """ + icon_name = model[titer][Column.IMG] + if ':' in icon_name: + icon_name, expanded = icon_name.split(':') + surface = get_metacontact_surface( + icon_name, expanded == 'opened', self.scale_factor) + renderer.set_property('icon_name', None) + renderer.set_property('surface', surface) + else: + renderer.set_property('surface', None) + renderer.set_property('icon_name', icon_name) + try: type_ = model[titer][Column.TYPE] except TypeError: @@ -4727,7 +4727,7 @@ class RosterWindow: if model[parent_iter][Column.TYPE] == 'group': renderer.set_property('xalign', 0.4) else: - renderer.set_property('xalign', 0.2) + renderer.set_property('xalign', 0.6) elif type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: @@ -5652,7 +5652,7 @@ class RosterWindow: # [icon, name, type, jid, account, editable, mood_pixbuf, # activity_pixbuf, TUNE_ICON, LOCATION_ICON, avatar_img, # padlock_pixbuf, visible] - self.columns = [Gtk.Image, str, str, str, str, + self.columns = [str, str, str, str, str, GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, str, str, Gtk.Image, str, bool] @@ -5773,8 +5773,8 @@ class RosterWindow: add_avatar_renderer() self.renderers_list += ( - ('icon', cell_renderer_image.CellRendererImage(0, 0), False, - 'image', Column.IMG, self._iconCellDataFunc, None), + ('icon', Gtk.CellRendererPixbuf(), False, + 'icon_name', Column.IMG, self._iconCellDataFunc, None), ('name', renderer_text, True, 'markup', Column.NAME, self._nameCellDataFunc, None),