Roster: Use icons from IconTheme for Roster
With this Gajim loses the ability to draw animated GIFs in the Roster GIFs have numerous drawbacks: - We cant add them to the IconTheme, which means we need a different interface to load them - The IconTheme scales all icons we load for the current scale (HiDPI) - The animation causes many updates to the Roster, and causes high cpu usage Fixes #8814, #8655
This commit is contained in:
parent
8be5562b92
commit
acc89ad622
|
@ -1,155 +0,0 @@
|
||||||
# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
||||||
# Copyright (C) 2005 Vincent Hanquez <tab AT snarc.org>
|
|
||||||
# Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
|
|
||||||
# Copyright (C) 2006 Travis Shirk <travis AT pobox.com>
|
|
||||||
#
|
|
||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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
|
|
|
@ -824,8 +824,8 @@ def get_icon_name_to_show(contact, account=None):
|
||||||
return 'event'
|
return 'event'
|
||||||
if account and contact.jid in app.gc_connected[account]:
|
if account and contact.jid in app.gc_connected[account]:
|
||||||
if app.gc_connected[account][contact.jid]:
|
if app.gc_connected[account][contact.jid]:
|
||||||
return 'muc_active'
|
return 'muc-active'
|
||||||
return 'muc_inactive'
|
return 'muc-inactive'
|
||||||
if contact.jid.find('@') <= 0: # if not '@' or '@' starts the jid ==> agent
|
if contact.jid.find('@') <= 0: # if not '@' or '@' starts the jid ==> agent
|
||||||
return contact.show
|
return contact.show
|
||||||
if contact.sub in ('both', 'to'):
|
if contact.sub in ('both', 'to'):
|
||||||
|
@ -837,7 +837,7 @@ def get_icon_name_to_show(contact, account=None):
|
||||||
return contact.show
|
return contact.show
|
||||||
if contact.show in app.SHOW_LIST:
|
if contact.show in app.SHOW_LIST:
|
||||||
return contact.show
|
return contact.show
|
||||||
return 'not in roster'
|
return 'notinroster'
|
||||||
|
|
||||||
def get_full_jid_from_iq(iq_obj):
|
def get_full_jid_from_iq(iq_obj):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -25,6 +25,7 @@ import xml.etree.ElementTree as ET
|
||||||
from gi.repository import Gdk
|
from gi.repository import Gdk
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
|
import cairo
|
||||||
|
|
||||||
from gajim.common import app
|
from gajim.common import app
|
||||||
from gajim.common import configpaths
|
from gajim.common import configpaths
|
||||||
|
@ -284,3 +285,25 @@ def get_monitor_scale_factor() -> int:
|
||||||
log.warning('Could not determine scale factor')
|
log.warning('Could not determine scale factor')
|
||||||
return 1
|
return 1
|
||||||
return monitor.get_scale_factor()
|
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
|
||||||
|
|
|
@ -48,7 +48,6 @@ from gajim import dialogs
|
||||||
from gajim import vcard
|
from gajim import vcard
|
||||||
from gajim import gtkgui_helpers
|
from gajim import gtkgui_helpers
|
||||||
from gajim import gui_menu_builder
|
from gajim import gui_menu_builder
|
||||||
from gajim import cell_renderer_image
|
|
||||||
from gajim import message_control
|
from gajim import message_control
|
||||||
|
|
||||||
from gajim.common import app
|
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 get_icon_name
|
||||||
from gajim.gtk.util import resize_window
|
from gajim.gtk.util import resize_window
|
||||||
from gajim.gtk.util import move_window
|
from gajim.gtk.util import move_window
|
||||||
|
from gajim.gtk.util import get_metacontact_surface
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('gajim.roster')
|
log = logging.getLogger('gajim.roster')
|
||||||
|
@ -282,8 +282,7 @@ class RosterWindow:
|
||||||
if self.regroup:
|
if self.regroup:
|
||||||
# Merged accounts view
|
# Merged accounts view
|
||||||
show = helpers.get_global_show()
|
show = helpers.get_global_show()
|
||||||
it = self.model.append(None, [
|
it = self.model.append(None, [get_icon_name(show),
|
||||||
app.interface.jabber_state_images['16'][show],
|
|
||||||
_('Merged accounts'), 'account', '', 'all', None, None, None,
|
_('Merged accounts'), 'account', '', 'all', None, None, None,
|
||||||
None, None, None, True] + [None] * self.nb_ext_renderers)
|
None, None, None, True] + [None] * self.nb_ext_renderers)
|
||||||
self._iters['MERGED']['account'] = it
|
self._iters['MERGED']['account'] = it
|
||||||
|
@ -295,8 +294,7 @@ class RosterWindow:
|
||||||
if app.account_is_securely_connected(account):
|
if app.account_is_securely_connected(account):
|
||||||
tls_pixbuf = 'changes-prevent'
|
tls_pixbuf = 'changes-prevent'
|
||||||
|
|
||||||
it = self.model.append(None, [
|
it = self.model.append(None, [get_icon_name(show),
|
||||||
app.interface.jabber_state_images['16'][show],
|
|
||||||
GLib.markup_escape_text(account), 'account', our_jid,
|
GLib.markup_escape_text(account), 'account', our_jid,
|
||||||
account, None, None, None, None, None, tls_pixbuf, True] +
|
account, None, None, None, None, None, tls_pixbuf, True] +
|
||||||
[None] * self.nb_ext_renderers)
|
[None] * self.nb_ext_renderers)
|
||||||
|
@ -356,7 +354,7 @@ class RosterWindow:
|
||||||
else:
|
else:
|
||||||
iter_parent = self._get_account_iter(account, self.model)
|
iter_parent = self._get_account_iter(account, self.model)
|
||||||
iter_group = self.model.append(iter_parent,
|
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,
|
GLib.markup_escape_text(group), 'group', group, account, None,
|
||||||
None, None, None, None, None, False] + [None] * self.nb_ext_renderers)
|
None, None, None, None, None, False] + [None] * self.nb_ext_renderers)
|
||||||
self.draw_group(group, account)
|
self.draw_group(group, account)
|
||||||
|
@ -1266,7 +1264,7 @@ class RosterWindow:
|
||||||
# look if another resource has awaiting events
|
# look if another resource has awaiting events
|
||||||
for c in contact_instances:
|
for c in contact_instances:
|
||||||
c_icon_name = helpers.get_icon_name_to_show(c, account)
|
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
|
icon_name = c_icon_name
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1303,32 +1301,27 @@ class RosterWindow:
|
||||||
iterC = self.model.iter_next(iterC)
|
iterC = self.model.iter_next(iterC)
|
||||||
|
|
||||||
if self.tree.row_expanded(path):
|
if self.tree.row_expanded(path):
|
||||||
state_images = self.get_appropriate_state_images(
|
icon_name += ':opened'
|
||||||
jid, size='opened',
|
|
||||||
icon_name=icon_name)
|
|
||||||
else:
|
else:
|
||||||
state_images = self.get_appropriate_state_images(
|
icon_name += ':closed'
|
||||||
jid, size='closed',
|
|
||||||
icon_name=icon_name)
|
|
||||||
|
|
||||||
# Expand/collapse icon might differ per iter
|
theme_icon = get_icon_name(icon_name)
|
||||||
# (group)
|
self.model[child_iter][Column.IMG] = theme_icon
|
||||||
img = state_images[icon_name]
|
|
||||||
self.model[child_iter][Column.IMG] = img
|
|
||||||
self.model[child_iter][Column.NAME] = name
|
self.model[child_iter][Column.NAME] = name
|
||||||
#TODO: compute visible
|
#TODO: compute visible
|
||||||
visible = True
|
visible = True
|
||||||
self.model[child_iter][Column.VISIBLE] = visible
|
self.model[child_iter][Column.VISIBLE] = visible
|
||||||
else:
|
else:
|
||||||
# A normal contact or little brother
|
# A normal contact or little brother
|
||||||
state_images = self.get_appropriate_state_images(jid,
|
transport = app.get_transport_name_from_jid(jid)
|
||||||
icon_name=icon_name)
|
if transport == 'jabber':
|
||||||
|
transport = None
|
||||||
|
theme_icon = get_icon_name(icon_name, transport=transport)
|
||||||
|
|
||||||
visible = self.contact_is_visible(contact, account)
|
visible = self.contact_is_visible(contact, account)
|
||||||
# All iters have the same icon (no expand/collapse)
|
# All iters have the same icon (no expand/collapse)
|
||||||
img = state_images[icon_name]
|
|
||||||
for child_iter in child_iters:
|
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.NAME] = name
|
||||||
self.model[child_iter][Column.VISIBLE] = visible
|
self.model[child_iter][Column.VISIBLE] = visible
|
||||||
if visible:
|
if visible:
|
||||||
|
@ -2095,8 +2088,7 @@ class RosterWindow:
|
||||||
def set_state(self, account, state):
|
def set_state(self, account, state):
|
||||||
child_iterA = self._get_account_iter(account, self.model)
|
child_iterA = self._get_account_iter(account, self.model)
|
||||||
if child_iterA:
|
if child_iterA:
|
||||||
self.model[child_iterA][0] = \
|
self.model[child_iterA][0] = get_icon_name(state)
|
||||||
app.interface.jabber_state_images['16'][state]
|
|
||||||
if app.interface.systray_enabled:
|
if app.interface.systray_enabled:
|
||||||
app.interface.systray.change_status(state)
|
app.interface.systray.change_status(state)
|
||||||
|
|
||||||
|
@ -3861,8 +3853,7 @@ class RosterWindow:
|
||||||
type_ = model[titer][Column.TYPE]
|
type_ = model[titer][Column.TYPE]
|
||||||
if type_ == 'group':
|
if type_ == 'group':
|
||||||
group = model[titer][Column.JID]
|
group = model[titer][Column.JID]
|
||||||
child_model[child_iter][Column.IMG] = \
|
child_model[child_iter][Column.IMG] = get_icon_name('opened')
|
||||||
app.interface.jabber_state_images['16']['opened']
|
|
||||||
if self.rfilter_enabled:
|
if self.rfilter_enabled:
|
||||||
return
|
return
|
||||||
for account in accounts:
|
for account in accounts:
|
||||||
|
@ -3924,8 +3915,7 @@ class RosterWindow:
|
||||||
|
|
||||||
type_ = model[titer][Column.TYPE]
|
type_ = model[titer][Column.TYPE]
|
||||||
if type_ == 'group':
|
if type_ == 'group':
|
||||||
child_model[child_iter][Column.IMG] = app.interface.\
|
child_model[child_iter][Column.IMG] = get_icon_name('closed')
|
||||||
jabber_state_images['16']['closed']
|
|
||||||
if self.rfilter_enabled:
|
if self.rfilter_enabled:
|
||||||
return
|
return
|
||||||
group = model[titer][Column.JID]
|
group = model[titer][Column.JID]
|
||||||
|
@ -4647,8 +4637,7 @@ class RosterWindow:
|
||||||
show = app.SHOW_LIST[status]
|
show = app.SHOW_LIST[status]
|
||||||
else: # accounts merged
|
else: # accounts merged
|
||||||
show = helpers.get_global_show()
|
show = helpers.get_global_show()
|
||||||
self.model[child_iterA][Column.IMG] = app.interface.jabber_state_images[
|
self.model[child_iterA][Column.IMG] = get_icon_name(show)
|
||||||
'16'][show]
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
### Style and theme related methods
|
### Style and theme related methods
|
||||||
|
@ -4714,6 +4703,17 @@ class RosterWindow:
|
||||||
"""
|
"""
|
||||||
When a row is added, set properties for icon renderer
|
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:
|
try:
|
||||||
type_ = model[titer][Column.TYPE]
|
type_ = model[titer][Column.TYPE]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -4727,7 +4727,7 @@ class RosterWindow:
|
||||||
if model[parent_iter][Column.TYPE] == 'group':
|
if model[parent_iter][Column.TYPE] == 'group':
|
||||||
renderer.set_property('xalign', 0.4)
|
renderer.set_property('xalign', 0.4)
|
||||||
else:
|
else:
|
||||||
renderer.set_property('xalign', 0.2)
|
renderer.set_property('xalign', 0.6)
|
||||||
elif type_:
|
elif type_:
|
||||||
# prevent type_ = None, see http://trac.gajim.org/ticket/2534
|
# prevent type_ = None, see http://trac.gajim.org/ticket/2534
|
||||||
if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]:
|
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,
|
# [icon, name, type, jid, account, editable, mood_pixbuf,
|
||||||
# activity_pixbuf, TUNE_ICON, LOCATION_ICON, avatar_img,
|
# activity_pixbuf, TUNE_ICON, LOCATION_ICON, avatar_img,
|
||||||
# padlock_pixbuf, visible]
|
# padlock_pixbuf, visible]
|
||||||
self.columns = [Gtk.Image, str, str, str, str,
|
self.columns = [str, str, str, str, str,
|
||||||
GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, str, str,
|
GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, str, str,
|
||||||
Gtk.Image, str, bool]
|
Gtk.Image, str, bool]
|
||||||
|
|
||||||
|
@ -5773,8 +5773,8 @@ class RosterWindow:
|
||||||
add_avatar_renderer()
|
add_avatar_renderer()
|
||||||
|
|
||||||
self.renderers_list += (
|
self.renderers_list += (
|
||||||
('icon', cell_renderer_image.CellRendererImage(0, 0), False,
|
('icon', Gtk.CellRendererPixbuf(), False,
|
||||||
'image', Column.IMG, self._iconCellDataFunc, None),
|
'icon_name', Column.IMG, self._iconCellDataFunc, None),
|
||||||
|
|
||||||
('name', renderer_text, True,
|
('name', renderer_text, True,
|
||||||
'markup', Column.NAME, self._nameCellDataFunc, None),
|
'markup', Column.NAME, self._nameCellDataFunc, None),
|
||||||
|
|
Loading…
Reference in New Issue