merge
This commit is contained in:
commit
ffc495daeb
16 files changed
+244
-107
No files matched your search
@@ -1,5 +1,7 @@
|
||||
* Selection widget used for many2one dynamically change their content following
|
||||
the domain specification
|
||||
* Add open button on binary and image widgets
|
||||
* Hide buttons on image widget if readonly
|
||||
* Added a connection manager à la gajim
|
||||
* Fix warning in wizards
|
||||
* Added possibility to use server-side icons
|
||||
|
||||
@@ -4,6 +4,7 @@ Copyright (C) 2007-2010 Bertrand Chenal.
|
||||
Copyright (C) 2008-2010 B2CK SPRL.
|
||||
Copyright (C) 2008-2010 Udo Spallek.
|
||||
Copyright (C) 2008-2010 virtual things - Preisler & Spallek GbR.
|
||||
Copyright (C) 2007-2009 Lorenzo Gil Sanchez.
|
||||
Copyright (C) 2004-2008 Tiny SPRL.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
||||
+10
-5
@@ -58,7 +58,7 @@ class TrytonIconFactory(gtk.IconFactory):
|
||||
continue
|
||||
try:
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(
|
||||
os.path.join(PIXMAPS_DIR, fname))
|
||||
os.path.join(PIXMAPS_DIR, fname).encode('utf-8'))
|
||||
except Exception:
|
||||
continue
|
||||
icon_set = gtk.IconSet(pixbuf)
|
||||
@@ -103,7 +103,7 @@ class TrytonIconFactory(gtk.IconFactory):
|
||||
fileno, path = tempfile.mkstemp()
|
||||
with os.fdopen(fileno, 'w') as svgfile:
|
||||
svgfile.write(icon['icon'])
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(path.encode('utf-8'))
|
||||
os.remove(path)
|
||||
iconset = gtk.IconSet(pixbuf)
|
||||
self.add(icon['name'], iconset)
|
||||
@@ -309,7 +309,8 @@ def file_selection(title, filename='', parent=None,
|
||||
def update_preview_cb(win, img):
|
||||
filename = win.get_preview_filename()
|
||||
try:
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, 128, 128)
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename.encode('utf-8'),
|
||||
128, 128)
|
||||
img.set_from_pixbuf(pixbuf)
|
||||
have_preview = True
|
||||
except Exception:
|
||||
@@ -519,7 +520,7 @@ def error(title, parent, details):
|
||||
|
||||
box = gtk.VBox()
|
||||
label_error = gtk.Label()
|
||||
label_error.set_markup('<b>' + _('Error: ') + '</b>' + title)
|
||||
label_error.set_markup('<b>' + _('Error: ') + '</b>' + to_xml(title))
|
||||
label_error.set_alignment(0, 0.5)
|
||||
label_error.set_padding(-1, 14)
|
||||
label_error.modify_font(pango.FontDescription("monospace"))
|
||||
@@ -1104,11 +1105,12 @@ class RPCProgress(object):
|
||||
def run(self):
|
||||
thread.start_new_thread(self.start, ())
|
||||
|
||||
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
|
||||
self.parent.window.set_cursor(watch)
|
||||
i = 0
|
||||
win = None
|
||||
progressbar = None
|
||||
while (not self.res) and (not self.error):
|
||||
time.sleep(0.1)
|
||||
i += 1
|
||||
if i > 10:
|
||||
if not win or not progressbar:
|
||||
@@ -1145,11 +1147,14 @@ class RPCProgress(object):
|
||||
win.set_transient_for(self.parent)
|
||||
win.set_modal(True)
|
||||
win.show_all()
|
||||
win.window.set_cursor(watch)
|
||||
with gtk.gdk.lock:
|
||||
progressbar.pulse()
|
||||
with gtk.gdk.lock:
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
time.sleep(0.1)
|
||||
self.parent.window.set_cursor(None)
|
||||
if win:
|
||||
win.destroy()
|
||||
while gtk.events_pending():
|
||||
|
||||
@@ -351,7 +351,7 @@ def test_simplify():
|
||||
domain = ['OR', [['x', '=', 3]], [['y', '=', 5]]]
|
||||
assert simplify(domain) == ['OR', [['x', '=', 3]], [['y', '=', 5]]]
|
||||
domain = ['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]]
|
||||
assert simplify(domain) == ['OR', ['x', '=', 3], ['y', '=', 5]]
|
||||
assert simplify(domain) == ['OR', ['x', '=', 3], [['y', '=', 5]]]
|
||||
|
||||
def test_merge():
|
||||
domain = [['x', '=', 6], ['y', '=', 7]]
|
||||
@@ -405,6 +405,17 @@ def test_evaldomain():
|
||||
assert not eval_domain(domain, {'x': 5})
|
||||
assert not eval_domain(domain, {'x': 11})
|
||||
|
||||
def test_localize():
|
||||
domain = [['x', '=', 5]]
|
||||
assert localize_domain(domain) == [['x', '=', 5]]
|
||||
|
||||
domain = [['x', '=', 5], ['x.code', '=', 7]]
|
||||
assert localize_domain(domain, 'x') == [['id', '=', 5], ['code', '=', 7]]
|
||||
|
||||
domain = ['OR', ['AND', ['x', '>', 7], ['x', '<', 15]], ['x.code', '=', 8]]
|
||||
assert localize_domain(domain, 'x') == \
|
||||
['OR', ['AND', ['id', '>', 7], ['id', '<', 15]], ['code', '=', 8]]
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_simple_inversion()
|
||||
test_and_inversion()
|
||||
@@ -416,3 +427,4 @@ if __name__ == '__main__':
|
||||
test_parse()
|
||||
test_simplify()
|
||||
test_evaldomain()
|
||||
test_localize()
|
||||
+1
-1
@@ -187,7 +187,7 @@ if not os.path.isdir(PIXMAPS_DIR):
|
||||
PIXMAPS_DIR = os.path.join(PREFIX, 'share', 'pixmaps', 'tryton')
|
||||
|
||||
TRYTON_ICON = gtk.gdk.pixbuf_new_from_file(
|
||||
os.path.join(PIXMAPS_DIR, 'tryton-icon.png'))
|
||||
os.path.join(PIXMAPS_DIR, 'tryton-icon.png').encode('utf-8'))
|
||||
|
||||
def _data_dir():
|
||||
data_dir = os.path.join(CURRENT_DIR, 'share', 'tryton')
|
||||
|
||||
@@ -389,6 +389,8 @@ class DBLogin(object):
|
||||
self.combo_profile.add_attribute(cell, 'sensitive', 1)
|
||||
self.combo_profile.set_model(self.profile_store)
|
||||
self.combo_profile.connect('changed', self.profile_changed)
|
||||
self.combo_profile.connect('move-active', self.profile_move_active)
|
||||
self.move_active = False
|
||||
self.profile_label = gtk.Label(_(u'Profile:'))
|
||||
self.profile_label.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
self.profile_label.set_alignment(1, 0.5)
|
||||
@@ -456,10 +458,16 @@ class DBLogin(object):
|
||||
username = ''
|
||||
if username:
|
||||
self.entry_login.set_text(username)
|
||||
self.entry_password.grab_focus()
|
||||
focus_widget = self.entry_password
|
||||
else:
|
||||
self.entry_login.set_text('')
|
||||
self.entry_login.grab_focus()
|
||||
focus_widget = self.entry_login
|
||||
if not self.move_active:
|
||||
focus_widget.grab_focus()
|
||||
self.move_active = False
|
||||
|
||||
def profile_move_active(self, combobox, scrolltype):
|
||||
self.move_active = True
|
||||
|
||||
def run(self, profile_name, parent):
|
||||
if not profile_name:
|
||||
|
||||
@@ -143,11 +143,10 @@ class Action(SignalEvent):
|
||||
self.widget.show_all()
|
||||
|
||||
if self.action['view_type'] == 'form':
|
||||
self.screen = Screen(self.action['res_model'], self._window,
|
||||
view_type=self.action['view_mode'], context=self.context,
|
||||
view_ids=view_ids, domain=self.domain, readonly=True)
|
||||
self.screen.screen_container.alternate_view = True
|
||||
self.screen.switch_view(view_type=self.action['view_mode'])
|
||||
self.screen = Screen(self.action['res_model'],
|
||||
self._window, view_type=self.action['view_mode'],
|
||||
context=self.context, view_ids=view_ids,
|
||||
domain=self.domain, readonly=True, alternate_view=True)
|
||||
alignment.add(self.screen.screen_container.alternate_viewport)
|
||||
name = self.screen.current_view.title
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
|
||||
@@ -155,25 +155,16 @@ class Group(SignalEvent, list):
|
||||
return list({}.fromkeys(res))
|
||||
|
||||
def load(self, ids, display=True, modified=False):
|
||||
if not ids:
|
||||
return True
|
||||
# Work with sets to compute intersection and set difference
|
||||
set_records = set(self.get(x) for x in ids)
|
||||
for record in set_records & set(self.record_removed):
|
||||
self.record_removed.remove(record)
|
||||
for record in set_records & set(self.record_deleted):
|
||||
self.record_deleted.remove(record)
|
||||
|
||||
set_records -= set(x for x in self)
|
||||
# return on the list form in order to preserver ordering
|
||||
ids = [x for x in ids if self.get(x) in set_records]
|
||||
if not ids:
|
||||
return True
|
||||
|
||||
if len(ids) > 1:
|
||||
self.lock_signal = True
|
||||
|
||||
new_records = []
|
||||
for id in ids:
|
||||
if self.get(id):
|
||||
continue
|
||||
new_record = Record(self.model_name, id, self.window,
|
||||
parent=self.parent, parent_name=self.parent_name, group=self)
|
||||
self.append(new_record)
|
||||
@@ -182,6 +173,15 @@ class Group(SignalEvent, list):
|
||||
self._record_changed)
|
||||
new_record.signal_connect(self, 'record-modified',
|
||||
self._record_modified)
|
||||
|
||||
# Remove previously removed or deleted records
|
||||
for record in self.record_removed[:]:
|
||||
if record.id in ids:
|
||||
self.record_removed.remove(record)
|
||||
for record in self.record_deleted[:]:
|
||||
if record.id in ids:
|
||||
self.record_deleted.remove(record)
|
||||
|
||||
if self.lock_signal:
|
||||
self.lock_signal = False
|
||||
self.signal('group-cleared')
|
||||
@@ -234,7 +234,7 @@ class Group(SignalEvent, list):
|
||||
if record[field]:
|
||||
if index >= record[field].get(record):
|
||||
index += 1
|
||||
record[field].set(record, index, modified=True)
|
||||
record[field].set_client(record, index)
|
||||
else:
|
||||
index = record[field].get(record)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class Screen(SignalEvent):
|
||||
def __init__(self, model_name, window, view_ids=None, view_type=None,
|
||||
context=None, views_preload=None, domain=None, row_activate=None,
|
||||
limit=None, readonly=False, exclude_field=None, sort=None,
|
||||
search_value=None):
|
||||
search_value=None, alternate_view=False):
|
||||
if view_ids is None:
|
||||
view_ids = []
|
||||
if view_type is None:
|
||||
@@ -54,6 +54,7 @@ class Screen(SignalEvent):
|
||||
self.__current_record = None
|
||||
self.current_record = None
|
||||
self.screen_container = ScreenContainer()
|
||||
self.screen_container.alternate_view = alternate_view
|
||||
self.filter_widget = None
|
||||
self.widget = self.screen_container.widget_get()
|
||||
self.__current_view = 0
|
||||
|
||||
@@ -121,8 +121,9 @@ class ViewForm(ParserView):
|
||||
'to be able to use the action button!'), self.window)
|
||||
return False
|
||||
email = {}
|
||||
if 'email' in action:
|
||||
email = self.screen.current_record.expr_eval(action['email'])
|
||||
if 'pyson_email' in action:
|
||||
email = self.screen.current_record.expr_eval(
|
||||
action['pyson_email'])
|
||||
if not email:
|
||||
email = {}
|
||||
email['subject'] = action['name'].replace('_', '')
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import base64
|
||||
import gtk
|
||||
import gettext
|
||||
import os
|
||||
from tryton.common import file_selection, message, warning, Tooltips
|
||||
import tempfile
|
||||
from tryton.common import file_selection, message, warning, Tooltips, file_open
|
||||
from interface import WidgetInterface
|
||||
|
||||
_ = gettext.gettext
|
||||
@@ -45,13 +47,25 @@ class Binary(WidgetInterface):
|
||||
|
||||
self.but_new = gtk.Button()
|
||||
img_new = gtk.Image()
|
||||
img_new.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_new.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_new.set_image(img_new)
|
||||
self.but_new.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_new.connect('clicked', self.sig_new)
|
||||
self.tooltips.set_tip(self.but_new, _('Select a File'))
|
||||
self.tooltips.set_tip(self.but_new, _('Select a File...'))
|
||||
self.widget.pack_start(self.but_new, expand=False, fill=False)
|
||||
|
||||
if self.filename:
|
||||
self.but_open = gtk.Button()
|
||||
img_open = gtk.Image()
|
||||
img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_open.set_image(img_open)
|
||||
self.but_open.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_open.connect('clicked', self.sig_open)
|
||||
self.tooltips.set_tip(self.but_open, _('Open...'))
|
||||
self.widget.pack_start(self.but_open, expand=False, fill=False)
|
||||
else:
|
||||
self.but_open = None
|
||||
|
||||
self.but_save_as = gtk.Button()
|
||||
img_save_as = gtk.Image()
|
||||
img_save_as.set_from_stock('tryton-save-as',
|
||||
@@ -73,6 +87,10 @@ class Binary(WidgetInterface):
|
||||
|
||||
self.tooltips.enable()
|
||||
|
||||
@property
|
||||
def filename_field(self):
|
||||
return self.record.group.fields.get(self.filename)
|
||||
|
||||
def _readonly_set(self, value):
|
||||
if value:
|
||||
self.but_new.hide()
|
||||
@@ -83,6 +101,9 @@ class Binary(WidgetInterface):
|
||||
self.but_remove.show()
|
||||
if self.wid_text:
|
||||
focus_chain = [self.wid_text]
|
||||
elif self.filename:
|
||||
focus_chain = [self.but_new, self.but_open, self.but_save_as,
|
||||
self.but_remove]
|
||||
else:
|
||||
focus_chain = [self.but_new, self.but_save_as, self.but_remove]
|
||||
self.widget.set_focus_chain(focus_chain)
|
||||
@@ -94,36 +115,42 @@ class Binary(WidgetInterface):
|
||||
return self.wid_size.grab_focus()
|
||||
|
||||
def sig_new(self, widget=None):
|
||||
try:
|
||||
filename = file_selection(_('Open...'),
|
||||
parent=self.window)
|
||||
if filename and self.field:
|
||||
self.field.set_client(self.record,
|
||||
base64.encodestring(open(filename, 'rb').read()))
|
||||
if self.filename and self.record:
|
||||
name_wid = self.record.group.fields[self.filename]
|
||||
name_wid.set_client(self.record, os.path.basename(filename))
|
||||
self.display(self.record, self.field)
|
||||
except Exception, exception:
|
||||
warning(_('Error reading the file.\nError message:\n%s') \
|
||||
% str(exception), self.window, _('Error'))
|
||||
filename = file_selection(_('Open...'),
|
||||
parent=self.window)
|
||||
if filename and self.field:
|
||||
self.field.set_client(self.record,
|
||||
base64.encodestring(open(filename, 'rb').read()))
|
||||
if self.filename_field:
|
||||
self.filename_field.set_client(self.record,
|
||||
os.path.basename(filename))
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def sig_open(self, widget=None):
|
||||
if not self.filename_field:
|
||||
return
|
||||
dtemp = tempfile.mkdtemp(prefix='tryton_')
|
||||
filename = self.filename_field.get(self.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(base64.decodestring(self.field.get(self.record)))
|
||||
root, type_ = os.path.splitext(filename)
|
||||
if type_:
|
||||
type_ = type_[1:]
|
||||
file_open(file_path, type_, self.window)
|
||||
|
||||
def sig_save_as(self, widget=None):
|
||||
try:
|
||||
filename = file_selection(_('Save As...'),
|
||||
parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename and self.field:
|
||||
file_p = open(filename,'wb+')
|
||||
file_p.write(base64.decodestring(
|
||||
self.field.get(self.record)))
|
||||
file_p.close()
|
||||
except Exception, exception:
|
||||
warning(_('Error writing the file.\nError message:\n%s') \
|
||||
% str(exception), self.window, _('Error'))
|
||||
filename = ''
|
||||
if self.filename_field:
|
||||
filename = self.filename_field.get(self.record)
|
||||
filename = file_selection(_('Save As...'), filename=filename,
|
||||
parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename:
|
||||
with open(filename,'wb') as fp:
|
||||
fp.write(base64.decodestring(self.field.get(self.record)))
|
||||
|
||||
def sig_remove(self, widget=None):
|
||||
if self.field:
|
||||
self.field.set_client(self.record, False)
|
||||
self.field.set_client(self.record, False)
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def sig_key_press(self, widget, event, *args):
|
||||
@@ -132,7 +159,10 @@ class Binary(WidgetInterface):
|
||||
self.sig_new(widget)
|
||||
return True
|
||||
elif event.keyval == gtk.keysyms.F2:
|
||||
self.sig_save_as(widget)
|
||||
if self.filename:
|
||||
self.sig_open(widget)
|
||||
else:
|
||||
self.sig_save_as(widget)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -142,12 +172,15 @@ class Binary(WidgetInterface):
|
||||
if self.wid_text:
|
||||
self.wid_text.set_text('')
|
||||
self.wid_size.set_text('')
|
||||
if self.but_open:
|
||||
self.but_open.set_sensitive(False)
|
||||
self.but_save_as.set_sensitive(False)
|
||||
return False
|
||||
if self.wid_text:
|
||||
name_wid = record.group.fields[self.filename]
|
||||
self.wid_text.set_text(name_wid.get(record) or '')
|
||||
self.wid_text.set_text(self.filename_field.get(record) or '')
|
||||
self.wid_size.set_text(humanize(len(field.get(record) or [])))
|
||||
if self.but_open:
|
||||
self.but_open.set_sensitive(bool(field.get(record)))
|
||||
self.but_save_as.set_sensitive(bool(field.get(record)))
|
||||
return True
|
||||
|
||||
@@ -159,8 +192,8 @@ class Binary(WidgetInterface):
|
||||
|
||||
def set_value(self, record, field):
|
||||
if self.wid_text:
|
||||
name_wid = self.record.group.fields[self.filename]
|
||||
name_wid.set_client(self.record, self.wid_text.get_text() or False)
|
||||
self.filename_field.set_client(self.record,
|
||||
self.wid_text.get_text() or False)
|
||||
return
|
||||
|
||||
def _color_widget(self):
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#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 gettext
|
||||
|
||||
import gtk
|
||||
from interface import WidgetInterface
|
||||
from tryton.common import Tooltips
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
class Char(WidgetInterface):
|
||||
"Char"
|
||||
@@ -50,4 +55,21 @@ class Sha(Char):
|
||||
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Sha, self).__init__(field_name, model_name, window, attrs=attrs)
|
||||
self.entry.set_visibility(False)
|
||||
self.entry.props.visibility = False
|
||||
|
||||
self.visibility_checkbox = gtk.CheckButton()
|
||||
self.visibility_checkbox.connect('toggled', self.toggle_visibility)
|
||||
Tooltips().set_tip(self.visibility_checkbox, _('Show plain text'))
|
||||
self.widget.pack_start(self.visibility_checkbox, expand=False)
|
||||
|
||||
def _readonly_set(self, value):
|
||||
super(Char, self)._readonly_set(value)
|
||||
self.entry.set_editable(not value)
|
||||
self.visibility_checkbox.props.visible = not value
|
||||
if value:
|
||||
self.widget.set_focus_chain([])
|
||||
else:
|
||||
self.widget.set_focus_chain([self.entry, self.visibility_checkbox])
|
||||
|
||||
def toggle_visibility(self, button):
|
||||
self.entry.props.visibility = not self.entry.props.visibility
|
||||
@@ -1,10 +1,12 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import gtk
|
||||
import gettext
|
||||
import os
|
||||
import tempfile
|
||||
from base64 import encodestring, decodestring
|
||||
from tryton.common import file_selection, Tooltips
|
||||
from tryton.common import file_selection, Tooltips, file_open
|
||||
from tryton.config import PIXMAPS_DIR
|
||||
from interface import WidgetInterface
|
||||
import urllib
|
||||
@@ -39,37 +41,55 @@ class Image(WidgetInterface):
|
||||
self.event.add(self.image)
|
||||
self.widget.pack_start(self.event, expand=True, fill=True)
|
||||
|
||||
self.alignment = gtk.Alignment(xalign=0.5, yalign=0.5)
|
||||
self.hbox = gtk.HBox(spacing=0)
|
||||
self.but_add = gtk.Button()
|
||||
img_add = gtk.Image()
|
||||
img_add.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_add.set_image(img_add)
|
||||
self.but_add.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_add.connect('clicked', self.sig_add)
|
||||
self.tooltips.set_tip(self.but_add, _('Set Image'))
|
||||
self.hbox.pack_start(self.but_add, expand=False, fill=False)
|
||||
if not attrs.get('readonly'):
|
||||
alignment = gtk.Alignment(xalign=0.5, yalign=0.5)
|
||||
hbox = gtk.HBox(spacing=0)
|
||||
self.but_add = gtk.Button()
|
||||
img_add = gtk.Image()
|
||||
img_add.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_add.set_image(img_add)
|
||||
self.but_add.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_add.connect('clicked', self.sig_add)
|
||||
self.tooltips.set_tip(self.but_add, _('Select an Image...'))
|
||||
hbox.pack_start(self.but_add, expand=False, fill=False)
|
||||
|
||||
self.but_save_as = gtk.Button()
|
||||
img_save_as = gtk.Image()
|
||||
img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_save_as.set_image(img_save_as)
|
||||
self.but_save_as.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_save_as.connect('clicked', self.sig_save_as)
|
||||
self.tooltips.set_tip(self.but_save_as, _('Save As'))
|
||||
self.hbox.pack_start(self.but_save_as, expand=False, fill=False)
|
||||
if self.filename:
|
||||
self.but_open = gtk.Button()
|
||||
img_open = gtk.Image()
|
||||
img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_open.set_image(img_open)
|
||||
self.but_open.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_open.connect('clicked', self.sig_open)
|
||||
self.tooltips.set_tip(self.but_open, _('Open...'))
|
||||
hbox.pack_start(self.but_open, expand=False, fill=False)
|
||||
else:
|
||||
self.but_open = None
|
||||
|
||||
self.but_remove = gtk.Button()
|
||||
img_remove = gtk.Image()
|
||||
img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_remove.set_image(img_remove)
|
||||
self.but_remove.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_remove.connect('clicked', self.sig_remove)
|
||||
self.tooltips.set_tip(self.but_remove, _('Clear'))
|
||||
self.hbox.pack_start(self.but_remove, expand=False, fill=False)
|
||||
self.but_save_as = gtk.Button()
|
||||
img_save_as = gtk.Image()
|
||||
img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_save_as.set_image(img_save_as)
|
||||
self.but_save_as.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_save_as.connect('clicked', self.sig_save_as)
|
||||
self.tooltips.set_tip(self.but_save_as, _('Save As...'))
|
||||
hbox.pack_start(self.but_save_as, expand=False, fill=False)
|
||||
|
||||
self.alignment.add(self.hbox)
|
||||
self.widget.pack_start(self.alignment, expand=False, fill=False)
|
||||
self.but_remove = gtk.Button()
|
||||
img_remove = gtk.Image()
|
||||
img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
self.but_remove.set_image(img_remove)
|
||||
self.but_remove.set_relief(gtk.RELIEF_NONE)
|
||||
self.but_remove.connect('clicked', self.sig_remove)
|
||||
self.tooltips.set_tip(self.but_remove, _('Clear'))
|
||||
hbox.pack_start(self.but_remove, expand=False, fill=False)
|
||||
|
||||
alignment.add(hbox)
|
||||
self.widget.pack_start(alignment, expand=False, fill=False)
|
||||
else:
|
||||
self.but_add = None
|
||||
self.but_open = None
|
||||
self.but_save_as = None
|
||||
self.but_remove = None
|
||||
|
||||
self.tooltips.enable()
|
||||
|
||||
@@ -77,14 +97,23 @@ class Image(WidgetInterface):
|
||||
|
||||
self.update_img()
|
||||
|
||||
@property
|
||||
def filename_field(self):
|
||||
return self.record.group.fields.get(self.filename)
|
||||
|
||||
def grab_focus(self):
|
||||
return self.image.grab_focus()
|
||||
|
||||
def _readonly_set(self, value):
|
||||
self._readonly = value
|
||||
self.but_add.set_sensitive(not value)
|
||||
self.but_save_as.set_sensitive(not value)
|
||||
self.but_remove.set_sensitive(not value)
|
||||
if self.but_add:
|
||||
self.but_add.set_sensitive(not value)
|
||||
if self.but_open:
|
||||
self.but_open.set_sensitive(not value)
|
||||
if self.but_save_as:
|
||||
self.but_save_as.set_sensitive(not value)
|
||||
if self.but_remove:
|
||||
self.but_remove.set_sensitive(not value)
|
||||
|
||||
def sig_add(self, widget):
|
||||
filter_all = gtk.FileFilter()
|
||||
@@ -103,17 +132,34 @@ class Image(WidgetInterface):
|
||||
if filename:
|
||||
self.field.set_client(self.record,
|
||||
encodestring(open(filename, 'rb').read()))
|
||||
if self.filename and self.record:
|
||||
name_wid = self.record.group.fields[self.filename]
|
||||
name_wid.set_client(self.record, os.path.basename(filename))
|
||||
if self.filename_field:
|
||||
self.filename_field.set_client(self.record,
|
||||
os.path.basename(filename))
|
||||
self.update_img()
|
||||
|
||||
def sig_open(self, widget=None):
|
||||
if not self.filename_field:
|
||||
return
|
||||
dtemp = tempfile.mkdtemp(prefix='tryton_')
|
||||
filename = self.filename_field.get(self.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(decodestring(self.field.get(self.record)))
|
||||
root, type_ = os.path.splitext(filename)
|
||||
if type_:
|
||||
type_ = type_[1:]
|
||||
file_open(file_path, type_, self.window)
|
||||
|
||||
def sig_save_as(self, widget):
|
||||
filename = file_selection(_('Save As...'), parent=self.window,
|
||||
action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
filename = ''
|
||||
if self.filename_field:
|
||||
filename = self.filename_field.get(self.record)
|
||||
filename = file_selection(_('Save As...'), filename=filename,
|
||||
parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename:
|
||||
open(filename, 'wb').write(decodestring(
|
||||
self.field.get_client(self.record)))
|
||||
with open(filename, 'wb') as fp:
|
||||
fp.write(decodestring(self.field.get(self.record)))
|
||||
|
||||
def sig_remove(self, widget):
|
||||
self.field.set_client(self.record, False)
|
||||
|
||||
@@ -285,8 +285,8 @@ class ViewList(ParserView):
|
||||
message(_('No record selected!'), self.window)
|
||||
return False
|
||||
email = {}
|
||||
if action.get('email'):
|
||||
email = self.screen.current_record.expr_eval(action['email'])
|
||||
if action.get('pyson_email'):
|
||||
email = self.screen.current_record.expr_eval(action['pyson_email'])
|
||||
if not email:
|
||||
email = {}
|
||||
email['subject'] = action['name'].replace('_', '')
|
||||
|
||||
@@ -19,6 +19,8 @@ class IPCServer(object):
|
||||
instance = None
|
||||
|
||||
def __init__(self, hostname, port, database):
|
||||
if Server.instance:
|
||||
Server.instance.stop()
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
self.database = database
|
||||
|
||||
@@ -25,8 +25,9 @@ class Dialog(object):
|
||||
self.dia = gtk.Dialog(_('Wizard'), parent,
|
||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
if hasattr(self.dia, 'set_deletable') and os.name != 'nt':
|
||||
if hasattr(self.dia, 'set_deletable'):
|
||||
self.dia.set_deletable(False)
|
||||
self.dia.connect('close', self.close)
|
||||
|
||||
self.accel_group = gtk.AccelGroup()
|
||||
self.dia.add_accel_group(self.accel_group)
|
||||
@@ -145,6 +146,10 @@ class Dialog(object):
|
||||
self.parent.present()
|
||||
return False
|
||||
|
||||
def close(self, widget, event=None):
|
||||
widget.emit_stop_by_name('close')
|
||||
return True
|
||||
|
||||
def destroy(self):
|
||||
self.dia.destroy()
|
||||
|
||||
|
||||
Reference in new issue
Block a user