#
# checklist.py: A class (derived from GtkTreeView) that provides a list of
# checkbox / text string pairs
#
# Copyright (C) 2000, 2001 Red Hat, Inc. All rights reserved.
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program. If not, see .
#
# Author(s): Brent Fox
# Jeremy Katz
#
import gtk
import gobject
class CheckList (gtk.TreeView):
"""A class (derived from gtk.TreeView) that provides a list of
checkbox / text string pairs"""
# override this to make your own columns if necessary
def create_columns(self, columns):
# add the string columns to the tree view widget
for i in range(1, columns + 1):
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn('Text', renderer, text=i,
**self.sensitivity_args)
column.set_clickable(False)
self.append_column(column)
# XXX need to handle the multicolumn case better still....
def __init__ (self, columns = 1, custom_store=None, sensitivity=False):
if custom_store is None:
self.store = gtk.TreeStore(gobject.TYPE_BOOLEAN,
gobject.TYPE_STRING,
gobject.TYPE_STRING)
else:
self.store = custom_store
gtk.TreeView.__init__ (self, self.store)
# XXX we only handle two text columns right now
if custom_store is None and columns > 2:
raise RuntimeError, "CheckList supports a maximum of 2 columns"
self.columns = columns
# sensitivity_col is an optional hidden boolean column that controls
# the sensitive property of all of the CellRenderers in its row.
#
# To enable this functionality the last column in the TreeStore
# must be boolean and you must pass a value of True for the
# 'sensitivity' keyword argument to this class' constructor.
self.sensitivity_col = None
self.sensitivity_args = {}
last_col = self.store.get_n_columns() - 1
if sensitivity and \
self.store.get_column_type(last_col) == gobject.TYPE_BOOLEAN:
self.sensitivity_col = last_col
self.sensitivity_args = {"sensitive": self.sensitivity_col}
self.checkboxrenderer = gtk.CellRendererToggle()
column = gtk.TreeViewColumn('', self.checkboxrenderer, active=0,
**self.sensitivity_args)
# column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
# column.set_fixed_width(40)
column.set_clickable(True)
self.checkboxrenderer.connect ("toggled", self.toggled_item)
self.append_column(column)
self.create_columns(columns)
self.set_rules_hint(False)
self.set_headers_visible(False)
self.columns_autosize()
self.set_enable_search(False)
# keep track of the number of rows we have so we can
# iterate over them all
self.num_rows = 0
self.tiptext = {}
self.props.has_tooltip = True
self.connect("query-tooltip", self._tipQuery)
def _tipQuery(self, widget, x, y, kbd, tip, *data):
(tx, ty) = widget.convert_widget_to_bin_window_coords(x, y)
r = widget.get_path_at_pos(tx, ty)
if not r:
return False
path = r[0]
if not self.tiptext.has_key(path):
return False
tip.set_text(self.tiptext[path])
return True
def append_row (self, textList, init_value, tooltipText = None):
"""Add a row to the list.
text: text to display in the row
init_value: initial state of the indicator
tooltipText: the text that will appear when the mouse is over the row."""
iter = self.store.append(None)
self.store.set_value(iter, 0, init_value)
if self.sensitivity_col is not None:
self.store.set_value(iter, self.sensitivity_col, True)
# add the text for the number of columns we have
i = 1
for text in textList[:self.columns]:
self.store.set_value(iter, i, textList[i - 1])
i = i + 1
if tooltipText:
self.tiptext[self.store.get_path(iter)] = tooltipText
self.num_rows = self.num_rows + 1
def toggled_item(self, data, row):
"""Set a function to be called when the value of a row is toggled.
The function will be called with two arguments, the clicked item
in the row and a string for which row was clicked."""
iter = self.store.get_iter((int(row),))
val = self.store.get_value(iter, 0)
self.store.set_value(iter, 0, not val)
def clear (self):
"Remove all rows"
self.store.clear()
self.num_rows = 0
def get_active(self, row):
"""Return FALSE or TRUE as to whether or not the row is toggled
similar to GtkToggleButtons"""
iter = self.store.get_iter((row,))
return self.store.get_value(iter, 0)
def set_active(self, row, is_active):
"Set row to be is_active, similar to GtkToggleButton"
iter = self.store.get_iter((row,))
self.store.set_value(iter, 0, is_active)
def get_text(self, row, column):
"Get the text from row and column"
iter = self.store.get_iter((row,))
return self.store.get_value(iter, column)
def set_column_title(self, column, title):
"Set the title of column to title"
col = self.get_column(column)
if col:
col.set_title(title)
def set_column_min_width(self, column, min):
"Set the minimum width of column to min"
col = self.get_column(column)
if col:
col.set_min_width(min)
def set_column_clickable(self, column, clickable):
"Set the column to be clickable"
col = self.get_column(column)
if col:
col.set_clickable(clickable)
def set_column_sizing(self, column, sizing):
"Set the column to use the given sizing method"
col = self.get_column(column)
if col:
col.set_sizing(sizing)
def set_column_sort_id(self, column, id):
"Set the sort id of column to id"
col = self.get_column(column)
if col:
col.set_sort_column_id(id)
def main():
win = gtk.Window()
cl = CheckList(1)
for i in range(1, 10):
cl.append_row("%s" %(i,), False, "foo: %d" %(i,))
sw = gtk.ScrolledWindow()
sw.set_policy (gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
sw.add (cl)
sw.set_shadow_type(gtk.SHADOW_IN)
cl.set_headers_visible(True)
win.add(sw)
win.set_size_request(250, 250)
win.show_all()
gtk.main()
if __name__ == "__main__":
main()