Add button to list view

This commit is contained in:
Cédric Krier
2008-08-26 10:24:51 +02:00
parent 5923c2b37b
commit fc4fa69ce0
5 changed files with 201 additions and 7 deletions
+76
View File
@@ -0,0 +1,76 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms.
import gtk
import gobject
import pango
class CellRendererButton(gtk.GenericCellRenderer):
#TODO Add keyboard editing
__gproperties__ = {
"text": (gobject.TYPE_STRING, None, "Text",
"Displayed text", gobject.PARAM_READWRITE),
}
__gsignals__ = {
'clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING, )),
}
def __init__(self, text=""):
self.__gobject_init__()
self.text = text
self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE)
self.clicking = False
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def on_render(self, window, widget, background_area, cell_area,
expose_area, flags):
state = gtk.STATE_NORMAL
shadow = gtk.SHADOW_OUT
if self.clicking and flags & gtk.CELL_RENDERER_SELECTED:
state = gtk.STATE_ACTIVE
shadow = gtk.SHADOW_IN
widget.style.paint_box(window, state, shadow,
None, widget, "button",
cell_area.x, cell_area.y,
cell_area.width, cell_area.height)
layout = widget.create_pango_layout('')
layout.set_font_description(widget.style.font_desc)
w, h = layout.get_size()
x = cell_area.x
y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2)
window.draw_layout(widget.style.text_gc[0], x, y, layout)
layout = widget.create_pango_layout(self.text)
layout.set_font_description(widget.style.font_desc)
w, h = layout.get_size()
x = cell_area.x + 3
y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2)
window.draw_layout(widget.style.text_gc[0], x, y, layout)
def on_get_size(self, widget, cell_area=None):
if cell_area is None:
return (0, 0, 30, 18)
else:
return (cell_area.x, cell_area.y, cell_area.width, cell_area.height)
def on_start_editing(self, event, widget, path, background_area,
cell_area, flags):
if event is not None and ((event.type == gtk.gdk.BUTTON_PRESS) \
or (event.type == gtk.gdk.KEY_PRESS \
and event.keyval == gtk.keysyms.space)):
self.clicking = True
widget.queue_draw()
gtk.main_iteration()
self.emit("clicked", path)
def timeout(self, widget):
self.clicking = False
widget.queue_draw()
gobject.timeout_add(60, timeout, self, widget)
gobject.type_register(CellRendererButton)
+5 -2
View File
@@ -10,6 +10,7 @@ from tryton.common import message
import gettext
import tryton.common as common
from tryton.config import CONFIG
from tryton.common.cellrendererbutton import CellRendererButton
_ = gettext.gettext
@@ -507,7 +508,8 @@ class ViewList(ParserView):
renderer = renderers[0]
if isinstance(renderer, gtk.CellRendererToggle):
editable = renderer.get_property('activatable')
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
editable = False
else:
editable = renderer.get_property('editable')
@@ -540,7 +542,8 @@ class ViewList(ParserView):
for renderer in col.get_cell_renderers():
if isinstance(renderer, gtk.CellRendererToggle):
renderer.set_property('activatable', False)
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
pass
else:
renderer.set_property('editable', False)
@@ -2,6 +2,7 @@
import gtk
import parser
import gettext
from tryton.common.cellrendererbutton import CellRendererButton
_ = gettext.gettext
@@ -74,7 +75,8 @@ class EditableTreeView(gtk.TreeView):
renderer = cols[idx].get_cell_renderers()[0]
if isinstance(renderer, gtk.CellRendererToggle):
editable = renderer.get_property('activatable')
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
editable = False
else:
editable = renderer.get_property('editable')
@@ -90,7 +92,8 @@ class EditableTreeView(gtk.TreeView):
renderer = cols[idx].get_cell_renderers()[0]
if isinstance(renderer, gtk.CellRendererToggle):
editable = renderer.get_property('activatable')
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
editable = False
else:
editable = renderer.get_property('editable')
@@ -187,7 +190,8 @@ class EditableTreeView(gtk.TreeView):
renderer = column.get_cell_renderers()[0]
if isinstance(renderer, gtk.CellRendererToggle):
editable = renderer.get_property('activatable')
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
editable = False
else:
editable = renderer.get_property('editable')
@@ -20,6 +20,8 @@ import datetime as DT
from tryton.common import DT_FORMAT, DHM_FORMAT, COLORS, node_attributes, TRYTON_ICON
import tryton.common as common
from _strptime import LocaleTime
from tryton.common.cellrendererbutton import CellRendererButton
from tryton.action import Action
def send_keys(renderer, editable, position, treeview):
editable.connect('key_press_event', treeview.on_keypressed)
@@ -61,6 +63,7 @@ class ParserTree(ParserInterface):
def parse(self, model, root_node, fields):
dict_widget = {}
button_list = []
attrs = node_attributes(root_node)
on_write = attrs.get('on_write', '')
editable = attrs.get('editable', False)
@@ -101,7 +104,8 @@ class ParserTree(ParserInterface):
if editable and not node_attrs.get('readonly', False):
if isinstance(renderer, gtk.CellRendererToggle):
renderer.set_property('activatable', True)
elif isinstance(renderer, gtk.CellRendererProgress):
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton)):
pass
else:
renderer.set_property('editable', True)
@@ -179,6 +183,38 @@ class ParserTree(ParserInterface):
digits = fields.get('digits', (16, 2))[1]
dict_widget[i] = (fname, label, label_sum, digits,
label_bold)
elif node.localName == 'button':
#TODO add shortcut
cell = Button(treeview, node_attrs, self.window, self.screen)
button_list.append(cell)
renderer = cell.renderer
string = node_attrs.get('string', _('Unknown'))
col = gtk.TreeViewColumn(string, renderer)
col.name = None
label = gtk.Label(string)
label.show()
help = string
if node_attrs.get('help'):
help += '\n' + node_attrs['help']
tooltips.set_tip(label, help)
tooltips.enable()
arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_IN)
col.arrow = arrow
col.arrow_show = False
col.set_widget(label)
col._type = 'button'
if 'width' in node_attrs:
width = int(node_attrs['width'])
else:
width = 80
col.width = width
if width > 0:
col.set_fixed_width(width)
col.set_resizable(True)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
i = treeview.append_column(col)
if not bool(int(attrs.get('fill', '0'))):
col = gtk.TreeViewColumn()
col.name = None
@@ -188,7 +224,7 @@ class ParserTree(ParserInterface):
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
treeview.append_column(col)
treeview.set_fixed_height_mode(True)
return treeview, dict_widget, [], on_write, [], None
return treeview, dict_widget, button_list, on_write, [], None
class Char(object):
@@ -633,6 +669,79 @@ class ProgressBar(object):
def value_from_text(self, model, text):
return float(text)
class Button(object):
def __init__(self, treeview=None, attrs=None, window=None, screen=None):
super(Button, self).__init__()
self.attrs = attrs or {}
self.renderer = CellRendererButton(attrs.get('string', _('Unknown')))
self.treeview = treeview
self.window = window
self.screen = screen
self.renderer.connect('clicked', self.button_clicked)
def button_clicked(self, widget, path):
if not path:
return True
store = self.treeview.get_model()
model = store.get_value(store.get_iter(path), 0)
state_changes = self.attrs.get('states', {})
if isinstance(state_changes, basestring):
state_changes = eval(state_changes)
if 'invisible' in state_changes:
if model.expr_eval(state_changes['invisible'], check_load=False):
return True
if 'readonly' in state_changes:
if model.expr_eval(state_changes['readonly'], check_load=False):
return True
self.screen.current_model = model
obj_id = self.screen.save_current()
if obj_id:
if not self.attrs.get('confirm', False) or \
common.sur(self.attrs['confirm'], self.window):
button_type = self.attrs.get('type', 'workflow')
if button_type == 'workflow':
args = ('object', 'exec_workflow', self.screen.name,
self.attrs['name'], obj_id)
try:
rpc.execute(*args)
except Exception, exception:
common.process_exception(exception, self.window, *args)
elif button_type == 'object':
args = ('object', 'execute', self.screen.name,
self.attrs['name'], [obj_id], model.context_get())
try:
rpc.execute(*args)
except Exception, exception:
common.process_exception(exception, self.window, *args)
elif button_type == 'action':
action_id = None
args = ('object', 'execute', 'ir.action', 'get_action_id',
int(self.attrs['name']), rpc.CONTEXT)
try:
action_id = rpc.execute(*args)
except Exception, exception:
action_id = common.process_exception(exception,
self.window, *args)
if action_id:
Action.execute(action_id, {
'model': self.screen.name,
'id': obj_id,
'ids': [obj_id],
}, self.window)
else:
raise Exception('Unallowed button type')
self.screen.reload()
else:
if self.screen.form:
self.screen.form.message_info(
_('Invalid Form, correct red fields!'))
self.screen.display()
CELLTYPES = {
'char': Char,
'many2one': M2O,
+2
View File
@@ -61,6 +61,8 @@ class Parse(object):
column.set_resizable(True)
column.set_visible(not attrs.get('tree_invisible', False))
self.tree.append_column(column)
elif name == 'button':
pass
else:
import logging
log = logging.getLogger('view')