Reputation: 12152
I want to display the status read or unread of a row by makeing the text (of a column in the row) bold or not.
The status of the row (or the data in the model) can be part of the model or somewhere else. I am flexible at this point.
How can I make the text of a specific cell bold depending on the underlying (dynamic) data, which is in this example the value 1
?
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class View(Gtk.TreeView):
def __init__(self, model):
Gtk.TreeView.__init__(self, model)
col = Gtk.TreeViewColumn('Text',
Gtk.CellRendererText(),
text=0)
self.append_column(col)
# bold text
# Gtk.CellRendererText(weight_set=True, weight=700),
class Model(Gtk.ListStore):
def __init__(self):
Gtk.ListStore.__init__(self, str, int)
self.append(['foo 1', 0])
self.append(['foo 2', 1]) # bold
self.append(['foo 3', 0])
self.append(['foo 4', 0])
self.append(['foo 5', 1]) # bold
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(100, 200)
# model & view
self.model = Model()
self.view = View(self.model)
# layout
self.layout = Gtk.Grid()
self.add(self.layout)
self.layout.attach(self.view, 0, 0, 1, 2)
self.connect('destroy', Gtk.main_quit)
self.show_all()
if __name__ == '__main__':
win = Window()
Gtk.main()
Upvotes: 3
Views: 1133
Reputation: 3307
After a short discussion with the Gtk maintainers, I've found that there is another, cleaner way to do this. Since both answers work, I've decided to put this as separate answer.
The problem with the other answer is that the cell_data_func
gets called for every row. Over time, this will get really slow if you have many rows.
The solution here is to add another column to your model that you then bind to the relevant attribute(s).
Currently, you do the following:
col = Gtk.TreeViewColumn(
'Text', renderer, text=0, weight_set=True)
This binds the text
property of the CellRenderer
to column 0 of your model.
Now, we can bind this to any other property too. For example, bind column 1 to the weight
property:
col = Gtk.TreeViewColumn(
'Text', renderer, text=0, weight=1, weight_set=True)
You can then set this column to different Pango.Weight
values to change the weight of the text.
class Model(Gtk.ListStore):
def __init__(self):
...
self.append(['foo 1', Pango.Weight.BOLD])
self.append(['foo 2', Pango.Weight.BOOK])
...
If you want to set additional properties, you can also set the markup
property (which parses the string as pango markup and allows you to change the font, color, etc of some parts of the text) and the attributes
property, which you can use to set many style attributes at once with the pango.AttrList type.
Upvotes: 4
Reputation: 3307
As is often in Gtk, this is very very simple, just not very obvious. You really need to know where to look and read the related docs carefully.
class View(Gtk.TreeView):
def __init__(self, model):
Gtk.TreeView.__init__(self, model)
renderer = Gtk.CellRendererText()
col = Gtk.TreeViewColumn(
'Text', renderer, text=0, weight_set=True)
col.set_cell_data_func(renderer, datafunc)
self.append_column(col)
The first key is the TreeViewColumn.set_cell_data_func
method. This allows you to set an intercept function that you can use to modify the properties of the cell before it is rendered. Here's an example one I wrote which does what you want:
def datafunc(col, renderer, model, titer, data):
val = model.get_value(titer, 1)
if val:
renderer.set_property("weight", 700)
As you can see, it receives the TreeViewColumn
, CellRenderer
, TreeModel
and TreeIter
involved, as well as custom data, which I've ommited.
The first step is to get the values of the current column. For that, we give the model the treeiter (which saves the "current row", kinda), and the column id we want (in this case the second column, 1
).
The rest is pretty simple, we use that value to decide if we need to set the "weight" property on the CellRenderer.
You used 700 here, but I'd recommend you to use Pango.Weight.BOLD
instead for clarity. This requires from gi.repository import Pango
of course.
Upvotes: 5