This commit is contained in:
Nicolas Évrard committed 2011-12-14 17:31:23 +01:00
commit c58f00cfe4
3 files changed
+202 -4

No files matched your search

+122
View File
@@ -0,0 +1,122 @@
#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
class CellRendererBinary(gtk.GenericCellRenderer):
__gproperties__ = {
'visible': (gobject.TYPE_INT, 'Visible', 'Visible', 0, 10, 0,
gobject.PARAM_READWRITE),
'editable': (gobject.TYPE_INT, 'Editable', 'Editable', 0, 10, 0,
gobject.PARAM_READWRITE),
'content': (gobject.TYPE_INT, 'Content', 'Content', 0, 10, 0,
gobject.PARAM_READWRITE),
}
__gsignals__ = {
'new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING,)),
'open': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING,)),
'save': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING,)),
'clear': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING,)),
}
def __init__(self, use_filename):
self.__gobject_init__()
self.visible = True
self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE)
self.use_filename = use_filename
if use_filename:
self.buttons = ('new', 'open', 'save', 'clear')
else:
self.buttons = ('new', 'save', 'clear')
self.clicking = ''
self.images = {}
widget = gtk.Button()
for key, stock_name in (
('new', 'tryton-find'),
('open', 'tryton-open'),
('save', 'tryton-save-as'),
('clear', 'tryton-clear')):
# hack to get gtk.gdk.Image from stock icon
img_sensitive = widget.render_icon(stock_name,
gtk.ICON_SIZE_SMALL_TOOLBAR)
img_insensitive = img_sensitive.copy()
img_sensitive.saturate_and_pixelate(img_insensitive, 0, False)
width = img_sensitive.get_width()
self.images[key] = (img_sensitive, img_insensitive, width)
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def button_width(self, cell_area):
return ((cell_area.width - (len(self.buttons) + 1) * 2)
/ len(self.buttons))
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):
button_width = self.button_width(cell_area)
for index, button_name in enumerate(self.buttons):
x_offset = button_width * index + 2 * (index + 1)
x_button = cell_area.x + x_offset
if x_button < event.x < x_button + button_width:
break
else:
button_name = None
if not self.visible or not button_name:
return
if not self.editable and button_name in ('new', 'clear'):
return
if not self.content and button_name == 'save':
return
if event is None or event.type == gtk.gdk.BUTTON_PRESS:
self.clicking = button_name
self.emit(button_name, path)
def timeout(self, widget):
self.clicking = ''
widget.queue_draw()
gobject.timeout_add(60, timeout, self, widget)
def on_render(self, window, widget, background_area, cell_area,
expose_area, flags):
if not self.visible:
return
# Handle Pixmap window as pygtk failed
if type(window) == gtk.gdk.Pixmap:
return
button_width = self.button_width(cell_area)
for index, button_name in enumerate(self.buttons):
state = gtk.STATE_NORMAL
shadow = gtk.SHADOW_OUT
pxbf_sens, pxbf_insens, pxbf_width = self.images[button_name]
if self.clicking and flags & gtk.CELL_RENDERER_SELECTED:
state = gtk.STATE_ACTIVE
shadow = gtk.SHADOW_IN
if (not self.editable and button_name in ('new', 'clear')
or not self.content and button_name in ('open', 'save')):
state = gtk.STATE_INSENSITIVE
pixbuf = pxbf_insens
else:
pixbuf = pxbf_sens
x_offset = button_width * index + 2 * (index + 1)
widget.style.paint_box(window, state, shadow,
None, widget, "button", cell_area.x + x_offset, cell_area.y,
button_width, cell_area.height)
window.draw_pixbuf(widget.style.black_gc,
pixbuf, 0, 0,
cell_area.x + x_offset + button_width / 2 - pxbf_width / 2,
cell_area.y)
gobject.type_register(CellRendererBinary)
+2 -1
View File
@@ -17,6 +17,7 @@ import tryton.common as common
from tryton.config import CONFIG
from tryton.common.cellrendererbutton import CellRendererButton
from tryton.common.cellrenderertoggle import CellRendererToggle
from tryton.common.cellrendererbinary import CellRendererBinary
from tryton.pyson import PYSONEncoder
from tryton.gui.window import Window
from tryton.exceptions import TrytonServerError
@@ -797,7 +798,7 @@ class ViewList(ParserView):
editable = renderer.get_property('activatable')
elif isinstance(renderer,
(gtk.CellRendererProgress, CellRendererButton,
gtk.CellRendererPixbuf)):
gtk.CellRendererPixbuf, CellRendererBinary)):
editable = False
else:
editable = renderer.get_property('editable')
@@ -1,7 +1,9 @@
#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 os
import gobject
import tempfile
from editabletree import EditableTreeView
from tryton.gui.window.view_form.view.interface import ParserInterface
from tryton.gui.window.win_search import WinSearch
@@ -10,7 +12,7 @@ from tryton.gui.window.view_form.screen import Screen
from tryton.config import CONFIG
import tryton.rpc as rpc
from tryton.common import DT_FORMAT, DHM_FORMAT, COLORS, node_attributes, \
TRYTON_ICON, HM_FORMAT
TRYTON_ICON, HM_FORMAT, file_selection, file_open
import tryton.common as common
from tryton.exceptions import TrytonError, TrytonServerError
from tryton.common.cellrendererbutton import CellRendererButton
@@ -20,6 +22,7 @@ from tryton.common.cellrenderertoggle import CellRendererToggle
from tryton.common.cellrenderercombo import CellRendererCombo
from tryton.common.cellrendererinteger import CellRendererInteger
from tryton.common.cellrendererfloat import CellRendererFloat
from tryton.common.cellrendererbinary import CellRendererBinary
from tryton.action import Action
from tryton.translate import date_format
from tryton.pyson import PYSONDecoder
@@ -108,7 +111,7 @@ class ParserTree(ParserInterface):
continue
for attr_name in ('relation', 'domain', 'selection',
'relation_field', 'string', 'views', 'invisible',
'add_remove', 'sort', 'context'):
'add_remove', 'sort', 'context', 'filename'):
if attr_name in fields[fname].attrs and \
not attr_name in node_attrs:
node_attrs[attr_name] = fields[fname].attrs[attr_name]
@@ -127,7 +130,8 @@ class ParserTree(ParserInterface):
pass
else:
renderer.set_property('editable', not readonly)
if not readonly:
if (not readonly
and not isinstance(renderer, CellRendererBinary)):
renderer.connect_after('editing-started', send_keys,
treeview)
@@ -505,6 +509,76 @@ class FloatTime(Char):
if callback:
callback()
class Binary(Char):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Binary, self).__init__(field_name, model_name, treeview,
attrs=attrs)
self.filename = attrs.get('filename')
self.renderer = CellRendererBinary(bool(self.filename))
self.renderer.connect('new', self.new_binary)
self.renderer.connect('open', self.open_binary)
self.renderer.connect('save', self.save_binary)
self.renderer.connect('clear', self.clear_binary)
def get_textual_value(self, record):
pass
def value_from_text(self, record, text, callback=None):
if callback:
callback()
def setter(self, column, cell, store, iter):
record = store.get_value(iter, 0)
size = record[self.field_name].get_size(record)
cell.set_property('content', bool(size))
def _get_record_field(self, path):
store = self.treeview.get_model()
record = store.get_value(store.get_iter(path), 0)
field = record.group.fields[self.field_name]
return record, field
def new_binary(self, renderer, path):
filename = file_selection(_('Open...'))
record, field = self._get_record_field(path)
if filename:
field.set_client(record, open(filename, 'rb').read())
def open_binary(self, renderer, path):
if not self.filename:
return
dtemp = tempfile.mkdtemp(prefix='tryton_')
record, field = self._get_record_field(path)
filename_field = record.group.fields.get(self.filename)
filename = filename_field.get(record).replace(
os.sep, '_').replace(os.altsep or os.sep, '_')
file_path = os.path.join(dtemp, filename)
with open(file_path, 'wb') as fp:
fp.write(field.get_data(record))
root, type_ = os.path.splitext(filename)
if type_:
type_ = type_[1:]
file_open(file_path, type_)
def save_binary(self, renderer, path):
filename = ''
record, field = self._get_record_field(path)
if self.filename:
filename_field = record.group.fields.get(self.filename)
filename = filename_field.get(record)
filename = file_selection(_('Save As...'), filename=filename,
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if filename:
with open(filename,'wb') as fp:
fp.write(field.get_data(record))
def clear_binary(self, renderer, path):
record, field = self._get_record_field(path)
field.set_client(record, False)
class M2O(Char):
def value_from_text(self, record, text, callback=None):
@@ -994,4 +1068,5 @@ CELLTYPES = {
'progressbar': ProgressBar,
'reference': Reference,
'one2one': O2O,
'binary': Binary,
}