diff --git a/doc/usage.rst b/doc/usage.rst
index 2caabd13bc..a4ee6ef68d 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -581,24 +581,6 @@ Tabs Position
* Right
* Bottom
-.. _Menu-Options-File_Actions:
-
-File Actions...:
- Opens a dialog to set up file types for print and open actions.
- Use ``"%s"`` as a placeholder for the document name.
-
- * Provided file types:
-
- - ODT file: Open Office Writer Document
- - PDF file: Adobes(TM) Portable Document Format
- - PNG file: Portable Network Graphics format
- - TXT file: Pure text file
-
- * Provided actions
-
- - Open: Setting up program system call which opens the specific file type.
- - Print: Setting up program system call printing the specific file type.
-
.. _Menu-Options-Email:
Email...:
diff --git a/tryton/action/main.py b/tryton/action/main.py
index cfbfa79919..aca6895e69 100644
--- a/tryton/action/main.py
+++ b/tryton/action/main.py
@@ -1,9 +1,7 @@
#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 time
-import datetime
import tryton.rpc as rpc
-from tryton.common import message, error, selection, file_open, mailto
+from tryton.common import message, selection, file_open, mailto
from tryton.gui.window import Window
from tryton.pyson import PYSONDecoder
from tryton.exceptions import TrytonServerError
@@ -15,6 +13,7 @@ import tryton.common as common
_ = gettext.gettext
+
class Action(object):
@staticmethod
@@ -71,7 +70,7 @@ class Action(object):
common.process_exception(exception)
return
if not res:
- raise Exception, 'ActionNotFound'
+ raise Exception('ActionNotFound')
action_type = res['type']
try:
res = rpc.execute('model', action_type, 'search_read',
@@ -117,7 +116,8 @@ class Action(object):
domain_context = ctx.copy()
domain_context['context'] = ctx
domain_context['_user'] = rpc._USER
- domain = PYSONDecoder(domain_context).decode(action['pyson_domain'])
+ domain = PYSONDecoder(domain_context).decode(
+ action['pyson_domain'])
search_context = ctx.copy()
search_context['context'] = ctx
diff --git a/tryton/client.py b/tryton/client.py
index 0d9a541345..aa79f2942f 100644
--- a/tryton/client.py
+++ b/tryton/client.py
@@ -22,21 +22,18 @@ import logging
from urlparse import urlparse
import threading
-from tryton import version
-from tryton import config
import tryton.common as common
-from tryton.config import CONFIG, CURRENT_DIR, PREFIX, PIXMAPS_DIR, \
- TRYTON_ICON, get_config_dir
+from tryton.config import CONFIG, get_config_dir
from tryton import translate
from tryton import gui
from tryton.ipc import Client as IPCClient
-import traceback
import time
import signal
if not hasattr(gtk.gdk, 'lock'):
class _Lock(object):
__enter__ = gtk.gdk.threads_enter
+
def __exit__(*ignored):
gtk.gdk.threads_leave()
@@ -44,11 +41,13 @@ if not hasattr(gtk.gdk, 'lock'):
if sys.platform == 'win32':
class Dialog(gtk.Dialog):
+
def run(self):
with gtk.gdk.lock:
return super(Dialog, self).run()
gtk.Dialog = Dialog
+
class TrytonClient(object):
"Tryton client"
@@ -103,7 +102,8 @@ class TrytonClient(object):
signal.signal(signal.SIGINT, lambda signum, frame: main.sig_quit())
signal.signal(signal.SIGTERM, lambda signum, frame: main.sig_quit())
if hasattr(signal, 'SIGQUIT'):
- signal.signal(signal.SIGQUIT, lambda signum, frame: main.sig_quit())
+ signal.signal(signal.SIGQUIT,
+ lambda signum, frame: main.sig_quit())
def excepthook(exctyp, exception, tb):
import common
@@ -135,7 +135,7 @@ class TrytonClient(object):
if sys.platform == 'win32':
while not self.quit_client.isSet():
with gtk.gdk.lock:
- running = gtk.main_iteration(True)
+ gtk.main_iteration(True)
else:
gtk.main()
except KeyboardInterrupt:
diff --git a/tryton/common/button.py b/tryton/common/button.py
index 75c40bffa6..b437058ad0 100644
--- a/tryton/common/button.py
+++ b/tryton/common/button.py
@@ -27,7 +27,8 @@ class Button(gtk.Button):
def state_set(self, record):
if record:
- states = record.expr_eval(self.attrs.get('states', {}), check_load=False)
+ states = record.expr_eval(self.attrs.get('states', {}),
+ check_load=False)
else:
states = {}
if states.get('invisible', False):
diff --git a/tryton/common/cellrendererbinary.py b/tryton/common/cellrendererbinary.py
index 0c7cc4b152..7bca98f24a 100644
--- a/tryton/common/cellrendererbinary.py
+++ b/tryton/common/cellrendererbinary.py
@@ -4,6 +4,9 @@ import gtk
import gobject
import pango
+BUTTON_BORDER = 10
+BUTTON_SPACING = 2
+
class CellRendererBinary(gtk.GenericCellRenderer):
__gproperties__ = {
@@ -48,7 +51,8 @@ class CellRendererBinary(gtk.GenericCellRenderer):
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)
+ height = img_sensitive.get_height()
+ self.images[key] = (img_sensitive, img_insensitive, width, height)
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
@@ -56,24 +60,31 @@ class CellRendererBinary(gtk.GenericCellRenderer):
def do_get_property(self, pspec):
return getattr(self, pspec.name)
- def button_width(self, cell_area):
- return ((cell_area.width / 2 - (len(self.buttons) + 1) * 2)
- / len(self.buttons))
+ def button_width(self):
+ return (sum(width for _, _, width, _ in self.images.itervalues())
+ + (2 * (BUTTON_BORDER + BUTTON_SPACING) * len(self.buttons))
+ - 2 * BUTTON_SPACING)
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)
+ 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)
+ if event is None:
+ return
+ button_width = self.button_width()
for index, button_name in enumerate(self.buttons):
- x_offset = button_width * index + 2 * (index + 1)
- x_button = cell_area.x + cell_area.width / 2 + 5 + x_offset
- if x_button < event.x < x_button + button_width:
+ _, _, pxbf_width, _ = self.images[button_name]
+ x_offset = (cell_area.width - button_width
+ + (pxbf_width + (2 * BUTTON_BORDER) + BUTTON_SPACING) * index)
+ x_button = cell_area.x + x_offset
+ if x_button < event.x < (x_button + pxbf_width
+ + (2 * BUTTON_BORDER)):
break
else:
button_name = None
@@ -83,9 +94,10 @@ class CellRendererBinary(gtk.GenericCellRenderer):
return
if not self.size and button_name == 'save':
return
- if event is None or event.type == gtk.gdk.BUTTON_PRESS:
+ if event.type == gtk.gdk.BUTTON_PRESS:
self.clicking = button_name
self.emit(button_name, path)
+
def timeout(self, widget):
self.clicking = ''
widget.queue_draw()
@@ -99,24 +111,31 @@ class CellRendererBinary(gtk.GenericCellRenderer):
if type(window) == gtk.gdk.Pixmap:
return
+ button_width = self.button_width()
+
# display size
layout = widget.create_pango_layout(self.size)
layout.set_font_description(widget.style.font_desc)
w, h = layout.get_size()
- x = int(cell_area.x + (cell_area.width - w / pango.SCALE) * 0)
+ x = int(cell_area.x + cell_area.width - button_width - w / pango.SCALE
+ - BUTTON_SPACING)
y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2)
+ layout.set_width(((cell_area.width / 2) - 2) * pango.SCALE)
state = gtk.STATE_NORMAL
if flags & gtk.CELL_RENDERER_SELECTED:
state = gtk.STATE_ACTIVE
- window.draw_layout(widget.style.text_gc[state], x, y, layout)
+ if x >= cell_area.x:
+ widget.style.paint_layout(window, state, True, expose_area,
+ widget, "cellrendererbinary", x, y, layout)
# display buttons
- 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:
+ pxbf_sens, pxbf_insens, pxbf_width, pxbf_height = \
+ self.images[button_name]
+ if (self.clicking == button_name
+ and flags & gtk.CELL_RENDERER_SELECTED):
state = gtk.STATE_ACTIVE
shadow = gtk.SHADOW_IN
if (not self.editable and button_name in ('new', 'clear')
@@ -125,14 +144,16 @@ class CellRendererBinary(gtk.GenericCellRenderer):
pixbuf = pxbf_insens
else:
pixbuf = pxbf_sens
- x_offset = (cell_area.width / 2 + 5
- + button_width * index + 2 * (index + 1)) - 1
+ x_offset = (cell_area.width - button_width
+ + (pxbf_width + (2 * BUTTON_BORDER) + BUTTON_SPACING) * index)
+ if x_offset < 0:
+ continue
widget.style.paint_box(window, state, shadow,
None, widget, "button", cell_area.x + x_offset, cell_area.y,
- button_width, cell_area.height)
+ pxbf_width + (2 * BUTTON_BORDER), 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)
+ cell_area.x + x_offset + BUTTON_BORDER,
+ cell_area.y + (cell_area.height - pxbf_height) / 2)
gobject.type_register(CellRendererBinary)
diff --git a/tryton/common/cellrendererbutton.py b/tryton/common/cellrendererbutton.py
index f57f83b468..d32ac4c4b7 100644
--- a/tryton/common/cellrendererbutton.py
+++ b/tryton/common/cellrendererbutton.py
@@ -54,19 +54,29 @@ class CellRendererButton(gtk.GenericCellRenderer):
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)
+ widget.style.paint_layout(window, state, True, expose_area, widget,
+ "cellrendererbutton", x, y, layout)
layout = widget.create_pango_layout(self.text)
layout.set_font_description(widget.style.font_desc)
+ layout.set_ellipsize(pango.ELLIPSIZE_END)
w, h = layout.get_size()
- x = int(cell_area.x + (cell_area.width - w / pango.SCALE) / 2)
+ if cell_area.width < w / pango.SCALE:
+ x = cell_area.x + 2 / pango.SCALE
+ else:
+ x = int(cell_area.x + (cell_area.width - w / pango.SCALE) / 2)
y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2)
- window.draw_layout(widget.style.text_gc[0], x, y, layout)
+ layout.set_width((cell_area.width - 4) * pango.SCALE)
+ layout.set_wrap(pango.WRAP_CHAR)
+ widget.style.paint_layout(window, state, True, expose_area, widget,
+ "cellrendererbutton", 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)
+ 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):
@@ -80,6 +90,7 @@ class CellRendererButton(gtk.GenericCellRenderer):
while gtk.events_pending():
gtk.main_iteration()
self.emit("clicked", path)
+
def timeout(self, widget):
self.clicking = False
widget.queue_draw()
diff --git a/tryton/common/cellrenderercombo.py b/tryton/common/cellrenderercombo.py
index 374ade5bd2..b4d3c0dfa9 100644
--- a/tryton/common/cellrenderercombo.py
+++ b/tryton/common/cellrenderercombo.py
@@ -106,10 +106,13 @@ class CellRendererCombo(gtk.GenericCellRenderer):
editable.modify_text(gtk.STATE_INSENSITIVE, fg_color)
else:
editable.modify_bg(gtk.STATE_ACTIVE, style.bg[gtk.STATE_ACTIVE])
- editable.modify_base(gtk.STATE_NORMAL, style.base[gtk.STATE_NORMAL])
+ editable.modify_base(gtk.STATE_NORMAL,
+ style.base[gtk.STATE_NORMAL])
editable.modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_NORMAL, style.text[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_INSENSITIVE, style.text[gtk.STATE_INSENSITIVE])
+ editable.modify_text(gtk.STATE_NORMAL,
+ style.text[gtk.STATE_NORMAL])
+ editable.modify_text(gtk.STATE_INSENSITIVE,
+ style.text[gtk.STATE_INSENSITIVE])
return editable
gobject.type_register(CellRendererCombo)
diff --git a/tryton/common/cellrendererdate.py b/tryton/common/cellrendererdate.py
index d7e199f4bc..d8afcbc80d 100644
--- a/tryton/common/cellrendererdate.py
+++ b/tryton/common/cellrendererdate.py
@@ -3,7 +3,7 @@
import gtk
import gobject
import pango
-from date_widget import mapping, DateEntry, compute_date
+from date_widget import DateEntry, compute_date
class CellRendererDate(gtk.GenericCellRenderer):
@@ -100,10 +100,13 @@ class CellRendererDate(gtk.GenericCellRenderer):
editable.modify_text(gtk.STATE_INSENSITIVE, fg_color)
else:
editable.modify_bg(gtk.STATE_ACTIVE, style.bg[gtk.STATE_ACTIVE])
- editable.modify_base(gtk.STATE_NORMAL, style.base[gtk.STATE_NORMAL])
+ editable.modify_base(gtk.STATE_NORMAL,
+ style.base[gtk.STATE_NORMAL])
editable.modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_NORMAL, style.text[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_INSENSITIVE, style.text[gtk.STATE_INSENSITIVE])
+ editable.modify_text(gtk.STATE_NORMAL,
+ style.text[gtk.STATE_NORMAL])
+ editable.modify_text(gtk.STATE_INSENSITIVE,
+ style.text[gtk.STATE_INSENSITIVE])
if self.text:
editable.set_text(self.text)
@@ -126,9 +129,10 @@ class CellRendererDate(gtk.GenericCellRenderer):
if ok:
self._date_cb(event)
else:
- if hasattr(event, 'keyval') and not event.keyval == gtk.keysyms.Escape:
+ if (hasattr(event, 'keyval')
+ and not event.keyval == gtk.keysyms.Escape):
dt = widget.date_get()
- res= compute_date(self.cmd, dt, widget.format)
+ res = compute_date(self.cmd, dt, widget.format)
if res:
widget.date_set(res)
self.cmd = ''
diff --git a/tryton/common/cellrendererinteger.py b/tryton/common/cellrendererinteger.py
index aaeedf31a4..d2c85c383c 100644
--- a/tryton/common/cellrendererinteger.py
+++ b/tryton/common/cellrendererinteger.py
@@ -7,7 +7,6 @@ import locale
class CellRendererInteger(CellRendererText):
-
def on_start_editing(self, event, widget, path, background_area,
cell_area, flags):
editable = super(CellRendererInteger, self).on_start_editing(event,
diff --git a/tryton/common/cellrenderertext.py b/tryton/common/cellrenderertext.py
index 4beded4d23..a704a5aab0 100644
--- a/tryton/common/cellrenderertext.py
+++ b/tryton/common/cellrenderertext.py
@@ -100,10 +100,13 @@ class CellRendererText(gtk.GenericCellRenderer):
editable.modify_text(gtk.STATE_INSENSITIVE, fg_color)
else:
editable.modify_bg(gtk.STATE_ACTIVE, style.bg[gtk.STATE_ACTIVE])
- editable.modify_base(gtk.STATE_NORMAL, style.base[gtk.STATE_NORMAL])
+ editable.modify_base(gtk.STATE_NORMAL,
+ style.base[gtk.STATE_NORMAL])
editable.modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_NORMAL, style.text[gtk.STATE_NORMAL])
- editable.modify_text(gtk.STATE_INSENSITIVE, style.text[gtk.STATE_INSENSITIVE])
+ editable.modify_text(gtk.STATE_NORMAL,
+ style.text[gtk.STATE_NORMAL])
+ editable.modify_text(gtk.STATE_INSENSITIVE,
+ style.text[gtk.STATE_INSENSITIVE])
editable.set_text(self.text)
editable.grab_focus()
diff --git a/tryton/common/cellrenderertoggle.py b/tryton/common/cellrenderertoggle.py
index 2f4f4592dd..b9cafbc9be 100644
--- a/tryton/common/cellrenderertoggle.py
+++ b/tryton/common/cellrenderertoggle.py
@@ -2,7 +2,6 @@
#this repository contains the full copyright notices and license terms.
import gtk
import gobject
-import pango
class CellRendererToggle(gtk.GenericCellRenderer):
diff --git a/tryton/common/common.py b/tryton/common/common.py
index f38ce58ae4..2758f8ea44 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -11,7 +11,7 @@ import subprocess
import re
import logging
from tryton.config import CONFIG
-from tryton.config import TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
+from tryton.config import TRYTON_ICON, PIXMAPS_DIR
import time
import sys
import xmlrpclib
@@ -37,7 +37,7 @@ try:
except ImportError:
ssl = None
import dis
-from threading import Lock, Semaphore
+from threading import Lock
try:
import pytz
except ImportError:
@@ -128,6 +128,7 @@ class TrytonIconFactory(gtk.IconFactory):
ICONFACTORY = TrytonIconFactory()
ICONFACTORY.add_default()
+
def find_in_path(name):
if os.name == "nt":
sep = ';'
@@ -141,12 +142,14 @@ def find_in_path(name):
return val
return name
+
def test_server_version(host, port):
version = rpc.server_version(host, port)
if not version:
return False
return version.split('.')[:2] == VERSION.split('.')[:2]
+
def refresh_dblist(host, port):
'''
Return the number of database available
@@ -158,6 +161,7 @@ def refresh_dblist(host, port):
return -1
return rpc.db_list(host, port)
+
def refresh_langlist(lang_widget, host, port):
liststore = lang_widget.get_model()
liststore.clear()
@@ -174,17 +178,18 @@ def refresh_langlist(lang_widget, host, port):
liststore.insert(i, (val, key))
if key == lang:
index = i
- if key == 'en_US' and index < 0 :
+ if key == 'en_US' and index < 0:
index = i
i += 1
lang_widget.set_active(index)
return lang_list
+
def request_server(server_widget):
result = False
parent = get_toplevel_window()
dialog = gtk.Dialog(
- title= _('Tryton Connection'),
+ title=_('Tryton Connection'),
parent=parent,
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
gtk.WIN_POS_CENTER_ON_PARENT |
@@ -211,7 +216,7 @@ def request_server(server_widget):
entry_server.set_text("localhost")
entry_server.set_activates_default(True)
entry_server.set_width_chars(16)
- table.attach(entry_server, 1, 2, 0, 1,yoptions=False,
+ table.attach(entry_server, 1, 2, 0, 1, yoptions=False,
xoptions=gtk.FILL | gtk.EXPAND)
label_port = gtk.Label(_("Port:"))
label_port.set_alignment(1, 0.5)
@@ -242,6 +247,7 @@ def request_server(server_widget):
dialog.destroy()
return result
+
def get_toplevel_window():
windows = [x for x in gtk.window_list_toplevels()
if x.window and x.props.visible]
@@ -250,6 +256,7 @@ def get_toplevel_window():
return window
return trans2windows[None]
+
def get_sensible_widget(window):
from tryton.gui.main import Main
main = Main.get_main()
@@ -260,6 +267,7 @@ def get_sensible_widget(window):
return page.widget
return window
+
def center_window(window, parent, sensible):
parent_x, parent_y = parent.window.get_origin()
window_allocation = window.get_allocation()
@@ -270,10 +278,11 @@ def center_window(window, parent, sensible):
int((sensible_allocation.height - window_allocation.height) / 2))
window.move(x, y)
+
def selection(title, values, alwaysask=False):
- if not values or len(values)==0:
+ if not values or len(values) == 0:
return None
- elif len(values)==1 and (not alwaysask):
+ elif len(values) == 1 and (not alwaysask):
key = values.keys()[0]
return (key, values[key])
@@ -331,13 +340,14 @@ def selection(title, values, alwaysask=False):
dialog.destroy()
return res
+
def file_selection(title, filename='',
action=gtk.FILE_CHOOSER_ACTION_OPEN, preview=True, multi=False,
filters=None):
parent = get_toplevel_window()
if action == gtk.FILE_CHOOSER_ACTION_OPEN:
buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN,gtk.RESPONSE_OK)
+ gtk.STOCK_OPEN, gtk.RESPONSE_OK)
else:
buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK)
@@ -403,48 +413,9 @@ def file_selection(title, filename='',
win.destroy()
return filenames
+
def file_open(filename, type, print_p=False):
- if os.name == 'nt':
- operation = 'open'
- if print_p:
- operation = 'print'
- try:
- os.startfile(os.path.normpath(filename), operation)
- except WindowsError:
- save_name = file_selection(_('Save As...'),
- action=gtk.FILE_CHOOSER_ACTION_SAVE)
- if save_name:
- file_p = open(filename, 'rb')
- save_p = open(save_name, 'wb+')
- save_p.write(file_p.read())
- save_p.close()
- file_p.close()
- return
- elif sys.platform == 'darwin':
- pid = os.fork()
- if not pid:
- pid = os.fork()
- if not pid:
- try:
- os.execv('/usr/bin/open', ['/usr/bin/open', filename])
- except OSError:
- sys.exit(0)
- time.sleep(0.1)
- sys.exit(0)
- os.waitpid(pid, 0)
- return
- cmd = ''
- if isinstance(CONFIG['client.actions'], basestring):
- CONFIG['client.actions'] = safe_eval(CONFIG['client.actions'])
- if type in CONFIG['client.actions']:
- if print_p:
- cmd = CONFIG['client.actions'][type][1]
- else:
- cmd = CONFIG['client.actions'][type][0]
- if not cmd:
- #TODO add dialog box
- pass
- if not cmd:
+ def save():
save_name = file_selection(_('Save As...'),
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if save_name:
@@ -453,25 +424,26 @@ def file_open(filename, type, print_p=False):
save_p.write(file_p.read())
save_p.close()
file_p.close()
- return
- cmd = cmd % filename
- args = shlex.split(str(cmd))
- prog = find_in_path(args[0])
- args[0] = os.path.basename(args[0])
- if print_p:
- os.spawnv(os.P_WAIT, prog, args)
- return
- pid = os.fork()
- if not pid:
- pid = os.fork()
- if not pid:
- try:
- os.execv(prog, args)
- except OSError:
- sys.exit(0)
- time.sleep(0.1)
- sys.exit(0)
- os.waitpid(pid, 0)
+
+ if os.name == 'nt':
+ operation = 'open'
+ if print_p:
+ operation = 'print'
+ try:
+ os.startfile(os.path.normpath(filename), operation)
+ except WindowsError:
+ save()
+ elif sys.platform == 'darwin':
+ try:
+ subprocess.Popen(['/usr/bin/open', filename])
+ except OSError:
+ save()
+ else:
+ try:
+ subprocess.Popen(['xdg-open', filename])
+ except OSError:
+ save()
+
def mailto(to=None, cc=None, subject=None, body=None, attachment=None):
if CONFIG['client.email']:
@@ -485,6 +457,23 @@ def mailto(to=None, cc=None, subject=None, body=None, attachment=None):
args = shlex.split(str(cmd))
subprocess.Popen(args)
return
+ if os.name != 'nt' and sys.platform != 'darwin':
+ args = ['xdg-email', '--utf8']
+ if cc:
+ args.extend(['--cc', cc])
+ if subject:
+ args.extend(['--subject', subject])
+ if body:
+ args.extend(['--body', body])
+ if attachment:
+ args.extend(['--attach', attachment])
+ if to:
+ args.append(to)
+ try:
+ subprocess.Popen(args)
+ return
+ except OSError:
+ pass
#http://www.faqs.org/rfcs/rfc2368.html
url = "mailto:"
if to:
@@ -540,7 +529,7 @@ class MessageDialog(UniqueDialog):
def build_dialog(self, parent, message, msg_type):
dialog = gtk.MessageDialog(parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, msg_type,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, msg_type,
gtk.BUTTONS_OK, message)
return dialog
@@ -559,7 +548,8 @@ class WarningDialog(UniqueDialog):
dialog.set_markup('%s' % (to_xml(title)))
dialog.format_secondary_markup(to_xml(message))
else:
- dialog.set_markup('%s\n%s' % (to_xml(title), to_xml(message)))
+ dialog.set_markup(
+ '%s\n%s' % (to_xml(title), to_xml(message)))
return dialog
warning = WarningDialog()
@@ -659,7 +649,7 @@ class AskDialog(UniqueDialog):
def build_dialog(self, parent, question, visibility):
win = gtk.Dialog('Tryton', parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OK, gtk.RESPONSE_OK))
win.set_has_separator(True)
@@ -704,9 +694,9 @@ ask = AskDialog()
class ConcurrencyDialog(UniqueDialog):
def build_dialog(self, parent, resource, obj_id, context):
- dialog = gtk.Dialog(_('Concurrency Exception'), parent, gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT
- | gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
+ dialog = gtk.Dialog(_('Concurrency Exception'), parent,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
+ gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
dialog.set_has_separator(True)
dialog.set_default_response(gtk.RESPONSE_CANCEL)
hbox = gtk.HBox()
@@ -830,15 +820,16 @@ class ErrorDialog(UniqueDialog):
if title == details:
title = ''
log = logging.getLogger('common.message')
- log.error(details)
+ log.error(details + '\n' + title)
response = super(ErrorDialog, self).__call__(title, details)
if response == gtk.RESPONSE_OK:
- send_bugtracker(details)
+ send_bugtracker(title, details)
error = ErrorDialog()
-def send_bugtracker(msg):
+
+def send_bugtracker(title, msg):
from tryton import rpc
parent = get_toplevel_window()
win = gtk.Dialog(_('Bug Tracker'), parent,
@@ -897,21 +888,15 @@ def send_bugtracker(msg):
protocol = 'http'
if ssl or hasattr(socket, 'ssl'):
protocol = 'https'
- server = xmlrpclib.Server(('%s://%s:%s@' + CONFIG['roundup.xmlrpc'])
- % (protocol, user, password), allow_none=True)
+ server = xmlrpclib.Server(
+ ('%s://%s:%s@' + CONFIG['roundup.xmlrpc'])
+ % (protocol, user, password), allow_none=True)
if hashlib:
- msg_md5 = hashlib.md5(msg).hexdigest()
+ msg_md5 = hashlib.md5(msg + '\n' + title).hexdigest()
else:
- msg_md5 = md5.new(msg).hexdigest()
- # use the last line of the message as title
- title = '[no title]'
- for line in msg.splitlines():
- #don't use empty line nor ^ from sql error
- if line and '^' != line.strip():
- if len(line) > 128:
- title = line[:128] + '...'
- else:
- title = line
+ msg_md5 = md5.new(msg + '\n' + title).hexdigest()
+ if not title:
+ title = '[no title]'
issue_id = None
msg_ids = server.filter('msg', None, {'summary': str(msg_md5)})
if msg_ids:
@@ -921,9 +906,10 @@ def send_bugtracker(msg):
if issue_id:
# issue to same message already exists, add user to nosy-list
server.set('issue' + str(issue_id), *['nosy=+' + user])
- message(_('The same bug was already reported by another user.\n' \
- 'To keep you informed your username is added to the nosy-list of this issue') + \
- '%s' % issue_id)
+ message(
+ _('The same bug was already reported by another user.\n'
+ 'To keep you informed your username is added '
+ 'to the nosy-list of this issue') + '%s' % issue_id)
else:
# create a new issue for this error-message
# first create message
@@ -934,23 +920,27 @@ def send_bugtracker(msg):
'nosy=' + user, 'title=' + title, 'priority=bug'])
message(_('Created new bug with ID ') + \
'issue%s' % issue_id)
- webbrowser.open(CONFIG['roundup.url'] + 'issue%s' % issue_id, new=2)
+ webbrowser.open(CONFIG['roundup.url'] + 'issue%s' % issue_id,
+ new=2)
except (socket.error, xmlrpclib.Fault), exception:
if (isinstance(exception, xmlrpclib.Fault)
and 'roundup.cgi.exceptions.Unauthorised' in
exception.faultString):
message(_('Connection error!\nBad username or password!'))
- return send_bugtracker(msg, parent)
+ return send_bugtracker(title, msg)
tb_s = reduce(lambda x, y: x + y,
traceback.format_exception(sys.exc_type,
sys.exc_value, sys.exc_traceback))
message(_('Exception:') + '\n' + tb_s, msg_type=gtk.MESSAGE_ERROR)
+
def to_xml(string):
- return string.replace('&','&').replace('<','<').replace('>','>')
+ return string.replace('&', '&'
+ ).replace('<', '<').replace('>', '>')
PLOCK = Lock()
+
def process_exception(exception, *args, **kwargs):
if isinstance(exception, TrytonError):
@@ -1049,6 +1039,7 @@ def process_exception(exception, *args, **kwargs):
error(error_title, error_detail)
return False
+
def node_attributes(node):
result = {}
attrs = node.attributes
@@ -1058,6 +1049,7 @@ def node_attributes(node):
result[str(attrs.item(i).localName)] = str(attrs.item(i).nodeValue)
return result
+
def hex2rgb(hexstring, digits=2):
"""
Converts a hexstring color to a rgb tuple.
@@ -1068,11 +1060,12 @@ def hex2rgb(hexstring, digits=2):
if isinstance(hexstring, (tuple, list)):
return hexstring
top = float(int(digits * 'f', 16))
- r = int(hexstring[1:digits+1], 16)
- g = int(hexstring[digits+1:digits*2+1], 16)
- b = int(hexstring[digits*2+1:digits*3+1], 16)
+ r = int(hexstring[1:digits + 1], 16)
+ g = int(hexstring[digits + 1:digits * 2 + 1], 16)
+ b = int(hexstring[digits * 2 + 1:digits * 3 + 1], 16)
return r / top, g / top, b / top
+
def clamp(minValue, maxValue, value):
"""Make sure value is between minValue and maxValue"""
if value < minValue:
@@ -1081,12 +1074,14 @@ def clamp(minValue, maxValue, value):
return maxValue
return value
+
def lighten(r, g, b, amount):
"""Return a lighter version of the color (r, g, b)"""
return (clamp(0.0, 1.0, r + amount),
clamp(0.0, 1.0, g + amount),
clamp(0.0, 1.0, b + amount))
+
def generateColorscheme(masterColor, keys, light=0.06):
"""
Generates a dictionary where the keys match the keys argument and
@@ -1121,7 +1116,7 @@ class DBProgress(object):
def update(self, combo, progressbar, callback, dbname=''):
self.db_info = None
- thread = threading.Thread(target=self.start).start()
+ threading.Thread(target=self.start).start()
gobject.timeout_add(100, self.end, combo, progressbar, callback,
dbname)
@@ -1206,7 +1201,8 @@ class RPCProgress(object):
hbox.pack_start(img, expand=True, fill=False)
vbox2 = gtk.VBox(False, 0)
label = gtk.Label()
- label.set_markup(''+_('Operation in progress')+'')
+ label.set_markup(
+ '' + _('Operation in progress') + '')
label.set_alignment(0.0, 0.5)
vbox2.pack_start(label, expand=True, fill=False)
vbox2.pack_start(gtk.HSeparator(), expand=True, fill=True)
@@ -1272,8 +1268,8 @@ COLOR_SCHEMES = {
}
COLORS = {
- 'invalid':'#ff6969',
- 'required':'#d2d2ff',
+ 'invalid': '#ff6969',
+ 'required': '#d2d2ff',
}
DT_FORMAT = '%Y-%m-%d'
@@ -1286,7 +1282,7 @@ FLOAT_TIME_CONV = {
'w': 168,
'd': 24,
'h': 1,
- 'm': 1.0/60,
+ 'm': 1.0 / 60,
}
FLOAT_TIME_SEPS = {
@@ -1298,6 +1294,7 @@ FLOAT_TIME_SEPS = {
'm': _('m'),
}
+
def text_to_float_time(text, conv=None):
try:
try:
@@ -1340,6 +1337,7 @@ def text_to_float_time(text, conv=None):
except ValueError:
return 0.0
+
def float_time_to_text(val, conv=None):
if conv:
tmp_conv = FLOAT_TIME_CONV.copy()
@@ -1362,7 +1360,7 @@ def float_time_to_text(val, conv=None):
val = val - days * conv['d']
hours = int(val)
val = val - hours
- mins = int((val% 1 + 0.01) / conv['m'])
+ mins = int((val % 1 + 0.01) / conv['m'])
if years:
value += ' ' + locale.format('%d', years, True) + FLOAT_TIME_SEPS['Y']
if months:
@@ -1376,6 +1374,7 @@ def float_time_to_text(val, conv=None):
value = value.strip()
return value
+
def filter_domain(domain):
'''
Return the biggest subset of domain with only AND operator
@@ -1394,23 +1393,23 @@ def filter_domain(domain):
return res
_ALLOWED_CODES = set(dis.opmap[x] for x in [
- 'POP_TOP','ROT_TWO','ROT_THREE','ROT_FOUR','DUP_TOP',
- 'BUILD_LIST','BUILD_MAP','BUILD_TUPLE',
- 'LOAD_CONST','RETURN_VALUE','STORE_SUBSCR',
- 'UNARY_POSITIVE','UNARY_NEGATIVE','UNARY_NOT',
- 'UNARY_INVERT','BINARY_POWER','BINARY_MULTIPLY',
- 'BINARY_DIVIDE','BINARY_FLOOR_DIVIDE','BINARY_TRUE_DIVIDE',
- 'BINARY_MODULO','BINARY_ADD','BINARY_SUBTRACT',
- 'BINARY_LSHIFT','BINARY_RSHIFT','BINARY_AND','BINARY_XOR', 'BINARY_OR',
- 'STORE_MAP', 'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR',
- 'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'JUMP_ABSOLUTE',
- 'DELETE_NAME', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_IF_FALSE_OR_POP',
- 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',
- 'BINARY_SUBSCR',
- ] if x in dis.opmap)
+ 'POP_TOP', 'ROT_TWO', 'ROT_THREE', 'ROT_FOUR', 'DUP_TOP', 'BUILD_LIST',
+ 'BUILD_MAP', 'BUILD_TUPLE', 'LOAD_CONST', 'RETURN_VALUE',
+ 'STORE_SUBSCR', 'UNARY_POSITIVE', 'UNARY_NEGATIVE', 'UNARY_NOT',
+ 'UNARY_INVERT', 'BINARY_POWER', 'BINARY_MULTIPLY', 'BINARY_DIVIDE',
+ 'BINARY_FLOOR_DIVIDE', 'BINARY_TRUE_DIVIDE', 'BINARY_MODULO',
+ 'BINARY_ADD', 'BINARY_SUBTRACT', 'BINARY_LSHIFT', 'BINARY_RSHIFT',
+ 'BINARY_AND', 'BINARY_XOR', 'BINARY_OR', 'STORE_MAP', 'LOAD_NAME',
+ 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR', 'STORE_NAME', 'GET_ITER',
+ 'FOR_ITER', 'LIST_APPEND', 'JUMP_ABSOLUTE', 'DELETE_NAME',
+ 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_IF_FALSE_OR_POP',
+ 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',
+ 'BINARY_SUBSCR',
+ ] if x in dis.opmap)
_SAFE_EVAL_CACHE = {}
+
def safe_eval(source, data=None):
if '__subclasses__' in source:
raise ValueError('__subclasses__ not allowed')
@@ -1447,6 +1446,7 @@ def safe_eval(source, data=None):
'dict': dict,
}}, data)
+
def timezoned_date(date):
if pytz and rpc.CONTEXT.get('timezone'):
lzone = pytz.timezone(rpc.CONTEXT['timezone'])
@@ -1456,6 +1456,7 @@ def timezoned_date(date):
date = ldt
return date
+
def humanize(size):
for x in ('bytes', 'KB', 'MB', 'GB', 'TB', 'PB'):
if size < 1000:
diff --git a/tryton/common/date_widget.py b/tryton/common/date_widget.py
index f6162a3810..a11edd1fa9 100644
--- a/tryton/common/date_widget.py
+++ b/tryton/common/date_widget.py
@@ -24,6 +24,7 @@ mapping = {
'%p': ('__', '([_ AP][_ M])'),
}
+
class DateEntry(gtk.Entry):
def __init__(self, format, callback=None, callback_process=None):
@@ -68,7 +69,8 @@ class DateEntry(gtk.Entry):
return
if self.mode_cmd:
- if self.callback: self.callback(value)
+ if self.callback:
+ self.callback(value)
self.stop_emission('insert-text')
return
@@ -110,7 +112,8 @@ class DateEntry(gtk.Entry):
end = len(self.initial_value)
if end < 0:
end = 0
- while (start > 0) and (self.initial_value[start] not in ['_', ' ','0','X']):
+ while (start > 0
+ and self.initial_value[start] not in ['_', ' ', '0', 'X']):
start -= 1
text = self.get_text()
text = text[:start] + self.initial_value[start:end] + text[end:]
@@ -179,15 +182,16 @@ class DateEntry(gtk.Entry):
for a in range(len(self.initial_value)):
if self.initial_value[a] == text[a]:
- text = text[:a] + default[a] + text[a+1:]
+ text = text[:a] + default[a] + text[a + 1:]
return text
def test_date(self, text):
default = datetime_strftime(datetime.datetime(2000, 1, 1),
self.format)
try:
- time.strptime(self.compute_date(text, default=default, year='2000'),
- self.format)
+ time.strptime(
+ self.compute_date(text, default=default, year='2000'),
+ self.format)
except ValueError:
return False
return True
@@ -287,7 +291,8 @@ class ComplexEntry(gtk.HBox):
self.widget_cmd.show()
self._date_cb(event)
else:
- if hasattr(event, 'keyval') and not event.keyval == gtk.keysyms.Escape:
+ if (hasattr(event, 'keyval')
+ and not event.keyval == gtk.keysyms.Escape):
cmd = self.widget_cmd.get_text()
dt = self.widget.date_get() or datetime.datetime.now()
res = compute_date(cmd, dt, self.widget.format)
@@ -296,6 +301,7 @@ class ComplexEntry(gtk.HBox):
self.widget_cmd.set_text('')
self.widget_cmd.hide()
+
def compute_date(cmd, dt, format):
lst = {
'^=(\d+)d$': lambda dt, r: dt + \
@@ -320,8 +326,8 @@ def compute_date(cmd, dt, format):
relativedelta(months=int(r.group(1))),
'^([\\+-]\d+)y$': lambda dt, r: dt + \
relativedelta(years=int(r.group(1))),
- '^=$': lambda dt,r: datetime.datetime.now(),
- '^-$': lambda dt,r: False
+ '^=$': lambda dt, r: datetime.datetime.now(),
+ '^-$': lambda dt, r: False
}
for r, f in lst.items():
groups = re.match(r, cmd)
@@ -336,6 +342,7 @@ def compute_date(cmd, dt, format):
if __name__ == '__main__':
win = gtk.Window()
win.set_title('gtk.Entry subclass')
+
def cb(window, event):
gtk.main_quit()
win.connect('delete-event', cb)
diff --git a/tryton/common/datetime_strftime.py b/tryton/common/datetime_strftime.py
index d125d8d204..2420eeeeea 100644
--- a/tryton/common/datetime_strftime.py
+++ b/tryton/common/datetime_strftime.py
@@ -3,6 +3,7 @@
#Copyright (c) 2002-2007 John D. Hunter; All Rights Reserved
import time
+
def datetime_strftime(dt, fmt):
'''
Allow datetime strftime formatting for years before 1900.
@@ -46,5 +47,5 @@ def datetime_strftime(dt, fmt):
s = s1
syear = "%04d" % (dt.year,)
for site in sites:
- s = s[:site] + syear + s[site+4:]
+ s = s[:site] + syear + s[site + 4:]
return s
diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py
index 8da0a6aa2a..5b7a125077 100644
--- a/tryton/common/domain_inversion.py
+++ b/tryton/common/domain_inversion.py
@@ -4,6 +4,7 @@
import operator
import types
+
def in_(a, b):
if isinstance(a, (list, tuple)):
return any(operator.contains(b, x) for x in a)
@@ -28,6 +29,7 @@ OPERATORS = {
'not child_of': lambda a, b: True,
}
+
def locale_part(expression, field_name):
if expression == field_name:
return 'id'
@@ -36,12 +38,14 @@ def locale_part(expression, field_name):
return local
return expression
+
def is_leaf(expression):
return (isinstance(expression, (list, tuple))
and len(expression) > 2
and isinstance(expression[1], basestring)
and expression[1] in OPERATORS)
+
def eval_leaf(part, context, boolop=operator.and_):
field, operand, value = part[:3]
if '.' in field:
@@ -54,6 +58,7 @@ def eval_leaf(part, context, boolop=operator.and_):
return True
return OPERATORS[operand](context[field], value)
+
def inverse_leaf(domain):
if domain in ('AND', 'OR'):
return domain
@@ -67,6 +72,7 @@ def inverse_leaf(domain):
else:
return map(inverse_leaf, domain)
+
def eval_domain(domain, context, boolop=operator.and_):
"compute domain boolean value according to the context"
if is_leaf(domain):
@@ -83,6 +89,7 @@ def eval_domain(domain, context, boolop=operator.and_):
return boolop(eval_domain(domain[0], context),
eval_domain(domain[1:], context, boolop))
+
def localize_domain(domain, field_name=None):
"returns only locale part of domain. eg: langage.code -> code"
if domain in ('AND', 'OR', True, False):
@@ -97,6 +104,7 @@ def localize_domain(domain, field_name=None):
else:
return [localize_domain(part, field_name) for part in domain]
+
def unlocalize_domain(domain, fieldname):
if domain in ('AND', 'OR', True, False):
return domain
@@ -105,6 +113,7 @@ def unlocalize_domain(domain, fieldname):
else:
return [unlocalize_domain(part, fieldname) for part in domain]
+
def simplify(domain):
"remove unused domain delimiter"
if is_leaf(domain):
@@ -120,6 +129,7 @@ def simplify(domain):
else:
return [simplify(branch) for branch in domain]
+
def merge(domain, domoperator=None):
if not domain or domain in ('AND', 'OR'):
return []
@@ -146,6 +156,7 @@ def parse(domain):
else:
return And(domain[1:] if domain[0] == 'AND' else domain)
+
def domain_inversion(domain, symbol, context=None):
"""compute an inversion of the domain eventually the context is used to
simplify the expression"""
@@ -169,7 +180,10 @@ class And(object):
self.variables |= expression.variables
def base(self, expression):
- return expression if '.' not in expression else expression.split('.')[0]
+ if '.' not in expression:
+ return expression
+ else:
+ return expression.split('.')[0]
def inverse(self, symbol, context):
result = []
@@ -209,8 +223,8 @@ class Or(And):
if (symbol not in self.variables
and not known_variables >= self.variables):
# In this case we don't know anything about this OR part, we
- # consider it to be True (because people will have the constraint on
- # this part later).
+ # consider it to be True (because people will have the constraint
+ # on this part later).
return True
for part in self.branches:
if isinstance(part, And):
@@ -244,6 +258,7 @@ class Or(And):
else:
return simplify(['OR'] + result)
+
# Test stuffs
def test_simple_inversion():
domain = [['x', '=', 3]]
@@ -258,6 +273,7 @@ def test_simple_inversion():
domain = [['x.id', '>', 5]]
assert domain_inversion(domain, 'x') == [['x.id', '>', 5]]
+
def test_and_inversion():
domain = [['x', '=', 3], ['y', '>', 5]]
assert domain_inversion(domain, 'x') == [['x', '=', 3]]
@@ -274,11 +290,13 @@ def test_and_inversion():
assert domain_inversion(domain, 'y', {'x': 3}) == [['y', '<', 3]]
assert domain_inversion(domain, 'x') == [['x.id', '>', 5]]
+
def test_or_inversion():
domain = ['OR', ['x', '=', 3], ['y', '>', 5], ['z', '=', 'abc']]
assert domain_inversion(domain, 'x') == [['x', '=', 3]]
assert domain_inversion(domain, 'x', {'y': 4}) == [['x', '=', 3]]
- assert domain_inversion(domain, 'x', {'y': 4, 'z': 'ab'}) == [['x', '=', 3]]
+ assert domain_inversion(domain, 'x', {'y': 4, 'z': 'ab'}) ==\
+ [['x', '=', 3]]
assert domain_inversion(domain, 'x', {'y': 7}) == True
assert domain_inversion(domain, 'x', {'y': 7, 'z': 'b'}) == True
assert domain_inversion(domain, 'x', {'z': 'abc'}) == True
@@ -299,6 +317,7 @@ def test_or_inversion():
assert domain_inversion(domain, 'length', {'length': 0, 'name': 'n'}) ==\
[['length', '>', 5]]
+
def test_orand_inversion():
domain = ['OR', [['x', '=', 3], ['y', '>', 5], ['z', '=', 'abc']],
[['x', '=', 4]], [['y', '>', 6]]]
@@ -308,6 +327,7 @@ def test_orand_inversion():
assert domain_inversion(domain, 'x', {'y': 7}) == True
assert domain_inversion(domain, 'x', {'z': 'ab'}) == True
+
def test_andor_inversion():
domain = [['OR', ['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]]
assert domain_inversion(domain, 'z') == [['z', '=', 3]]
@@ -315,6 +335,7 @@ def test_andor_inversion():
assert domain_inversion(domain, 'z', {'x': 5, 'y': 5}) == False
assert domain_inversion(domain, 'z', {'x': 5, 'y': 7}) == [['z', '=', 3]]
+
def test_andand_inversion():
domain = [[['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]]
assert domain_inversion(domain, 'z') == [['z', '=', 3]]
@@ -325,6 +346,7 @@ def test_andand_inversion():
domain = [[['x', '=', 4], ['y', '>', 6], ['z', '=', 2]], [['w', '=', 2]]]
assert domain_inversion(domain, 'z', {'x': 4}) == [['z', '=', 2]]
+
def test_oror_inversion():
domain = ['OR', ['OR', ['x', '=', 3], ['y', '>', 5]],
['OR', ['x', '=', 2], ['z', '=', 'abc']],
@@ -342,6 +364,7 @@ def test_oror_inversion():
assert domain_inversion(domain, 'x', {'y': 4, 'z': 'b'}) == \
['OR', [['x', '=', 3]], [['x', '=', 2]]]
+
def test_parse():
domain = parse([['x', '=', 5]])
assert domain.variables == set('x')
@@ -352,6 +375,7 @@ def test_parse():
domain = parse([[['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]])
assert domain.variables == set('xyz')
+
def test_simplify():
domain = [['x', '=', 3]]
assert simplify(domain) == [['x', '=', 3]]
@@ -364,6 +388,7 @@ def test_simplify():
domain = ['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]]
assert simplify(domain) == ['OR', ['x', '=', 3], [['y', '=', 5]]]
+
def test_merge():
domain = [['x', '=', 6], ['y', '=', 7]]
assert merge(domain) == ['AND', ['x', '=', 6], ['y', '=', 7]]
@@ -391,6 +416,7 @@ def test_merge():
['OR', ['c', '=', 3], ['AND', ['d', '=', 4], ['d2', '=', 6]]],
['d', '=', 5], ['e', '=', 6], ['f', '=', 7]]
+
def test_evaldomain():
domain = [['x', '>', 5]]
assert eval_domain(domain, {'x': 6})
@@ -423,6 +449,7 @@ 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]]
diff --git a/tryton/common/environment.py b/tryton/common/environment.py
index 84a29dec40..3f34580f50 100644
--- a/tryton/common/environment.py
+++ b/tryton/common/environment.py
@@ -20,8 +20,8 @@ class EvalEnvironment(dict):
if self.eval_type == 'eval':
return self.parent.get_eval(check_load=self.check_load)[item]
else:
- return self.parent.group.fields[item].get_on_change_value(self.parent,
- check_load=self.check_load)
+ return self.parent.group.fields[item].get_on_change_value(
+ self.parent, check_load=self.check_load)
def __getattr__(self, item):
try:
diff --git a/tryton/common/tdp.py b/tryton/common/tdp.py
index 9b7f372bd1..1363b85840 100644
--- a/tryton/common/tdp.py
+++ b/tryton/common/tdp.py
@@ -32,6 +32,7 @@ OPERATORS = set((
'ilike',
'not ilike'))
+
def operator(field):
type_ = field['type'] if field else ''
if type_ in ('char', 'text', 'many2one') or not field:
@@ -68,7 +69,7 @@ def cast(field, value):
return key
return value
elif type_ == 'datetime':
- value = value.replace(' : ', ':') # Parser add spaces arround :
+ value = value.replace(' : ', ':') # Parser add spaces arround :
try:
value = datetime.datetime(*time.strptime(value,
date_format() + ' ' + HM_FORMAT)[:6])
@@ -87,6 +88,7 @@ def cast(field, value):
else:
return value
+
def quote(value):
for test in (':', ' '):
if test in value:
@@ -127,15 +129,16 @@ class Base(object):
right = property(_get_right, _set_right)
def domain(self, parent_field=None):
- raise NotImplementedError("domain method is missing on %s" % \
- self.__class__)
+ raise NotImplementedError("domain method is missing on %s"
+ % self.__class__)
def complete_fmt(self, left, value, right):
return (self.fmt % (left, value, right)).strip()
def complete(self, parent_field=None):
left = self.left and tuple(self.left.complete()) or ('',)
- right = self.right and tuple(self.right.complete(parent_field)) or ('',)
+ right = (self.right and tuple(self.right.complete(parent_field))
+ or ('',))
for lvalue in left:
for rvalue in right:
@@ -144,15 +147,15 @@ class Base(object):
def split(self, words=""):
field, value = None, ' '.join(words)
for i in xrange(len(words)):
- candidate = ' '.join(words[-i-1:])
+ candidate = ' '.join(words[-i - 1:])
if candidate.lower() in self.parser.dom_fields:
field = self.parser.dom_fields[candidate.lower()]
- value = ' '.join(words[:-i-1])
+ value = ' '.join(words[:-i - 1])
return field, value
def __str__(self, prefix=''):
- res = '%s[%s] %s'% (prefix, self.pos or 'root', self.value)
+ res = '%s[%s] %s' % (prefix, self.pos or 'root', self.value)
res = res.ljust(30) + str(type(self))
if self.left:
res += "\n" + self.left.__str__(' ' + prefix)
@@ -202,8 +205,8 @@ class Literal(Base):
candidate = word + candidate
for field in suggestions:
if field.lower().startswith(candidate.lower()):
- if words[pos+1:]:
- new_item = ' '.join(reversed(words[pos+1:]))
+ if words[pos + 1:]:
+ new_item = ' '.join(reversed(words[pos + 1:]))
new_item += ' ' + field
else:
new_item = field
@@ -221,7 +224,7 @@ class Literal(Base):
if field.lower().startswith(candidate.lower()):
new_item = quote(field)
- if (i-len(words) < 0) and words[i-len(words):]:
+ if (i - len(words) < 0) and words[i - len(words):]:
find = False
for item in self.suggest(words[i - len(words):],
self.parser.sugg_fields):
@@ -230,7 +233,7 @@ class Literal(Base):
find = True
if find:
break
- new_item += ' ' + ' '.join(words[i-len(words):])
+ new_item += ' ' + ' '.join(words[i - len(words):])
yield new_item
break
@@ -246,7 +249,8 @@ class Literal(Base):
if parent_field:
if parent_field['type'] in ('selection', 'reference', 'boolean'):
if parent_field['type'] in ('selection', 'reference'):
- suggestions = tuple(x[1] for x in parent_field['selection'])
+ suggestions = tuple(x[1]
+ for x in parent_field['selection'])
else:
suggestions = (_('Y'), _('Yes'), _('True'), '1', _('N'),
_('No'), _('False'), '0')
@@ -369,12 +373,13 @@ class Colon(Base, InfixMixin):
if field['type'] in ('char', 'text', 'many2one'):
value += '%'
- domain.append((field['name'] , operator(field), value))
+ domain.append((field['name'], operator(field), value))
else:
domain.extend(self.right.domain(field))
return domain
+
class DoubleDot(Base, InfixMixin):
value = '..'
lbp = 70
@@ -436,7 +441,7 @@ class Comma(Base, InfixMixin):
node = node.left
walk(self.left, values)
- return [(field_name, 'in' , list(reversed(values)))]
+ return [(field_name, 'in', list(reversed(values)))]
class Comparator(Base, InfixMixin):
@@ -464,15 +469,19 @@ class Comparator(Base, InfixMixin):
res.append((field_name, self.value, value))
return res
+
class LessThan(Comparator):
value = '<'
+
class LessThanOrEqual(Comparator):
value = '<='
+
class BiggerThan(Comparator):
value = '>'
+
class BiggerThanOrEqual(Comparator):
value = '>='
@@ -519,6 +528,7 @@ class Not(Base, InfixMixin):
res.append((field_name, oper, value))
return res
+
class NotEqual(Equal):
value = '!='
fmt = '%s%s%s'
@@ -574,6 +584,7 @@ class CloseParenthesis(Base):
return self.left.domain()
return []
+
class OpenParenthesis(Base):
value = '('
lbp = 10
@@ -701,7 +712,7 @@ class DomainParser:
return left
def next_token(self):
- try :
+ try:
new_tk = self.token_flow.next()
except StopIteration:
return End(self)
@@ -808,6 +819,7 @@ class DomainParser:
domain = domain[1:]
else:
nary = ' '
+
def format(expression):
if (isinstance(expression, (list, tuple))
and len(expression) > 2
@@ -892,6 +904,7 @@ def test_parser():
}
return DomainParser(fields)
+
def test_selection_complete():
parser = test_parser()
assert list(parser.parse('S').complete()) == ['Selection:']
@@ -912,6 +925,7 @@ def test_selection_complete():
assert list(parser.parse('Selection: Ham foo').complete()) == [
'Selection: Ham foo']
+
def test_selection_domain():
parser = test_parser()
assert parser.parse('S').domain() == [('rec_name', 'ilike', 'S%')]
@@ -923,6 +937,7 @@ def test_selection_domain():
assert parser.parse('Selection: Ham; Spam').domain() == [
('selection', 'in', ['ham', 'spam'])]
+
def test_selection_string():
parser = test_parser()
assert parser.string([]) == ''
@@ -933,6 +948,7 @@ def test_selection_string():
assert parser.string([('selection', 'in', ['ham', 'spam'])]) == \
'Selection: Ham; Spam'
+
def test_boolean_complete():
parser = test_parser()
assert list(parser.parse('b').complete()) == ['Boolean:']
@@ -943,13 +959,15 @@ def test_boolean_complete():
assert list(parser.parse('boolean: y').complete()) == ['Boolean: Y',
'Boolean: Yes']
assert list(parser.parse('boolean: 1').complete()) == ['Boolean: 1']
- assert list(parser.parse('boolean: false').complete()) == ['Boolean: False']
+ assert list(parser.parse('boolean: false').complete()) ==\
+ ['Boolean: False']
assert list(parser.parse('boolean: f').complete()) == ['Boolean: False']
assert list(parser.parse('boolean: n').complete()) == ['Boolean: N',
'Boolean: No']
assert list(parser.parse('boolean: 0').complete()) == ['Boolean: 0']
assert list(parser.parse('boolean: =1').complete()) == ['Boolean: =1']
+
def test_boolean_domain():
parser = test_parser()
assert parser.parse('B').domain() == [('rec_name', 'ilike', 'B%')]
@@ -961,6 +979,7 @@ def test_boolean_domain():
assert parser.parse('Boolean: true; false').domain() == [
('boolean', 'in', [True, False])]
+
def test_boolean_string():
parser = test_parser()
assert parser.string([('boolean', '=', True)]) == 'Boolean: True'
@@ -968,6 +987,7 @@ def test_boolean_string():
assert parser.string([('boolean', 'in', [True, False])]) == \
'Boolean: True; False'
+
def test_char_complete():
parser = test_parser()
assert list(parser.parse('c').complete()) == ['Char:']
@@ -977,6 +997,7 @@ def test_char_complete():
'Char: "foo bar"']
assert list(parser.parse('char: =foo').complete()) == ['Char: =foo']
+
def test_char_domain():
parser = test_parser()
assert parser.parse('c').domain() == [('rec_name', 'ilike', 'c%')]
@@ -989,7 +1010,9 @@ def test_char_domain():
assert parser.parse('Char: !=foo').domain() == [('char', '!=', 'foo')]
assert parser.parse('Char: != foo').domain() == [('char', '!=', 'foo')]
assert parser.parse('Char: 2; 3').domain() == [('char', 'in', ['2', '3'])]
- assert parser.parse('Char:! 2; 3').domain() == [('char', 'not in', ['2', '3'])]
+ assert parser.parse('Char:! 2; 3').domain() == [
+ ('char', 'not in', ['2', '3'])]
+
def test_char_string():
parser = test_parser()
@@ -1007,6 +1030,7 @@ def test_numeric_complete():
assert list(parser.parse('numeric: 100').complete()) == [
'Numeric: 100']
+
def test_numeric_domain():
parser = test_parser()
assert parser.parse('Numeric: >100').domain() == [
@@ -1022,17 +1046,20 @@ def test_numeric_domain():
assert parser.parse('Numeric: 2; 3').domain() == [
('numeric', 'in', [Decimal(2), Decimal(3)])]
+
def test_numeric_string():
parser = test_parser()
assert parser.string([('numeric', '=', Decimal(100))]) == 'Numeric: 100.00'
assert parser.string([('numeric', 'in', [Decimal(2), Decimal(3)])]) == \
'Numeric: 2.00; 3.00'
+
def test_integer_complete():
parser = test_parser()
assert list(parser.parse('integer: 42').complete()) == ['Integer: 42']
assert list(parser.parse('integer: 2;3').complete()) == ['Integer: 2; 3']
+
def test_integer_domain():
parser = test_parser()
assert parser.parse('Integer: >42').domain() == [
@@ -1050,6 +1077,7 @@ def test_integer_domain():
assert parser.parse('Integer: 2; 3').domain() == [
('integer', 'in', [2, 3])]
+
def test_integer_string():
parser = test_parser()
assert parser.string([('integer', '=', 42)]) == 'Integer: 42'
@@ -1061,6 +1089,7 @@ def test_float_complete():
parser = test_parser()
assert list(parser.parse('float: 3.14').complete()) == ['Float: 3.14']
+
def test_float_domain():
parser = test_parser()
assert parser.parse('Float: >3.14').domain() == [
@@ -1076,6 +1105,7 @@ def test_float_domain():
assert parser.parse('Float: foo').domain() == [
('float', '=', False)]
+
def test_float_string():
parser = test_parser()
assert parser.string([('float', '=', 3.14)]) == 'Float: 3.14'
@@ -1084,6 +1114,7 @@ def test_float_string():
assert parser.string([('float', 'not in', [3.14, 42])]) == \
'Float: !3.14; 42.00'
+
def test_date_complete():
today = datetime.date.today()
today_str = datetime_strftime(today, date_format())
@@ -1113,6 +1144,7 @@ def test_date_complete():
'Date: 12/04/2002',
]
+
def test_date_domain():
today = datetime.date.today()
today_str = datetime_strftime(today, date_format())
@@ -1127,7 +1159,9 @@ def test_date_domain():
assert parser.parse('Date: 12/4/2002').domain() == [
('date', '=', datetime.date(2002, 12, 4))]
assert parser.parse('Date: 12/4/2002; 1/1/1970').domain() == [
- ('date', 'in', [datetime.date(2002, 12, 4), datetime.date(1970, 1, 1)])]
+ ('date', 'in', [datetime.date(2002, 12, 4),
+ datetime.date(1970, 1, 1)])]
+
def test_date_string():
parser = test_parser()
@@ -1138,6 +1172,7 @@ def test_date_string():
datetime.date(1970, 1, 1)])]) == \
'Date: 12/04/2002; 01/01/1970'
+
def test_datetime_complete():
today = datetime.date.today()
today_str = datetime_strftime(today, date_format())
@@ -1149,6 +1184,7 @@ def test_datetime_complete():
assert list(parser.parse('Date Time: ' + today_str + ' 12:30:00'
).complete()) == ['Date Time: "' + today_str + ' 12:30:00"']
+
def test_datetime_domain():
today = datetime.date.today()
today_str = datetime_strftime(today, date_format())
@@ -1170,6 +1206,7 @@ def test_datetime_domain():
datetime.datetime.combine(datetime.date(1970, 1, 1),
datetime.time.min)])]
+
def test_datetime_string():
parser = test_parser()
assert parser.string([('datetime', '=', False)]) == 'Date Time: ='
@@ -1184,6 +1221,7 @@ def test_datetime_string():
datetime.time.min)])]) == \
'Date Time: 12/04/2002; 01/01/1970'
+
def test_composite_complete():
today = datetime.date.today()
today_str = datetime_strftime(today, date_format())
@@ -1230,6 +1268,7 @@ def test_composite_complete():
'Selection: Ham or Selection: Spamham',
]
+
def test_composite_domain():
parser = test_parser()
assert parser.parse('char: foo boolean: false').domain() == [
@@ -1250,9 +1289,9 @@ def test_composite_domain():
assert parser.parse('char: foo or char: bar or boolean: 0').domain() == [
'OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%'),
('boolean', '=', False)]
- assert parser.parse('(char: foo or char: bar) and boolean: 1').domain() == [
- ['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
- ('boolean', '=', True)]
+ assert parser.parse('(char: foo or char: bar) and boolean: 1').domain() ==\
+ [['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
+ ('boolean', '=', True)]
assert parser.parse('(char: foo or char: bar) boolean: 1').domain() == [
['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
('boolean', '=', True)]
@@ -1260,15 +1299,18 @@ def test_composite_domain():
).domain() == [
['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
('datetime', '=', datetime.datetime(2002, 12, 4, 0, 0))]
- assert parser.parse('(char: foo or char: bar) Date Time: 12/4/2002').domain() == [
- ['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
- ('datetime', '=', datetime.datetime(2002, 12, 4, 0, 0))]
- assert parser.parse('char: foo or (char: bar and boolean: 1)').domain() == [
- 'OR', ('char', 'ilike', 'foo%'), [
- ('char', 'ilike', 'bar%'), ('boolean', '=', True)]]
- assert parser.parse('char: foo and (char: bar or boolean: 0)').domain() == [
- ('char', 'ilike', 'foo%'),
- ['OR', ('char', 'ilike', 'bar%'), ('boolean', '=', False)]]
+ assert parser.parse(
+ '(char: foo or char: bar) Date Time: 12/4/2002').domain() == [
+ ['OR', ('char', 'ilike', 'foo%'), ('char', 'ilike', 'bar%')],
+ ('datetime', '=', datetime.datetime(2002, 12, 4, 0, 0))]
+ assert parser.parse(
+ 'char: foo or (char: bar and boolean: 1)').domain() == [
+ 'OR', ('char', 'ilike', 'foo%'), [
+ ('char', 'ilike', 'bar%'), ('boolean', '=', True)]]
+ assert parser.parse(
+ 'char: foo and (char: bar or boolean: 0)').domain() == [
+ ('char', 'ilike', 'foo%'),
+ ['OR', ('char', 'ilike', 'bar%'), ('boolean', '=', False)]]
assert parser.parse('char: foo (char: bar or boolean: 0)').domain() == [
('char', 'ilike', 'foo%'),
['OR', ('char', 'ilike', 'bar%'), ('boolean', '=', False)]]
@@ -1338,6 +1380,7 @@ def test_composite_string():
['OR', ('char', 'ilike', 'bar%'), ('boolean', '=', False)]]) == \
'Char: foo (Char: bar or Boolean: False)'
+
def test_quote_complete():
parser = test_parser()
assert list(parser.parse('"char"').complete()) == ['Char:']
@@ -1348,12 +1391,14 @@ def test_quote_complete():
assert list(parser.parse('Char: "Boolean: false"').complete()) == [
'Char: "Boolean: false"']
+
def test_quote_domain():
parser = test_parser()
assert parser.parse('"char"').domain() == [('rec_name', 'ilike', 'char%')]
assert parser.parse('char: "foo bar"').domain() == [
('char', 'ilike', 'foo bar%')]
+
def test_quote_string():
parser = test_parser()
assert parser.string([('rec_name', 'ilike', 'char:%')]) == '"char:"'
@@ -1361,16 +1406,19 @@ def test_quote_string():
assert parser.string([('char', 'ilike', 'Boolean: false%')]) == \
'Char: "Boolean: false"'
+
def test_column():
parser = test_parser()
assert parser.parse(':').domain() == []
assert parser.parse('::').domain() == []
assert parser.parse(': foo').domain() == [('rec_name', 'ilike', 'foo%')]
assert parser.parse('foo :').domain() == [('rec_name', 'ilike', 'foo%')]
- assert parser.parse(': foo b').domain() == [('rec_name', 'ilike', 'foo b%')]
+ assert parser.parse(': foo b').domain() == [
+ ('rec_name', 'ilike', 'foo b%')]
assert parser.parse('": foo b"').domain() == [
('rec_name', 'ilike', ': foo b%')]
+
def test_double_dot():
parser = test_parser()
assert parser.parse('Integer: 0..42').domain() == [
@@ -1384,6 +1432,7 @@ def test_double_dot():
assert parser.parse('Integer: 0..42 Char: foo').domain() == [
('integer', '>=', 0), ('integer', '<', 42), ('char', 'ilike', 'foo%')]
+
def test_comma():
parser = test_parser()
assert parser.parse('Char: foo; bar').domain() == [
@@ -1409,6 +1458,7 @@ def test_comma():
assert parser.parse('Integer: 0; 1;; 2; 3').domain() == [
('integer', 'in', [0, 1, 0, 2, 3])]
+
def test_comparator():
parser = test_parser()
assert parser.parse('< foo').domain() == [
@@ -1430,6 +1480,7 @@ def test_comparator():
assert parser.parse('foo <').domain() == [
('rec_name', 'ilike', 'foo%'), ('rec_name', '<', '')]
+
def test_str():
parser = test_parser()
assert str(parser.parse('foo bar spam ham =')) == '''\
diff --git a/tryton/config.py b/tryton/config.py
index 4683034d29..d98e3cd18d 100644
--- a/tryton/config.py
+++ b/tryton/config.py
@@ -15,11 +15,13 @@ from tryton.exceptions import TrytonError
_ = gettext.gettext
+
def get_home_dir():
if os.name == 'nt':
return os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'])
return os.environ['HOME']
+
def get_config_dir():
if os.name == 'nt':
return os.path.join(os.environ['APPDATA'], '.config', 'tryton',
@@ -29,20 +31,6 @@ def get_config_dir():
if not os.path.isdir(get_config_dir()):
os.makedirs(get_config_dir(), 0700)
-def find_path(progs, args):
- if os.name == 'nt':
- return ''
- if sys.platform == 'darwin':
- return ''
- paths = [x for x in os.environ['PATH'].split(':')
- if os.path.isdir(x)]
- for dir in paths:
- for prog in progs:
- val = os.path.join(dir, prog)
- if os.path.isfile(val) or os.path.islink(val):
- return val + ' ' + args
- return ''
-
class ConfigManager(object):
"Config manager"
@@ -78,17 +66,6 @@ class ConfigManager(object):
'client.default_path': get_home_dir(),
'client.lang': locale.getdefaultlocale()[0],
'client.language_direction': 'ltr',
- 'client.actions': {
- 'odt': {0: find_path(['ooffice', 'ooffice2', 'libreoffice'], '"%s"'),
- 1: find_path(['ooffice', 'ooffice2', 'libreoffice'], '-p "%s"')},
- 'txt': {0: find_path(['ooffice', 'ooffice2', 'libreoffice'], '"%s"'),
- 1: find_path(['ooffice', 'ooffice2', 'libreoffice'], '-p "%s"')},
- 'pdf': {0: find_path(['evince', 'xpdf', 'gpdf',
- 'kpdf', 'epdfview', 'acroread'], '"%s"'), 1: ''},
- 'png': {0: find_path(['feh', 'display', 'qiv', 'eye'], '"%s"'), 1: ''},
- 'csv': {0: find_path(['ooffice', 'ooffice2', 'libreoffice'], '"%s"'),
- 1: find_path(['ooffice', 'ooffice2', 'libreoffice'], '-p "%s"')},
- },
'client.email': '',
'client.can_change_accelerators': False,
'client.limit': 1000,
@@ -128,18 +105,19 @@ class ConfigManager(object):
if opt.config and not os.path.isfile(opt.config):
raise TrytonError(_('File "%s" not found') % (opt.config,))
- self.rcfile = opt.config or os.path.join(get_config_dir(), 'tryton.conf')
+ self.rcfile = opt.config or os.path.join(
+ get_config_dir(), 'tryton.conf')
self.load()
for arg in ('log_level', 'log_logger'):
if getattr(opt, arg):
- self.options['logging.'+arg[4:]] = getattr(opt, arg)
+ self.options['logging.' + arg[4:]] = getattr(opt, arg)
if opt.verbose:
self.options['logging.default'] = 'INFO'
for arg in ('login', 'port', 'server'):
if getattr(opt, arg):
- self.options['login.'+arg] = getattr(opt, arg)
+ self.options['login.' + arg] = getattr(opt, arg)
def save(self):
try:
@@ -204,6 +182,7 @@ if not os.path.isdir(PIXMAPS_DIR):
TRYTON_ICON = gtk.gdk.pixbuf_new_from_file(
os.path.join(PIXMAPS_DIR, 'tryton-icon.png').encode('utf-8'))
+
def _data_dir():
data_dir = os.path.join(CURRENT_DIR, 'share', 'tryton')
if not os.path.isdir(data_dir):
diff --git a/tryton/fingerprints.py b/tryton/fingerprints.py
index 8c7f8069bd..101feda004 100644
--- a/tryton/fingerprints.py
+++ b/tryton/fingerprints.py
@@ -25,7 +25,6 @@ class Fingerprints(dict):
self[host] = sha1
def save(self):
- lines = []
with open(KNOWN_HOSTS_PATH, 'w') as known_hosts:
known_hosts.writelines('%s %s' % (host, sha1)
+ os.linesep for host, sha1 in self.iteritems())
@@ -33,7 +32,7 @@ class Fingerprints(dict):
def __setitem__(self, key, value):
assert isinstance(key, basestring)
if value:
- assert len(value) == 59 # len of formated sha1
+ assert len(value) == 59 # len of formated sha1
else:
value = ''
super(Fingerprints, self).__setitem__(key, value)
diff --git a/tryton/gui/main.py b/tryton/gui/main.py
index e50b6c48a7..7a2cd441e2 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -15,15 +15,13 @@ except ImportError:
import json
import webbrowser
import tryton.rpc as rpc
-from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, DATA_DIR, \
- get_config_dir
+from tryton.config import CONFIG, TRYTON_ICON, get_config_dir
import tryton.common as common
from tryton.action import Action
from tryton.exceptions import TrytonServerError, TrytonError
from tryton.gui.window import Window
from tryton.gui.window.preference import Preference
from tryton.gui.window import Limit
-from tryton.gui.window import FileActions
from tryton.gui.window import Email
from tryton.gui.window.dblogin import DBLogin
from tryton.gui.window.dbcreate import DBCreate
@@ -32,12 +30,10 @@ from tryton.gui.window.tips import Tips
from tryton.gui.window.about import About
from tryton.gui.window.shortcuts import Shortcuts
from tryton.gui.window.dbrestore import DBRestore
-import re
import tryton.translate as translate
import tryton.plugins
import pango
import time
-import threading
try:
import gtk_osxapplication
except ImportError:
@@ -82,7 +78,8 @@ class Main(object):
self.macapp = None
if gtk_osxapplication is not None:
self.macapp = gtk_osxapplication.OSXApplication()
- self.macapp.connect("NSApplicationBlockTermination", self.sig_close)
+ self.macapp.connect("NSApplicationBlockTermination",
+ self.sig_close)
gtk.accel_map_add_entry('/File/Connect', gtk.keysyms.O,
gtk.gdk.CONTROL_MASK)
@@ -101,7 +98,7 @@ class Main(object):
gtk.accel_map_add_entry('/Form/Save', gtk.keysyms.S,
gtk.gdk.CONTROL_MASK)
gtk.accel_map_add_entry('/Form/Duplicate', gtk.keysyms.D,
- gtk.gdk.CONTROL_MASK|gtk.gdk.SHIFT_MASK)
+ gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK)
gtk.accel_map_add_entry('/Form/Delete', gtk.keysyms.D,
gtk.gdk.CONTROL_MASK)
gtk.accel_map_add_entry('/Form/Next', gtk.keysyms.Page_Down,
@@ -112,10 +109,10 @@ class Main(object):
gtk.gdk.CONTROL_MASK)
gtk.accel_map_add_entry('/Form/Close', gtk.keysyms.W,
gtk.gdk.CONTROL_MASK)
- gtk.accel_map_add_entry('/Form/Previous Tab', gtk.keysyms.Page_Up,
- gtk.gdk.CONTROL_MASK)
- gtk.accel_map_add_entry('/Form/Next Tab', gtk.keysyms.Page_Down,
- gtk.gdk.CONTROL_MASK)
+ gtk.accel_map_add_entry('/Form/Previous Tab',
+ gtk.keysyms.Page_Up, gtk.gdk.CONTROL_MASK)
+ gtk.accel_map_add_entry('/Form/Next Tab',
+ gtk.keysyms.Page_Down, gtk.gdk.CONTROL_MASK)
gtk.accel_map_add_entry('/Form/Goto', gtk.keysyms.G,
gtk.gdk.CONTROL_MASK)
gtk.accel_map_add_entry('/Form/Reload', gtk.keysyms.R,
@@ -189,11 +186,6 @@ class Main(object):
self.sig_statusbar_show()
- if os.name == 'nt' or sys.platform == 'darwin':
- # Disable actions, on win32 we use os.startfile
- # and on mac we use /usr/bin/open
- self.menuitem_actions.set_sensitive(False)
-
# Adding a timer the check to requests
gobject.timeout_add(5 * 60 * 1000, self.request_set)
_MAIN.append(self)
@@ -259,6 +251,7 @@ class Main(object):
self.menuitem_shortcut = menuitem_shortcut
menubar.add(menuitem_shortcut)
menuitem_shortcut.set_accel_path('/Shortcuts')
+
def shortcut_activate(widget):
if (not menuitem_shortcut.get_submenu()
or not menuitem_shortcut.get_submenu().get_children()):
@@ -276,7 +269,7 @@ class Main(object):
if self.macapp is not None:
self.menubar.set_no_show_all(True)
self.macapp.set_menu_bar(self.menubar)
- self.macapp.insert_app_menu_item(self.aboutitem,0)
+ self.macapp.insert_app_menu_item(self.aboutitem, 0)
menuitem_file.show_all()
menuitem_user.show_all()
menuitem_options.show_all()
@@ -296,7 +289,8 @@ class Main(object):
if not update:
self.sb_username = gtk.Label()
self.sb_username.set_alignment(0.0, 0.5)
- self.status_hbox.pack_start(self.sb_username, True, True, padding=5)
+ self.status_hbox.pack_start(self.sb_username, True, True,
+ padding=5)
self.sb_requests = gtk.Label()
self.sb_requests.set_alignment(0.5, 0.5)
@@ -310,14 +304,16 @@ class Main(object):
self.secure_img = gtk.Image()
self.secure_img.set_from_stock('tryton-lock', gtk.ICON_SIZE_MENU)
- self.status_hbox.pack_start(self.secure_img, False, True, padding=2)
+ self.status_hbox.pack_start(self.secure_img, False, True,
+ padding=2)
self.status_hbox.show_all()
def _set_menu_file(self):
menu_file = gtk.Menu()
- imagemenuitem_connect = gtk.ImageMenuItem(_('_Connect...'), self.accel_group)
+ imagemenuitem_connect = gtk.ImageMenuItem(_('_Connect...'),
+ self.accel_group)
image = gtk.Image()
image.set_from_stock('tryton-connect', gtk.ICON_SIZE_MENU)
imagemenuitem_connect.set_image(image)
@@ -351,7 +347,8 @@ class Main(object):
image.set_from_stock('tryton-folder-new', gtk.ICON_SIZE_MENU)
imagemenuitem_db_new.set_image(image)
imagemenuitem_db_new.connect('activate', self.sig_db_new)
- imagemenuitem_db_new.set_accel_path('/File/Database/New Database')
+ imagemenuitem_db_new.set_accel_path(
+ '/File/Database/New Database')
menu_database.add(imagemenuitem_db_new)
imagemenuitem_db_restore = gtk.ImageMenuItem(_('_Restore Database...'))
@@ -359,7 +356,8 @@ class Main(object):
image.set_from_stock('tryton-folder-saved-search', gtk.ICON_SIZE_MENU)
imagemenuitem_db_restore.set_image(image)
imagemenuitem_db_restore.connect('activate', self.sig_db_restore)
- imagemenuitem_db_restore.set_accel_path('/File/Database/Restore Database')
+ imagemenuitem_db_restore.set_accel_path(
+ '/File/Database/Restore Database')
menu_database.add(imagemenuitem_db_restore)
imagemenuitem_db_dump = gtk.ImageMenuItem(_('_Backup Database...'))
@@ -367,7 +365,8 @@ class Main(object):
image.set_from_stock('tryton-save-as', gtk.ICON_SIZE_MENU)
imagemenuitem_db_dump.set_image(image)
imagemenuitem_db_dump.connect('activate', self.sig_db_dump)
- imagemenuitem_db_dump.set_accel_path('/File/Database/Backup Database')
+ imagemenuitem_db_dump.set_accel_path(
+ '/File/Database/Backup Database')
menu_database.add(imagemenuitem_db_dump)
imagemenuitem_db_drop = gtk.ImageMenuItem(_('Dro_p Database...'))
@@ -375,11 +374,12 @@ class Main(object):
image.set_from_stock('tryton-delete', gtk.ICON_SIZE_MENU)
imagemenuitem_db_drop.set_image(image)
imagemenuitem_db_drop.connect('activate', self.sig_db_drop)
- imagemenuitem_db_drop.set_accel_path('/File/Database/Drop Database')
+ imagemenuitem_db_drop.set_accel_path(
+ '/File/Database/Drop Database')
menu_database.add(imagemenuitem_db_drop)
-
- imagemenuitem_close = gtk.ImageMenuItem(_('_Quit...'), self.accel_group)
+ imagemenuitem_close = gtk.ImageMenuItem(_('_Quit...'),
+ self.accel_group)
image = gtk.Image()
image.set_from_stock('tryton-log-out', gtk.ICON_SIZE_MENU)
imagemenuitem_close.set_image(image)
@@ -404,7 +404,8 @@ class Main(object):
menu_user.add(gtk.SeparatorMenuItem())
- imagemenuitem_menu = gtk.ImageMenuItem(_('_Menu Reload'), self.accel_group)
+ imagemenuitem_menu = gtk.ImageMenuItem(_('_Menu Reload'),
+ self.accel_group)
image = gtk.Image()
image.set_from_stock('tryton-start-here', gtk.ICON_SIZE_MENU)
imagemenuitem_menu.set_image(image)
@@ -414,11 +415,11 @@ class Main(object):
imagemenuitem_menu_toggle = gtk.ImageMenuItem(_('_Menu Toggle'),
self.accel_group)
- imagemenuitem_menu_toggle.connect('activate', lambda *a: self.menu_toggle())
+ imagemenuitem_menu_toggle.connect('activate',
+ lambda *a: self.menu_toggle())
imagemenuitem_menu_toggle.set_accel_path('/User/Menu Toggle')
menu_user.add(imagemenuitem_menu_toggle)
-
imagemenuitem_home = gtk.ImageMenuItem(_('_Home'), self.accel_group)
image = gtk.Image()
image.set_from_stock('tryton-go-home', gtk.ICON_SIZE_MENU)
@@ -434,7 +435,8 @@ class Main(object):
image.set_from_stock('tryton-mail-message-new', gtk.ICON_SIZE_MENU)
imagemenuitem_send_request.set_image(image)
imagemenuitem_send_request.connect('activate', self.sig_request_new)
- imagemenuitem_send_request.set_accel_path('/User/Send a Request')
+ imagemenuitem_send_request.set_accel_path(
+ '/User/Send a Request')
menu_user.add(imagemenuitem_send_request)
imagemenuitem_open_request = gtk.ImageMenuItem(_('_Read my Requests'))
@@ -442,7 +444,8 @@ class Main(object):
image.set_from_stock('tryton-mail-message', gtk.ICON_SIZE_MENU)
imagemenuitem_open_request.set_image(image)
imagemenuitem_open_request.connect('activate', self.sig_request_open)
- imagemenuitem_open_request.set_accel_path('/User/Read my Requests')
+ imagemenuitem_open_request.set_accel_path(
+ '/User/Read my Requests')
menu_user.add(imagemenuitem_open_request)
return menu_user
@@ -460,7 +463,8 @@ class Main(object):
radiomenuitem_default = gtk.RadioMenuItem(label=_('_Default'))
radiomenuitem_default.connect('activate',
lambda x: self.sig_toolbar('default'))
- radiomenuitem_default.set_accel_path('/Options/Toolbar/Default')
+ radiomenuitem_default.set_accel_path(
+ '/Options/Toolbar/Default')
menu_toolbar.add(radiomenuitem_default)
if (CONFIG['client.toolbar'] or 'both') == 'default':
radiomenuitem_default.set_active(True)
@@ -543,18 +547,20 @@ class Main(object):
checkmenuitem_statusbar = gtk.CheckMenuItem(_('Statusbar'))
checkmenuitem_statusbar.connect('activate',
- lambda menuitem: self.sig_statusbar_change(menuitem.get_active()))
- checkmenuitem_statusbar.set_accel_path('/Options/Form/Statusbar')
+ lambda menuitem: self.sig_statusbar_change(menuitem.get_active()))
+ checkmenuitem_statusbar.set_accel_path(
+ '/Options/Form/Statusbar')
menu_form.add(checkmenuitem_statusbar)
if CONFIG['form.statusbar']:
checkmenuitem_statusbar.set_active(True)
- checkmenuitem_save_width_height = gtk.CheckMenuItem(_('Save Width/Height'))
+ checkmenuitem_save_width_height = gtk.CheckMenuItem(
+ _('Save Width/Height'))
checkmenuitem_save_width_height.connect('activate',
- lambda menuitem: CONFIG.__setitem__('client.save_width_height',
- menuitem.get_active()))
+ lambda menuitem: CONFIG.__setitem__('client.save_width_height',
+ menuitem.get_active()))
checkmenuitem_save_width_height.set_accel_path(
- '/Options/Form/Save Width Height')
+ '/Options/Form/Save Width Height')
menu_form.add(checkmenuitem_save_width_height)
if CONFIG['client.save_width_height']:
checkmenuitem_save_width_height.set_active(True)
@@ -602,7 +608,8 @@ class Main(object):
label=_('Left'))
radiomenuitem_left.connect('activate',
lambda x: CONFIG.__setitem__('client.form_tab', 'left'))
- radiomenuitem_left.set_accel_path('/Options/Tabs Position/Left')
+ radiomenuitem_left.set_accel_path(
+ '/Options/Tabs Position/Left')
menu_tab.add(radiomenuitem_left)
if (CONFIG['client.form_tab'] or 'left') == 'left':
radiomenuitem_left.set_active(True)
@@ -611,7 +618,8 @@ class Main(object):
label=_('Right'))
radiomenuitem_right.connect('activate',
lambda x: CONFIG.__setitem__('client.form_tab', 'right'))
- radiomenuitem_right.set_accel_path('/Options/Tabs Position/Right')
+ radiomenuitem_right.set_accel_path(
+ '/Options/Tabs Position/Right')
menu_tab.add(radiomenuitem_right)
if (CONFIG['client.form_tab'] or 'left') == 'right':
radiomenuitem_right.set_active(True)
@@ -620,7 +628,8 @@ class Main(object):
label=_('Bottom'))
radiomenuitem_bottom.connect('activate',
lambda x: CONFIG.__setitem__('client.form_tab', 'bottom'))
- radiomenuitem_bottom.set_accel_path('/Options/Tabs Position/Bottom')
+ radiomenuitem_bottom.set_accel_path(
+ '/Options/Tabs Position/Bottom')
menu_tab.add(radiomenuitem_bottom)
if (CONFIG['client.form_tab'] or 'left') == 'bottom':
radiomenuitem_bottom.set_active(True)
@@ -631,12 +640,6 @@ class Main(object):
menuitem_limit.set_accel_path('/Options/Search Limit')
menu_options.add(menuitem_limit)
- menuitem_actions = gtk.MenuItem(_('File _Actions...'))
- self.menuitem_actions = menuitem_actions
- menuitem_actions.connect('activate', self.sig_file_actions)
- menuitem_actions.set_accel_path('/Options/File Actions')
- menu_options.add(menuitem_actions)
-
menuitem_email = gtk.MenuItem(_('_Email...'))
self.menuitem_email = menuitem_email
menuitem_email.connect('activate', self.sig_email)
@@ -657,13 +660,15 @@ class Main(object):
def _set_menu_plugins(self):
menu_plugins = gtk.Menu()
- imagemenuitem_plugin_execute = gtk.ImageMenuItem(_('_Execute a Plugin'))
+ imagemenuitem_plugin_execute = gtk.ImageMenuItem(
+ _('_Execute a Plugin'))
image = gtk.Image()
image.set_from_stock('tryton-executable', gtk.ICON_SIZE_MENU)
imagemenuitem_plugin_execute.set_image(image)
- imagemenuitem_plugin_execute.connect('activate', self.sig_plugin_execute)
+ imagemenuitem_plugin_execute.connect('activate',
+ self.sig_plugin_execute)
imagemenuitem_plugin_execute.set_accel_path(
- '/Plugins/Execute a Plugin')
+ '/Plugins/Execute a Plugin')
menu_plugins.add(imagemenuitem_plugin_execute)
return menu_plugins
@@ -678,15 +683,16 @@ class Main(object):
imagemenuitem_tips.set_accel_path('/Help/Tips')
menu_help.add(imagemenuitem_tips)
- imagemenuitem_shortcuts = gtk.ImageMenuItem(_('_Keyboard Shortcuts...'))
+ imagemenuitem_shortcuts = gtk.ImageMenuItem(
+ _('_Keyboard Shortcuts...'))
image = gtk.Image()
image.set_from_stock('tryton-help', gtk.ICON_SIZE_MENU)
imagemenuitem_shortcuts.set_image(image)
imagemenuitem_shortcuts.connect('activate', self.sig_shortcuts)
- imagemenuitem_shortcuts.set_accel_path('/Help/Keyboard Shortcuts')
+ imagemenuitem_shortcuts.set_accel_path(
+ '/Help/Keyboard Shortcuts')
menu_help.add(imagemenuitem_shortcuts)
-
imagemenuitem_about = gtk.ImageMenuItem(_('_About...'))
image = gtk.Image()
image.set_from_stock('gtk-about', gtk.ICON_SIZE_MENU)
@@ -817,9 +823,6 @@ class Main(object):
def sig_limit(self, widget):
Limit().run()
- def sig_file_actions(self, widget):
- FileActions().run()
-
def sig_email(self, widget):
Email().run()
@@ -843,7 +846,8 @@ class Main(object):
'get_preferences', False, rpc.CONTEXT)
if prefs and 'language_direction' in prefs:
translate.set_language_direction(prefs['language_direction'])
- CONFIG['client.language_direction'] = prefs['language_direction']
+ CONFIG['client.language_direction'] = \
+ prefs['language_direction']
self.sb_username.set_text(prefs.get('status_bar', ''))
if prefs and 'language' in prefs:
translate.setlang(prefs['language'], prefs.get('locale'))
@@ -866,8 +870,8 @@ class Main(object):
ctx = {}
ctx.update(rpc.CONTEXT)
ctx['active_test'] = False
- return Window.create(None, 'res.request', False, [ ],
- mode=['form', 'tree'], context=ctx)
+ return Window.create(None, 'res.request', False, [],
+ mode=['form', 'tree'], context=ctx)
def sig_request_open(self, widget):
ctx = {}
@@ -881,8 +885,8 @@ class Main(object):
else:
raise
ids = ids1 + ids2
- return Window.create(False, 'res.request', ids, [ ],
- mode=['tree', 'form'], context=ctx)
+ return Window.create(False, 'res.request', ids, [],
+ mode=['tree', 'form'], context=ctx)
def request_set(self, exception=False):
try:
@@ -897,7 +901,6 @@ class Main(object):
else:
ids, ids2 = rpc.execute('model', 'res.request', 'request_get',
rpc.CONTEXT)
- label = _('Requests (%s/%s)') % (len(ids), len(ids2))
message = _('Waiting requests: %s received - %s sent') % (len(ids),
len(ids2))
self.sb_requests.set_text(message)
@@ -935,7 +938,8 @@ class Main(object):
common.ICONFACTORY.load_icons()
if prefs and 'language_direction' in prefs:
translate.set_language_direction(prefs['language_direction'])
- CONFIG['client.language_direction'] = prefs['language_direction']
+ CONFIG['client.language_direction'] = \
+ prefs['language_direction']
menu_id = self.sig_win_menu(quiet=False, prefs=prefs)
if menu_id:
self.sig_home_new(quiet=True, except_id=menu_id, prefs=prefs)
@@ -1026,7 +1030,8 @@ class Main(object):
if (self.menu_screen
and self.menu_screen.current_view.view_type == 'tree'):
try:
- has_focus = self.menu_screen.current_view.widget_tree.has_focus()
+ has_focus = \
+ self.menu_screen.current_view.widget_tree.has_focus()
except AttributeError:
has_focus = (self.menu_screen.current_view.widget_tree.flags()
& gtk.HAS_FOCUS)
@@ -1114,7 +1119,7 @@ class Main(object):
def sig_configure(self, widget, event):
if hasattr(event, 'width') \
and hasattr(event, 'height'):
- self._width = int(event.width)
+ self._width = int(event.width)
self._height = int(event.height)
return False
@@ -1336,7 +1341,7 @@ class Main(object):
if dbname:
with open(filename, 'rb') as file_p:
data = file_p.read()
- host, port = url.rsplit(':' , 1)
+ host, port = url.rsplit(':', 1)
rpcprogress = common.RPCProgress('db_exec', (host, int(port),
'restore', dbname, passwd, buffer(data), update))
try:
@@ -1497,7 +1502,6 @@ class Main(object):
direct_print = json.loads(params.get('direct_print', 'false'))
email_print = json.loads(params.get('email_print', 'false'))
email = json.loads(params.get('email', 'null'))
- name = json.loads(params.get('name', 'false'))
context = json.loads(params.get('context', '{}'))
except ValueError:
return
diff --git a/tryton/gui/window/__init__.py b/tryton/gui/window/__init__.py
index 3558718664..d0d616fc01 100644
--- a/tryton/gui/window/__init__.py
+++ b/tryton/gui/window/__init__.py
@@ -1,6 +1,5 @@
#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 window import *
-from fileactions import *
from email import *
from limit import *
diff --git a/tryton/gui/window/about.py b/tryton/gui/window/about.py
index 84d3ecaa03..8757d71d04 100644
--- a/tryton/gui/window/about.py
+++ b/tryton/gui/window/about.py
@@ -3,9 +3,8 @@
#this repository contains the full copyright notices and license terms.
import gtk
import gettext
-import os
import webbrowser
-from tryton.config import TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
+from tryton.config import TRYTON_ICON
from tryton.version import VERSION, WEBSITE
from tryton.common import get_toplevel_window
diff --git a/tryton/gui/window/attachment.py b/tryton/gui/window/attachment.py
index 4c83734452..daafd69d77 100644
--- a/tryton/gui/window/attachment.py
+++ b/tryton/gui/window/attachment.py
@@ -5,20 +5,27 @@ from tryton.gui.window.view_form.screen import Screen
from tryton.gui.window.win_form import WinForm
-class Attachment(object):
+class Attachment(WinForm):
"Attachment window"
- def __init__(self, model_name, record_id):
+ def __init__(self, model_name, record_id, callback=None):
self.resource = '%s,%s' % (model_name, record_id)
-
- def run(self):
+ self.attachment_callback = callback
screen = Screen('ir.attachment', domain=[
('resource', '=', self.resource),
], mode=['tree', 'form'], context={
'resource': self.resource,
}, exclude_field='resource')
screen.search_filter()
- def callback(result):
- if result:
- screen.group.save()
- WinForm(screen, callback, view_type='tree')
+ super(Attachment, self).__init__(screen, self.callback,
+ view_type='tree')
+
+ def destroy(self):
+ self.prev_view.save_width_height()
+ super(Attachment, self).destroy()
+
+ def callback(self, result):
+ if result:
+ self.screen.group.save()
+ if self.attachment_callback:
+ self.attachment_callback()
diff --git a/tryton/gui/window/board.py b/tryton/gui/window/board.py
index 697d887250..2e9d80b016 100644
--- a/tryton/gui/window/board.py
+++ b/tryton/gui/window/board.py
@@ -2,8 +2,6 @@
#this repository contains the full copyright notices and license terms.
"Board"
import gettext
-import gtk
-from tryton.config import CONFIG
from tryton.signal_event import SignalEvent
from tryton.gui import Main
import tryton.rpc as rpc
diff --git a/tryton/gui/window/dbcreate.py b/tryton/gui/window/dbcreate.py
index e59463baa9..817f7592a7 100644
--- a/tryton/gui/window/dbcreate.py
+++ b/tryton/gui/window/dbcreate.py
@@ -5,7 +5,7 @@ import gobject
import gettext
import re
import tryton.common as common
-from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR
+from tryton.config import CONFIG, TRYTON_ICON
from tryton.exceptions import TrytonServerError
import tryton.rpc as rpc
@@ -28,10 +28,11 @@ class DBCreate(object):
self.entry_adminpasswd2.set_sensitive(True)
self.entry_server_connection.modify_text(gtk.STATE_INSENSITIVE, \
gtk.gdk.color_parse(common.COLOR_SCHEMES["black"]))
- self.tooltips.set_tip(self.entry_server_connection,_("This is the URL of " \
- "the Tryton server. Use server 'localhost' and port '8000' if " \
- "the server is installed on this computer. Click on 'Change' to " \
- "change the address."))
+ self.tooltips.set_tip(self.entry_server_connection,
+ _("This is the URL of the Tryton server. Use server "
+ "'localhost' and port '8000' if the server is installed "
+ "on this computer. Click on 'Change' to change the "
+ "address."))
else:
self.entry_serverpasswd.set_sensitive(False)
self.entry_dbname.set_sensitive(False)
@@ -89,12 +90,12 @@ class DBCreate(object):
must be filled, then the Create button is set to sensitive. This
event method doesn't check the valid of single entrys.
"""
- if self.entry_server_connection.get_text() != "" \
- and self.entry_serverpasswd.get_text() != "" \
- and self.entry_dbname.get_text() != "" \
- and self.combo_language.get_active() != -1 \
- and self.entry_adminpasswd.get_text() != "" \
- and self.entry_adminpasswd2.get_text() != "":
+ if (self.entry_server_connection.get_text() != ""
+ and self.entry_serverpasswd.get_text() != ""
+ and self.entry_dbname.get_text() != ""
+ and self.combo_language.get_active() != -1
+ and self.entry_adminpasswd.get_text() != ""
+ and self.entry_adminpasswd2.get_text() != ""):
widget.unset_flags(gtk.HAS_DEFAULT)
self.button_create.set_sensitive(True)
self.button_create.set_flags(gtk.CAN_DEFAULT)
@@ -114,7 +115,7 @@ class DBCreate(object):
- First character must be a letter
"""
- if (new_text.isalnum() or new_text == '_' ):
+ if new_text.isalnum() or new_text == '_':
_hid = entry.get_data('handlerid')
entry.handler_block(_hid)
_pos = entry.get_position()
@@ -133,11 +134,9 @@ class DBCreate(object):
self.port = port
# GTK Stuffs
- self.dialog = gtk.Dialog(
- title= _("Create new database"),
- flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.WIN_POS_CENTER_ON_PARENT,
- )
+ self.dialog = gtk.Dialog(title=_("Create new database"),
+ flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
+ gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.set_has_separator(True)
self.dialog.set_icon(TRYTON_ICON)
# This event is needed for controlling the button_create
@@ -152,7 +151,8 @@ class DBCreate(object):
img_connect = gtk.Image()
img_connect.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
self.button_create.set_image(img_connect)
- self.tooltips.set_tip(self.button_create, _('Create the new database.'))
+ self.tooltips.set_tip(self.button_create,
+ _('Create the new database.'))
self.dialog.add_action_widget(self.button_create, gtk.RESPONSE_OK)
self.dialog.set_default_response(gtk.RESPONSE_OK)
@@ -163,10 +163,10 @@ class DBCreate(object):
table.set_col_spacings(3)
self.label_server_setup = gtk.Label()
- self.label_server_setup.set_markup(""+ _("Server Setup:")+ "")
+ self.label_server_setup.set_markup("" + _("Server Setup:") + "")
self.label_server_setup.set_justify(gtk.JUSTIFY_LEFT)
self.label_server_setup.set_alignment(0, 1)
- self.label_server_setup.set_padding( 9, 5)
+ self.label_server_setup.set_padding(9, 5)
table.attach(self.label_server_setup, 0, 3, 0, 1, xoptions=gtk.FILL)
self.label_server = gtk.Label(_("Server connection:"))
self.label_server.set_alignment(1, 0.5)
@@ -176,25 +176,26 @@ class DBCreate(object):
self.entry_server_connection.set_sensitive(False)
self.entry_server_connection.unset_flags(gtk.CAN_FOCUS)
self.entry_server_connection.set_editable(False)
- self.tooltips.set_tip(self.entry_server_connection, _("This is the URL of " \
- "the server. Use server 'localhost' and port '8000' if " \
- "the server is installed on this computer. Click on 'Change' to " \
- "change the address."))
+ self.tooltips.set_tip(self.entry_server_connection,
+ _("This is the URL of the server. Use server 'localhost' and port "
+ "'8000' if the server is installed on this computer. Click on "
+ "'Change' to change the address."))
self.button_server_change = gtk.Button(_("C_hange"), stock=None,
use_underline=True)
img_button_server_change = gtk.Image()
- img_button_server_change.set_from_stock('tryton-preferences-system', \
+ img_button_server_change.set_from_stock('tryton-preferences-system',
gtk.ICON_SIZE_BUTTON)
self.button_server_change.set_image(img_button_server_change)
- table.attach(self.button_server_change, 2, 3, 1, 2, yoptions=False, xoptions=gtk.FILL)
- self.tooltips.set_tip(self.button_server_change, _("Setup the " \
- "server connection..."))
+ table.attach(self.button_server_change, 2, 3, 1, 2, yoptions=False,
+ xoptions=gtk.FILL)
+ self.tooltips.set_tip(self.button_server_change,
+ _("Setup the server connection..."))
table.attach(self.entry_server_connection, 1, 2, 1, 2)
self.label_serverpasswd = gtk.Label(_("Tryton Server Password:"))
self.label_serverpasswd.set_justify(gtk.JUSTIFY_RIGHT)
self.label_serverpasswd.set_alignment(1, 0.5)
- self.label_serverpasswd.set_padding( 3, 3)
+ self.label_serverpasswd.set_padding(3, 3)
table.attach(self.label_serverpasswd, 0, 1, 2, 3, xoptions=gtk.FILL,
yoptions=gtk.FILL)
self.entry_serverpasswd = gtk.Entry()
@@ -212,15 +213,15 @@ class DBCreate(object):
table.attach(self.hseparator, 0, 3, 3, 4, yoptions=gtk.FILL)
label_dbname = gtk.Label()
- label_dbname.set_markup("" + _("New database setup:") + "")
+ label_dbname.set_markup("" + _("New database setup:") + "")
label_dbname.set_justify(gtk.JUSTIFY_LEFT)
label_dbname.set_alignment(0, 1)
- label_dbname.set_padding( 9, 5)
+ label_dbname.set_padding(9, 5)
table.attach(label_dbname, 0, 3, 4, 5, xoptions=gtk.FILL,
yoptions=gtk.FILL)
label_dbname = gtk.Label(_("Database name:"))
label_dbname.set_justify(gtk.JUSTIFY_RIGHT)
- label_dbname.set_padding( 3, 3)
+ label_dbname.set_padding(3, 3)
label_dbname.set_alignment(1, 0.5)
table.attach(label_dbname, 0, 1, 5, 6, xoptions=gtk.FILL,
yoptions=gtk.FILL)
@@ -229,18 +230,18 @@ class DBCreate(object):
self.entry_dbname.set_width_chars(16)
self.entry_dbname.set_activates_default(True)
table.attach(self.entry_dbname, 1, 3, 5, 6, yoptions=gtk.FILL)
- self.tooltips.set_tip(self.entry_dbname, _("Choose the name of the new " \
- "database.\n" \
- "Allowed characters are alphanumerical or _ (underscore)\n" \
- "You need to avoid all accents, space or special characters! " \
- "Example: tryton"))
- handlerid = self.entry_dbname.connect("insert-text", \
+ self.tooltips.set_tip(self.entry_dbname,
+ _("Choose the name of the new database.\n"
+ "Allowed characters are alphanumerical or _ (underscore)\n"
+ "You need to avoid all accents, space or special characters! "
+ "Example: tryton"))
+ handlerid = self.entry_dbname.connect("insert-text",
self.entry_insert_text)
self.entry_dbname.set_data('handlerid', handlerid)
label_language = gtk.Label(_("Default language:"))
label_language.set_justify(gtk.JUSTIFY_RIGHT)
label_language.set_alignment(1, 0.5)
- label_language.set_padding( 3, 3)
+ label_language.set_padding(3, 3)
table.attach(label_language, 0, 1, 6, 7, xoptions=gtk.FILL,
yoptions=gtk.FILL)
eventbox_language = gtk.EventBox()
@@ -253,24 +254,25 @@ class DBCreate(object):
"the administration menu."))
label_adminpasswd = gtk.Label(_("Admin password:"))
label_adminpasswd.set_justify(gtk.JUSTIFY_RIGHT)
- label_adminpasswd.set_padding( 3, 3)
+ label_adminpasswd.set_padding(3, 3)
label_adminpasswd.set_alignment(1, 0.5)
table.attach(label_adminpasswd, 0, 1, 7, 8, xoptions=gtk.FILL,
yoptions=gtk.FILL)
self.entry_adminpasswd = gtk.Entry()
self.entry_adminpasswd.set_visibility(False)
self.entry_adminpasswd.set_activates_default(True)
- self.tooltips.set_tip(self.entry_adminpasswd, _("Choose a password for " \
- "the admin user of the new database. With these credentials you " \
- "will be later able to login into the database:\n" \
- "User name: admin\n" \
- "Password: "))
+ self.tooltips.set_tip(self.entry_adminpasswd,
+ _("Choose a password for the admin user of the new database. "
+ "With these credentials you will be later able to login into "
+ "the database:\n"
+ "User name: admin\n"
+ "Password: "))
table.attach(self.entry_adminpasswd, 1, 3, 7, 8, yoptions=gtk.FILL)
self.entry_adminpasswd.connect("key-press-event", \
self.event_passwd_clear)
label_adminpasswd2 = gtk.Label(_("Confirm admin password:"))
label_adminpasswd2.set_justify(gtk.JUSTIFY_RIGHT)
- label_adminpasswd2.set_padding( 3, 3)
+ label_adminpasswd2.set_padding(3, 3)
label_adminpasswd2.set_alignment(1, 0.5)
table.attach(label_adminpasswd2, 0, 1, 8, 9, xoptions=gtk.FILL,
yoptions=gtk.FILL)
@@ -355,14 +357,14 @@ class DBCreate(object):
common.process_exception(exception)
continue
if exist:
- common.warning(_("A database with the same name " \
- "already exists.\n" \
- "Try another database name."),
- _("This database name already exist!"))
- self.entry_dbname.set_text("")
- self.entry_dbname.grab_focus()
- continue
- else: # Everything runs fine, break the block here
+ common.warning(_("A database with the same name "
+ "already exists.\n"
+ "Try another database name."),
+ _("This database name already exist!"))
+ self.entry_dbname.set_text("")
+ self.entry_dbname.grab_focus()
+ continue
+ else: # Everything runs fine, break the block here
host = url_m.group(1)
port = url_m.group(2)
try:
@@ -378,13 +380,13 @@ class DBCreate(object):
self.entry_serverpasswd.set_text("")
self.entry_serverpasswd.grab_focus()
continue
- else: # Unclassified error
- common.warning(_("Can't create the " \
- "database, caused by an unknown reason.\n" \
- "If there is a database created, it could " \
- "be broken. Maybe drop this database! " \
- "Please check the error message for " \
- "possible informations.\n" \
+ else: # Unclassified error
+ common.warning(_("Can't create the "
+ "database, caused by an unknown reason.\n"
+ "If there is a database created, it could "
+ "be broken. Maybe drop this database! "
+ "Please check the error message for "
+ "possible informations.\n"
"Error message:\n")
+ str(exception.faultCode),
_("Error creating database!"))
@@ -410,4 +412,3 @@ class DBCreate(object):
parent.present()
self.dialog.destroy()
return dbname
-
diff --git a/tryton/gui/window/dbdumpdrop.py b/tryton/gui/window/dbdumpdrop.py
index 08cfe1aea6..6be380e745 100644
--- a/tryton/gui/window/dbdumpdrop.py
+++ b/tryton/gui/window/dbdumpdrop.py
@@ -1,7 +1,5 @@
# 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 threading
-
import gtk
import gobject
import gettext
@@ -11,6 +9,7 @@ import tryton.rpc as rpc
_ = gettext.gettext
+
class DBBackupDrop(object):
"""
Widget for database backup and drop.
@@ -20,14 +19,16 @@ class DBBackupDrop(object):
db_widget.hide()
label.hide()
dbprogress = common.DBProgress(host, port)
+
def callback(dbs, createdb):
if dbs is None or dbs == -1:
if dbs is None:
- label.set_label('' + \
- _('Could not connect to server!') + '')
+ label.set_label('' +
+ _('Could not connect to server!') + '')
else:
- label.set_label('' + \
- _('This client version is not compatible with the server!')
+ label.set_label('' +
+ _('This client version is not compatible '
+ 'with the server!')
+ '')
db_widget.hide()
label.show()
@@ -58,9 +59,9 @@ class DBBackupDrop(object):
must be filled, then the Create button is set to sensitive. This
event method doesn't check the valid of single entrys.
"""
- if self.entry_server_connection.get_text() != "" \
- and self.combo_database.get_active_text() != "" \
- and self.entry_serverpasswd.get_text() != "":
+ if (self.entry_server_connection.get_text() != ""
+ and self.combo_database.get_active_text() != ""
+ and self.entry_serverpasswd.get_text() != ""):
widget.unset_flags(gtk.HAS_DEFAULT)
self.button_ok.set_sensitive(True)
self.button_ok.set_flags(gtk.CAN_DEFAULT)
@@ -73,7 +74,7 @@ class DBBackupDrop(object):
def __init__(self, function=None):
# This widget is used for creating and droping a database!
- if function =="backup":
+ if function == "backup":
dialog_title = _("Backup a database")
button_ok_text = _("Backup")
button_ok_tooltip = _("Backup the choosen database.")
@@ -114,14 +115,15 @@ class DBBackupDrop(object):
table.set_border_width(10)
table.set_row_spacings(3)
table.set_col_spacings(3)
- self.dialog_vbox.pack_start(table, True, False,0)
+ self.dialog_vbox.pack_start(table, True, False, 0)
label_subtitle = gtk.Label()
- label_subtitle.set_markup(""+ label_subtitle_text + "")
+ label_subtitle.set_markup("" + label_subtitle_text + "")
label_subtitle.set_justify(gtk.JUSTIFY_LEFT)
label_subtitle.set_alignment(0, 1)
- label_subtitle.set_padding( 9, 5)
- table.attach(label_subtitle, 0, 3, 0, 1, yoptions=False, xoptions=gtk.FILL)
+ label_subtitle.set_padding(9, 5)
+ table.attach(label_subtitle, 0, 3, 0, 1, yoptions=False,
+ xoptions=gtk.FILL)
hseparator = gtk.HSeparator()
table.attach(hseparator, 0, 3, 1, 2, yoptions=False)
@@ -183,7 +185,7 @@ class DBBackupDrop(object):
self.label_serverpasswd = gtk.Label(_("Tryton Server Password:"))
self.label_serverpasswd.set_justify(gtk.JUSTIFY_RIGHT)
self.label_serverpasswd.set_alignment(1, 0.5)
- self.label_serverpasswd.set_padding( 3, 3)
+ self.label_serverpasswd.set_padding(3, 3)
table.attach(self.label_serverpasswd, 0, 1, 4, 5, yoptions=False,
xoptions=gtk.FILL)
@@ -234,4 +236,3 @@ class DBBackupDrop(object):
self.dialog.destroy()
return (url, database, passwd)
-
diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py
index 4e28d7c2bb..73024dc0af 100644
--- a/tryton/gui/window/dblogin.py
+++ b/tryton/gui/window/dblogin.py
@@ -5,10 +5,7 @@ import ConfigParser
import gtk
import gobject
import os
-import re
import gettext
-import threading
-import time
from tryton.version import VERSION
import tryton.common as common
@@ -31,8 +28,9 @@ class DBListEditor(object):
# GTK Stuffs
self.parent = parent
self.dialog = gtk.Dialog(title=_(u'Profile Editor'), parent=parent,
- flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
- self.ok_button = self.dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
+ flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ self.ok_button = self.dialog.add_button(gtk.STOCK_OK,
+ gtk.RESPONSE_ACCEPT)
self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.set_has_separator(True)
self.dialog.set_icon(TRYTON_ICON)
@@ -94,7 +92,8 @@ class DBListEditor(object):
database.set_padding(3, 3)
self.database_entry = gtk.Entry()
self.database_entry.connect('changed', self.dbentry_changed)
- self.database_entry.connect('changed', self.update_profiles, 'database')
+ self.database_entry.connect('changed', self.update_profiles,
+ 'database')
self.database_entry.set_activates_default(True)
self.database_label = gtk.Label()
self.database_label.set_use_markup(True)
@@ -108,7 +107,7 @@ class DBListEditor(object):
self.database_combo.connect('changed', self.dbcombo_changed)
self.database_button = gtk.Button(_(u'Create'))
self.database_button.connect('clicked', self.db_create)
- self.database_progressbar= gtk.ProgressBar()
+ self.database_progressbar = gtk.ProgressBar()
self.database_progressbar.set_text(_(u'Fetching databases list'))
image = gtk.Image()
image.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
@@ -131,7 +130,8 @@ class DBListEditor(object):
username.set_alignment(1, 0.5)
username.set_padding(3, 3)
self.username_entry = gtk.Entry()
- self.username_entry.connect('changed', self.update_profiles, 'username')
+ self.username_entry.connect('changed', self.update_profiles,
+ 'username')
self.username_entry.set_activates_default(True)
table.attach(username, 0, 1, 4, 5, yoptions=False, xoptions=gtk.FILL)
table.attach(self.username_entry, 1, 2, 4, 5, yoptions=False)
@@ -193,10 +193,10 @@ class DBListEditor(object):
def profile_create(self, button):
self.clear_entries()
model = self.profile_tree.get_model()
- selection = self.profile_tree.get_selection()
model.append(['', False])
column = self.profile_tree.get_column(0)
- self.profile_tree.set_cursor(len(model)-1, column, start_editing=True)
+ self.profile_tree.set_cursor(len(model) - 1, column,
+ start_editing=True)
def profile_delete(self, button):
self.clear_entries()
@@ -375,7 +375,7 @@ class DBLogin(object):
# GTK Stuffs
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(title=_('Login'), parent=self.parent,
- flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
+ flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.set_has_separator(True)
self.dialog.set_icon(TRYTON_ICON)
@@ -444,7 +444,8 @@ class DBLogin(object):
self.label_host.set_alignment(1, 0.5)
self.label_host.set_padding(3, 3)
self.entry_host = gtk.Entry()
- self.entry_host.connect_after('focus-out-event', self.clear_profile_combo)
+ self.entry_host.connect_after('focus-out-event',
+ self.clear_profile_combo)
self.entry_host.set_activates_default(True)
self.table_main.attach(self.label_host, 0, 1, 4, 5, xoptions=gtk.FILL)
self.table_main.attach(self.entry_host, 1, 3, 4, 5)
@@ -453,7 +454,8 @@ class DBLogin(object):
self.label_database.set_alignment(1, 0.5)
self.label_database.set_padding(3, 3)
self.entry_database = gtk.Entry()
- self.entry_database.connect_after('focus-out-event', self.clear_profile_combo)
+ self.entry_database.connect_after('focus-out-event',
+ self.clear_profile_combo)
self.entry_database.set_activates_default(True)
self.table_main.attach(self.label_database, 0, 1, 5, 6,
xoptions=gtk.FILL)
@@ -465,12 +467,12 @@ class DBLogin(object):
self.entry_login = gtk.Entry()
self.entry_login.set_activates_default(True)
self.table_main.attach(self.entry_login, 1, 3, 6, 7)
- label_password = gtk.Label(str = _("Password:"))
+ label_password = gtk.Label(str=_("Password:"))
label_password.set_justify(gtk.JUSTIFY_RIGHT)
label_password.set_alignment(1, 0.5)
label_password.set_padding(3, 3)
self.table_main.attach(label_password, 0, 1, 7, 8, xoptions=gtk.FILL)
- label_username = gtk.Label(str = _("User name:"))
+ label_username = gtk.Label(str=_("User name:"))
label_username.set_alignment(1, 0.5)
label_username.set_padding(3, 3)
self.table_main.attach(label_username, 0, 1, 6, 7, xoptions=gtk.FILL)
@@ -631,13 +633,10 @@ class DBLogin(object):
port = self.get_port(netloc)
except ValueError:
continue
- if ':' in host:
- hostname = '[%s]' % host
- else:
- hostname = host
try:
if not common.test_server_version(host, port):
- common.warning('', _(u'Incompatible version of the server'))
+ common.warning('',
+ _(u'Incompatible version of the server'))
continue
except Exception, exception:
common.process_exception(exception)
@@ -660,4 +659,3 @@ class DBLogin(object):
Main.get_main().refresh_ssl()
raise TrytonError('QueryCanceled')
return result
-
diff --git a/tryton/gui/window/dbrestore.py b/tryton/gui/window/dbrestore.py
index 6be7386542..8f52fc7e9e 100644
--- a/tryton/gui/window/dbrestore.py
+++ b/tryton/gui/window/dbrestore.py
@@ -5,7 +5,7 @@ import gtk
import gobject
import gettext
import tryton.common as common
-from tryton.config import CONFIG, TRYTON_ICON
+from tryton.config import CONFIG
import tryton.rpc as rpc
_ = gettext.gettext
@@ -19,10 +19,10 @@ class DBRestore(object):
must be filled, then the restore button is set to sensitive. This
event method doesn't check the valid of single entrys.
"""
- if self.entry_server_url.get_text() != "" \
- and self.entry_server_password.get_text() != "" \
- and self.entry_server_url.get_text() != "" \
- and self.entry_db_name.get_text() != "":
+ if (self.entry_server_url.get_text() != ""
+ and self.entry_server_password.get_text() != ""
+ and self.entry_server_url.get_text() != ""
+ and self.entry_db_name.get_text() != ""):
widget.unset_flags(gtk.HAS_DEFAULT)
self.button_restore.set_sensitive(True)
self.button_restore.set_flags(gtk.CAN_DEFAULT)
@@ -40,7 +40,7 @@ class DBRestore(object):
- Allowed characters are alpha-nummeric [A-Za-z0-9] and underscore (_)
- First character must be a letter
"""
- if (new_text.isalnum() or new_text == '_' ):
+ if new_text.isalnum() or new_text == '_':
_hid = entry.get_data('handlerid')
entry.handler_block(_hid)
_pos = entry.get_position()
@@ -48,6 +48,7 @@ class DBRestore(object):
new_text = ""
_pos = entry.insert_text(new_text, _pos)
entry.handler_unblock(_hid)
+
def _move_cursor():
with gtk.gdk.lock:
entry.set_position(_pos)
@@ -158,7 +159,8 @@ class DBRestore(object):
img_restore.set_from_stock('tryton-folder-saved-search', \
gtk.ICON_SIZE_BUTTON)
self.button_restore.set_image(img_restore)
- self.tooltips.set_tip(self.button_restore, _('Restore the database from file.'))
+ self.tooltips.set_tip(self.button_restore,
+ _('Restore the database from file.'))
self.dialog.add_action_widget(self.button_restore, gtk.RESPONSE_OK)
self.dialog.set_default_response(gtk.RESPONSE_OK)
diff --git a/tryton/gui/window/email.py b/tryton/gui/window/email.py
index 4112050f92..d9e6d1d443 100644
--- a/tryton/gui/window/email.py
+++ b/tryton/gui/window/email.py
@@ -14,9 +14,9 @@ class Email(object):
def __init__(self):
self.parent = get_toplevel_window()
self.win = gtk.Dialog(_('Email'), self.parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
+ gtk.RESPONSE_OK))
self.win.set_default_response(gtk.RESPONSE_OK)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
@@ -84,7 +84,6 @@ class Email(object):
self.win.vbox.pack_start(hbox, expand=True, fill=True)
-
self.win.show_all()
def run(self):
diff --git a/tryton/gui/window/fileactions.py b/tryton/gui/window/fileactions.py
deleted file mode 100644
index 403365662a..0000000000
--- a/tryton/gui/window/fileactions.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#This file is part of Tryton. The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
-"File actions"
-import gtk
-import gettext
-from tryton.config import TRYTON_ICON, CONFIG
-from tryton.common import safe_eval, get_toplevel_window
-
-_ = gettext.gettext
-
-
-class FileActions(object):
- "File actions window"
-
- def __init__(self):
- self.parent= get_toplevel_window()
- self.win = gtk.Dialog(_('File Actions'), self.parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
- self.win.set_default_response(gtk.RESPONSE_OK)
- self.win.set_icon(TRYTON_ICON)
- self.win.set_has_separator(True)
- self.win.vbox.pack_start(gtk.Label(
- _('Edit Files Actions')), expand=False, fill=True)
- self.win.vbox.pack_start(gtk.HSeparator())
- self.treeview = gtk.TreeView()
-
- self.model = gtk.ListStore(str, str, str, str)
- self.treeview.set_model(self.model)
-
- for index, text in enumerate((_('File Type'), _('Open'), _('Print'))):
- renderer = gtk.CellRendererText()
- if index != 0:
- renderer.set_property('editable', True)
- renderer.connect('edited', self._sig_edited)
- column = gtk.TreeViewColumn(text, renderer, text=index + 1)
- column.set_resizable(True)
- self.treeview.append_column(column)
-
- i = 1
- if isinstance(CONFIG['client.actions'], basestring):
- CONFIG['client.actions'] = safe_eval(CONFIG['client.actions'])
- extensions = CONFIG['client.actions'].keys()
- extensions.sort()
- for extension in extensions:
- iter = self.model.append()
- self.model.set(iter, 0, extension,
- 1, _('%s file') % extension.upper(),
- 2, CONFIG['client.actions'][extension][0],
- 3, CONFIG['client.actions'][extension][1])
-
- scroll = gtk.ScrolledWindow()
- scroll.add(self.treeview)
- scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- viewport= gtk.Viewport()
- viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN)
- viewport.set_size_request(400, 200)
- viewport.add(scroll)
- self.win.vbox.pack_start(viewport, expand=True, fill=True)
-
- label = gtk.Label(_('Use "%s" as a placeholder for the file name'))
- label.set_alignment(0.0, 0.5)
- label.set_padding(0, 10)
- self.win.vbox.pack_start(label, expand=False, fill=True)
- self.win.show_all()
-
- def run(self):
- "Run the window"
- res = self.win.run()
- if res == gtk.RESPONSE_OK:
- config = {}
- for extension, _, cmd_open, cmd_print in self.model:
- config[extension] = {
- 0: cmd_open,
- 1: cmd_print,
- }
- CONFIG['client.actions'] = config
- CONFIG.save()
- self.parent.present()
- self.win.destroy()
- return res
-
- def _sig_edited(self, cell, path, new_text):
- iter = self.model.get_iter_from_string(path)
- (path, column) = self.treeview.get_cursor()
- column_id = self.treeview.get_columns().index(column)
- self.model.set(iter, column_id + 1, new_text)
diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py
index ddde3c2bba..66b3852fe8 100644
--- a/tryton/gui/window/form.py
+++ b/tryton/gui/window/form.py
@@ -8,10 +8,8 @@ import locale
import tryton.rpc as rpc
from tryton.gui.window.view_form.screen import Screen
from tryton.action import Action
-from tryton.config import CONFIG
from tryton.gui import Main
from tryton.gui.window import Window
-from tryton.gui.window.preference import Preference
from tryton.gui.window.win_export import WinExport
from tryton.gui.window.win_import import WinImport
from tryton.gui.window.attachment import Attachment
@@ -21,7 +19,7 @@ from tryton.common import (TRYTON_ICON, message, sur, sur_3b, COLOR_SCHEMES,
from tryton.exceptions import TrytonServerError
import tryton.common as common
from tryton.translate import date_format
-from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT
+from tryton.common import HM_FORMAT
from tryton.pyson import PYSONEncoder
from tabcontent import TabContent
@@ -183,9 +181,9 @@ class Form(SignalEvent, TabContent):
return
parent = common.get_toplevel_window()
win = gtk.Dialog(_('Go to ID'), parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
+ gtk.RESPONSE_OK))
win.set_icon(TRYTON_ICON)
win.set_has_separator(True)
win.set_default_response(gtk.RESPONSE_OK)
@@ -200,6 +198,7 @@ class Form(SignalEvent, TabContent):
entry.set_property('activates_default', True)
entry.set_max_length(0)
entry.set_alignment(1.0)
+
def sig_insert_text(widget, new_text, new_text_length, position):
value = widget.get_text()
position = widget.get_position()
@@ -240,7 +239,9 @@ class Form(SignalEvent, TabContent):
def sig_attach(self, widget=None):
obj_id = self.id_get()
if obj_id >= 0 and obj_id is not False:
- Attachment(self.model, obj_id).run()
+ def callback():
+ self.update_attachment_count(reload=True)
+ Attachment(self.model, obj_id, callback)
else:
self.message_info(_('No record selected!'))
self.update_attachment_count(reload=True)
@@ -300,7 +301,7 @@ class Form(SignalEvent, TabContent):
display_format = date_format() + ' ' + HM_FORMAT
date = timezoned_date(line[key])
value = common.datetime_strftime(date, display_format)
- message_str += val + ' ' + value +'\n'
+ message_str += val + ' ' + value + '\n'
message_str += _('Model:') + ' ' + self.model
message(message_str)
return True
@@ -482,6 +483,7 @@ class Form(SignalEvent, TabContent):
self.activate_save()
def modified_save(self, reload=True):
+ self.screen.current_view.set_value()
if self.screen.modified():
value = sur_3b(
_('This record has been modified\n' \
diff --git a/tryton/gui/window/limit.py b/tryton/gui/window/limit.py
index bac2ce6a58..b0501e8131 100644
--- a/tryton/gui/window/limit.py
+++ b/tryton/gui/window/limit.py
@@ -15,9 +15,9 @@ class Limit(object):
def __init__(self):
self.parent = get_toplevel_window()
self.win = gtk.Dialog(_('Limit'), self.parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
+ gtk.RESPONSE_OK))
self.win.set_default_response(gtk.RESPONSE_OK)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
@@ -29,8 +29,9 @@ class Limit(object):
hbox.pack_start(gtk.Label(_('Limit:')), expand=True, fill=True)
self.spin_limit = gtk.SpinButton(climb_rate=1, digits=0)
self.spin_limit.set_numeric(False)
- self.spin_limit.set_adjustment(gtk.Adjustment(value=CONFIG['client.limit'],
- lower=1, upper=sys.maxint, step_incr=10, page_incr=100))
+ self.spin_limit.set_adjustment(gtk.Adjustment(
+ value=CONFIG['client.limit'], lower=1, upper=sys.maxint,
+ step_incr=10, page_incr=100))
hbox.pack_start(self.spin_limit, expand=True, fill=True)
self.win.vbox.pack_start(hbox, expand=True, fill=True)
diff --git a/tryton/gui/window/preference.py b/tryton/gui/window/preference.py
index 3f0359675c..69f04c38eb 100644
--- a/tryton/gui/window/preference.py
+++ b/tryton/gui/window/preference.py
@@ -19,7 +19,7 @@ class Preference(object):
def __init__(self, user):
self.parent = common.get_toplevel_window()
self.win = gtk.Dialog(_('Preferences'), self.parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.win.set_has_separator(False)
self.win.set_icon(TRYTON_ICON)
diff --git a/tryton/gui/window/shortcuts.py b/tryton/gui/window/shortcuts.py
index 2d6bc3df01..b1a3733aec 100644
--- a/tryton/gui/window/shortcuts.py
+++ b/tryton/gui/window/shortcuts.py
@@ -91,7 +91,7 @@ Examples:
label.set_alignment(0, 0.5)
table.attach(label, 1, 2, i, i + 1,
yoptions=False, xoptions=gtk.FILL)
- i +=1
+ i += 1
return table
def run(self):
diff --git a/tryton/gui/window/tips.py b/tryton/gui/window/tips.py
index a5348abd3c..e6528fa0e5 100644
--- a/tryton/gui/window/tips.py
+++ b/tryton/gui/window/tips.py
@@ -18,7 +18,8 @@ class Tips(object):
'''),
- _(u'''Do you know Triton, one of the namesakes for our project?
+ _(
+u'''Do you know Triton, one of the namesakes for our project?
Triton (pronounced /ˈtraɪtən/ TRYE-tən, or as in Greek Τρίτων) is the
largest moon of the planet Neptune, discovered on October 10, 1846
@@ -41,7 +42,6 @@ You can save any graphs in PNG file with right-click on it.
'''),
]
-
parent = get_toplevel_window()
self.win = gtk.Dialog(_('Tips'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
@@ -118,5 +118,3 @@ You can save any graphs in PNG file with right-click on it.
def tip_previous(self, widget):
self.number -= 1
self.tip_set()
-
-
diff --git a/tryton/gui/window/view_board/action.py b/tryton/gui/window/view_board/action.py
index a88223182d..64859add15 100644
--- a/tryton/gui/window/view_board/action.py
+++ b/tryton/gui/window/view_board/action.py
@@ -4,14 +4,9 @@
import gtk
from tryton.gui.window.view_form.screen import Screen
import tryton.rpc as rpc
-import time
-import datetime
-from tryton.gui.window.win_search import WinSearch
-from tryton.action import Action as Action2
import tryton.common as common
from tryton.pyson import PYSONDecoder
import gettext
-from tryton.config import CONFIG
from tryton.signal_event import SignalEvent
from tryton.exceptions import TrytonServerError
from tryton.gui.window.win_form import WinForm
@@ -89,7 +84,7 @@ class Action(SignalEvent):
else:
self.title.set_text(name)
- self.widget.set_size_request(int(attrs.get('width',-1)),
+ self.widget.set_size_request(int(attrs.get('width', -1)),
int(attrs.get('height', -1)))
self.screen.search_filter()
@@ -97,6 +92,7 @@ class Action(SignalEvent):
def row_activate(self):
if not self.screen.current_record:
pass
+
def callback(result):
if result:
self.screen.current_record.save()
@@ -133,5 +129,5 @@ class Action(SignalEvent):
return
del self.domain[:]
self.domain.extend(new_domain)
- if hasattr(self, 'screen'): # Catch early update
+ if hasattr(self, 'screen'): # Catch early update
self.display()
diff --git a/tryton/gui/window/view_board/parser.py b/tryton/gui/window/view_board/parser.py
index 7aa0abedd0..e22021cf80 100644
--- a/tryton/gui/window/view_board/parser.py
+++ b/tryton/gui/window/view_board/parser.py
@@ -2,10 +2,13 @@
#this repository contains the full copyright notices and license terms.
'Parser'
import gtk
-from tryton.gui.window.view_form.view.form_gtk.parser import _container
+import gettext
+from tryton.gui.window.view_form.view.form_gtk.parser import _container, VBox
import tryton.common as common
from action import Action
-from tryton.config import CONFIG, TRYTON_ICON
+from tryton.config import CONFIG
+
+_ = gettext.gettext
class ParserBoard(object):
@@ -47,13 +50,6 @@ class ParserBoard(object):
xexpand=xexpand, xfill=xfill)
elif node.localName == 'separator':
text = attrs.get('string', '')
- if 'string' in attrs or 'name' in attrs:
- if not text:
- if 'name' in attrs and attrs['name'] in fields:
- if 'states' in fields[attrs['name']]:
- attrs['states'] = \
- fields[attrs['name']]['states']
- text = fields[attrs['name']]['string']
vbox = VBox(attrs=attrs)
if text:
label = gtk.Label(text)
@@ -68,22 +64,6 @@ class ParserBoard(object):
xexpand=xexpand, xfill=xfill)
elif node.localName == 'label':
text = attrs.get('string', '')
- if not text:
- if 'name' in attrs and attrs['name'] in fields:
- if 'states' in fields[attrs['name']]:
- attrs['states'] = fields[attrs['name']]['states']
- if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- text = _(':') + fields[attrs['name']]['string']
- else:
- text = fields[attrs['name']]['string'] + _(':')
- if 'align' not in attrs:
- attrs['align'] = 1.0
- else:
- for node in node.childNodes:
- if node.nodeType == node.TEXT_NODE:
- text += node.data
- else:
- text += node.toxml()
if not text:
container.empty_add(int(attrs.get('colspan', 1)))
continue
@@ -115,7 +95,8 @@ class ParserBoard(object):
container.wid_add(notebook,
colspan=int(attrs.get('colspan', 4)),
yexpand=True, yfill=True)
- widget, new_widgets = self.parse(node, notebook, tooltips=tooltips)
+ widget, new_widgets = self.parse(node, notebook,
+ tooltips=tooltips)
widgets += new_widgets
elif node.localName == 'page':
if CONFIG['client.form_tab'] == 'left':
@@ -124,9 +105,10 @@ class ParserBoard(object):
angle = -90
else:
angle = 0
- label = gtk.Label(attrs.get('string','No String Attr.'))
+ label = gtk.Label(attrs.get('string', _('No String Attr.')))
label.set_angle(angle)
- widget, new_widgets = self.parse(node, notebook, tooltips=tooltips)
+ widget, new_widgets = self.parse(node, notebook,
+ tooltips=tooltips)
widgets += new_widgets
notebook.append_page(widget, label)
elif node.localName == 'group':
@@ -145,7 +127,8 @@ class ParserBoard(object):
hpaned = gtk.HPaned()
container.wid_add(hpaned, colspan=int(attrs.get('colspan', 4)),
yexpand=True, yfill=True)
- widget, new_widgets = self.parse(node, paned=hpaned, tooltips=tooltips)
+ widget, new_widgets = self.parse(node, paned=hpaned,
+ tooltips=tooltips)
widgets += new_widgets
if 'position' in attrs:
hpaned.set_position(int(attrs['position']))
@@ -153,19 +136,20 @@ class ParserBoard(object):
vpaned = gtk.VPaned()
container.wid_add(vpaned, colspan=int(attrs.get('colspan', 4)),
yexpand=True, yfill=True)
- widget, new_widgets = self.parse(node, paned=vpaned, tooltips=tooltips)
+ widget, new_widgets = self.parse(node, paned=vpaned,
+ tooltips=tooltips)
widgets += new_widgets
if 'position' in attrs:
vpaned.set_position(int(attrs['position']))
elif node.localName == 'child':
- widget, new_widgets = self.parse(node, paned=paned, tooltips=tooltips)
+ widget, new_widgets = self.parse(node, paned=paned,
+ tooltips=tooltips)
widgets += new_widgets
if not paned.get_child1():
paned.pack1(widget, resize=True, shrink=True)
elif not paned.get_child2():
paned.pack2(widget, resize=True, shrink=True)
elif node.localName == 'action':
- name = str(attrs['name'])
widget_act = Action(attrs, self.context)
widgets.append(widget_act)
yexpand = bool(attrs.get('yexpand', 1))
diff --git a/tryton/gui/window/view_board/view_board.py b/tryton/gui/window/view_board/view_board.py
index fde66aec38..688e0cff2b 100644
--- a/tryton/gui/window/view_board/view_board.py
+++ b/tryton/gui/window/view_board/view_board.py
@@ -6,6 +6,7 @@ import xml.dom.minidom
from parser import ParserBoard
from tryton.gui.window.view_board.action import Action
+
class ViewBoard(object):
'View board'
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index d0f469e853..903c6de2c2 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -3,14 +3,13 @@
import os
import tempfile
import tryton.rpc as rpc
-from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, datetime_strftime, \
+from tryton.common import DT_FORMAT, DHM_FORMAT, datetime_strftime, \
domain_inversion, eval_domain, localize_domain, unlocalize_domain, \
merge, inverse_leaf, EvalEnvironment, RPCProgress
import tryton.common as common
import time
import datetime
from decimal import Decimal
-import logging
from tryton.exceptions import TrytonServerError
@@ -60,8 +59,8 @@ class CharField(object):
def validation_domains(self, record):
screen_domain, attr_domain = self.domains_get(record)
if attr_domain:
- return screen_domain, screen_domain + unlocalize_domain(attr_domain,
- self.name)
+ return (screen_domain, screen_domain +
+ unlocalize_domain(attr_domain, self.name))
else:
return screen_domain, screen_domain
@@ -91,12 +90,13 @@ class CharField(object):
elif domain == [('id', '=', False)]:
res = False
else:
- if (isinstance(inverted_domain, list) \
- and len(inverted_domain) == 1 and inverted_domain[0][1] == '='):
- # If the inverted domain is so constraint that only one value is
- # possible we should use it. But we must also pay attention to
- # the fact that the original domain might be a 'OR' domain and
- # thus not preventing the modification of fields.
+ if (isinstance(inverted_domain, list)
+ and len(inverted_domain) == 1
+ and inverted_domain[0][1] == '='):
+ # If the inverted domain is so constraint that only one value
+ # is possible we should use it. But we must also pay attention
+ # to the fact that the original domain might be a 'OR' domain
+ # and thus not preventing the modification of fields.
leftpart, _, value = inverted_domain[0][:3]
setdefault = True
if '.' in leftpart:
@@ -135,9 +135,9 @@ class CharField(object):
def set_client(self, record, value, force_change=False):
internal = record.value.get(self.name, False)
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
- if (internal or False) != (record.value.get(self.name, False) or False):
+ if ((internal or False)
+ != (record.value.get(self.name, False) or False)):
record.modified_fields.setdefault(self.name)
record.signal('record-modified')
self.sig_changed(record)
@@ -230,11 +230,10 @@ class FloatField(CharField):
def set_client(self, record, value, force_change=False):
internal = record.value.get(self.name)
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
digits = record.expr_eval(self.attrs.get('digits', (16, 2)))
- if abs(float(internal or 0.0) - float(record.value[self.name] or 0.0)) \
- >= (10.0**(-int(digits[1]))):
+ if (abs(float(internal or 0.0) - float(record.value[self.name] or 0.0))
+ >= (10.0 ** (-int(digits[1])))):
if not self.get_state_attrs(record).get('readonly', False):
record.modified_fields.setdefault(self.name)
record.signal('record-modified')
@@ -248,12 +247,11 @@ class NumericField(CharField):
def set_client(self, record, value, force_change=False):
value = Decimal(str(value))
internal = record.value.get(self.name)
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
digits = record.expr_eval(self.attrs.get('digits', (16, 2)))
- if abs((internal or Decimal('0.0')) - \
- (record.value[self.name] or Decimal('0.0'))) \
- >= Decimal(str(10.0**(-int(digits[1])))):
+ if (abs((internal or Decimal('0.0'))
+ - (record.value[self.name] or Decimal('0.0')))
+ >= Decimal(str(10.0 ** (-int(digits[1]))))):
if not self.get_state_attrs(record).get('readonly', False):
record.modified_fields.setdefault(self.name)
record.signal('record-modified')
@@ -270,12 +268,12 @@ class IntegerField(CharField):
def get_client(self, record):
return record.value.get(self.name) or 0
+
class BooleanField(CharField):
def set_client(self, record, value, force_change=False):
value = bool(value)
internal = bool(record.value.get(self.name, False))
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
if internal != bool(record.value.get(self.name, False)):
record.modified_fields.setdefault(self.name)
@@ -367,7 +365,6 @@ class M2OField(CharField):
def set_client(self, record, value, force_change=False):
internal = record.value.get(self.name) or (False, '')
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
if (internal[0] or False) != (record.value[self.name][0] or False):
record.modified_fields.setdefault(self.name)
@@ -394,7 +391,8 @@ class M2OField(CharField):
def domain_get(self, record):
screen_domain, attr_domain = self.domains_get(record)
- return localize_domain(inverse_leaf(screen_domain), self.name) + attr_domain
+ return (localize_domain(inverse_leaf(screen_domain), self.name)
+ + attr_domain)
def get_state_attrs(self, record):
result = super(M2OField, self).get_state_attrs(record)
@@ -404,6 +402,7 @@ class M2OField(CharField):
result['readonly'] = True
return result
+
class O2OField(M2OField):
pass
@@ -453,7 +452,8 @@ class O2MField(CharField):
if record.model_name == self.attrs['relation']:
group.fields = record.group.fields
group.signal_connect(group, 'group-changed', self._group_changed)
- group.signal_connect(group, 'group-list-changed', self._group_list_changed)
+ group.signal_connect(group, 'group-list-changed',
+ self._group_list_changed)
group.signal_connect(group, 'group-cleared', self._group_cleared)
record.value[self.name] = group
@@ -493,10 +493,10 @@ class O2MField(CharField):
if record.value.get(self.name) is None:
return {}
result = {}
- for record2 in (record.value[self.name] \
- + record.value[self.name].record_removed \
+ for record2 in (record.value[self.name]
+ + record.value[self.name].record_removed
+ record.value[self.name].record_deleted):
- result.update(record2.get_timestamp())
+ result.update(record2.get_timestamp())
return result
def get_eval(self, record, check_load=True):
@@ -530,7 +530,8 @@ class O2MField(CharField):
record.value[self.name] = group
group.load(value, display=False)
group.signal_connect(group, 'group-changed', self._group_changed)
- group.signal_connect(group, 'group-list-changed', self._group_list_changed)
+ group.signal_connect(group, 'group-list-changed',
+ self._group_list_changed)
group.signal_connect(group, 'group-cleared', self._group_cleared)
if modified:
record.modified_fields.setdefault(self.name)
@@ -591,7 +592,8 @@ class O2MField(CharField):
new_record.set_default(vals, modified=modified)
group.add(new_record)
group.signal_connect(group, 'group-changed', self._group_changed)
- group.signal_connect(group, 'group-list-changed', self._group_list_changed)
+ group.signal_connect(group, 'group-list-changed',
+ self._group_list_changed)
group.signal_connect(group, 'group-cleared', self._group_cleared)
return True
@@ -717,7 +719,8 @@ class M2MField(O2MField):
group.fields = fields
group.load(value, display=False)
group.signal_connect(group, 'group-changed', self._group_changed)
- group.signal_connect(group, 'group-list-changed', self._group_list_changed)
+ group.signal_connect(group, 'group-list-changed',
+ self._group_list_changed)
group.signal_connect(group, 'group-cleared', self._group_cleared)
if modified:
record.modified_fields.setdefault(self.name)
@@ -744,7 +747,6 @@ class ReferenceField(CharField):
def set_client(self, record, value, force_change=False):
internal = record.value.get(self.name)
- prev_modified_fields = record.modified_fields.copy()
self.set(record, value)
if (internal or False) != (record.value[self.name] or False):
record.modified_fields.setdefault(self.name)
@@ -792,6 +794,7 @@ class ReferenceField(CharField):
record.modified_fields.setdefault(self.name)
record.signal('record-modified')
+
class BinaryField(CharField):
def get(self, record, check_load=True, readonly=True, modified=False):
@@ -849,14 +852,14 @@ TYPES = {
'char': CharField,
'sha': CharField,
'float_time': FloatField,
- 'integer' : IntegerField,
- 'biginteger' : IntegerField,
- 'float' : FloatField,
- 'numeric' : NumericField,
- 'many2one' : M2OField,
- 'many2many' : M2MField,
- 'one2many' : O2MField,
- 'reference' : ReferenceField,
+ 'integer': IntegerField,
+ 'biginteger': IntegerField,
+ 'float': FloatField,
+ 'numeric': NumericField,
+ 'many2one': M2OField,
+ 'many2many': M2MField,
+ 'one2many': O2MField,
+ 'reference': ReferenceField,
'selection': SelectionField,
'boolean': BooleanField,
'datetime': DateTimeField,
diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py
index 338cf67462..a32dab1b48 100644
--- a/tryton/gui/window/view_form/model/group.py
+++ b/tryton/gui/window/view_form/model/group.py
@@ -1,6 +1,5 @@
#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 copy
import tryton.rpc as rpc
from record import Record
from field import Field, O2MField
@@ -236,8 +235,8 @@ class Group(SignalEvent, list):
ctx = rpc.CONTEXT.copy()
ctx.update(self._context)
if self.parent_datetime_field:
- ctx['_datetime'] = self.parent.get_eval(check_load=False)\
- [self.parent_datetime_field]
+ ctx['_datetime'] = self.parent.get_eval(check_load=False
+ )[self.parent_datetime_field]
return ctx
context = property(_get_context)
@@ -247,7 +246,8 @@ class Group(SignalEvent, list):
record.signal_unconnect(record.group)
record.group = self
record.signal_connect(self, 'record-changed', self._record_changed)
- record.signal_connect(self, 'record-modified', self._record_modified)
+ record.signal_connect(self, 'record-modified',
+ self._record_modified)
if position == -1:
self.append(record)
else:
@@ -373,7 +373,8 @@ class Group(SignalEvent, list):
if len(new) and len(to_add):
ctx.update(self.context)
- args = ('model', self.model_name, 'default_get', to_add.keys(), ctx)
+ args = ('model', self.model_name, 'default_get', to_add.keys(),
+ ctx)
try:
values = rpc.execute(*args)
except TrytonServerError, exception:
diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py
index 9cc919927c..6d882e6336 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -4,10 +4,7 @@ import tryton.rpc as rpc
from tryton.signal_event import SignalEvent
import tryton.common as common
from tryton.pyson import PYSONDecoder
-import field
-import datetime
-import logging
-import time
+import field as fields
from functools import reduce
from tryton.exceptions import TrytonServerError
@@ -33,14 +30,14 @@ class Record(SignalEvent):
self.modified_fields = {}
self._timestamp = None
self.attachment_count = -1
- self.next = {} # Used in Group list
+ self.next = {} # Used in Group list
self.value = {}
self.autocompletion = {}
self.exception = False
def __getitem__(self, name, raise_exception=False):
if name not in self._loaded and self.id >= 0:
- ids = [self.id]
+ ids = [self.id]
if name == '*':
loading = reduce(
lambda x, y: 'eager' if x == y == 'eager' else 'lazy',
@@ -65,21 +62,22 @@ class Record(SignalEvent):
ids.append(record.id)
n += 1
if loading == 'eager':
- fields = [fname for fname, field in self.group.fields.iteritems()
- if field.attrs.get('loading', 'eager') == 'eager']
+ fnames = [fname
+ for fname, field in self.group.fields.iteritems()
+ if field.attrs.get('loading', 'eager') == 'eager']
else:
- fields = self.group.fields.keys()
- fields = [fname for fname in fields if fname not in self._loaded]
- fields.extend(('%s.rec_name' % fname for fname in fields[:]
+ fnames = self.group.fields.keys()
+ fnames = [fname for fname in fnames if fname not in self._loaded]
+ fnames.extend(('%s.rec_name' % fname for fname in fnames[:]
if self.group.fields[fname].attrs['type']
in ('many2one', 'one2one', 'reference')))
- fields.append('_timestamp')
+ fnames.append('_timestamp')
ctx = rpc.CONTEXT.copy()
ctx.update(self.context_get())
ctx.update(dict(('%s.%s' % (self.model_name, fname), 'size')
for fname, field in self.group.fields.iteritems()
if field.attrs['type'] == 'binary'))
- args = ('model', self.model_name, 'read', ids, fields, ctx)
+ args = ('model', self.model_name, 'read', ids, fnames, ctx)
exception = None
try:
values = rpc.execute(*args)
@@ -89,7 +87,7 @@ class Record(SignalEvent):
values = common.process_exception(exception, *args)
if not values:
values = [{'id': x} for x in ids]
- default_values = dict((f, False) for f in fields)
+ default_values = dict((f, False) for f in fnames)
for value in values:
value.update(default_values)
self.exception = True
@@ -391,10 +389,11 @@ class Record(SignalEvent):
for fieldname, value in val.items():
if fieldname not in self.group.fields:
continue
- if isinstance(self.group.fields[fieldname], field.M2OField):
+ if isinstance(self.group.fields[fieldname], fields.M2OField):
if fieldname + '.rec_name' in val:
value = (value, val[fieldname + '.rec_name'])
- elif isinstance(self.group.fields[fieldname], field.ReferenceField):
+ elif isinstance(self.group.fields[fieldname],
+ fields.ReferenceField):
if value:
ref_model, ref_id = value.split(',', 1)
if fieldname + '.rec_name' in val:
@@ -417,13 +416,14 @@ class Record(SignalEvent):
continue
if fieldname not in self.group.fields:
continue
- if isinstance(self.group.fields[fieldname], field.O2MField):
+ if isinstance(self.group.fields[fieldname], fields.O2MField):
later[fieldname] = value
continue
- if isinstance(self.group.fields[fieldname], field.M2OField):
+ if isinstance(self.group.fields[fieldname], fields.M2OField):
if fieldname + '.rec_name' in val:
value = (value, val[fieldname + '.rec_name'])
- elif isinstance(self.group.fields[fieldname], field.ReferenceField):
+ elif isinstance(self.group.fields[fieldname],
+ fields.ReferenceField):
if value:
ref_model, ref_id = value.split(',', 1)
if fieldname + '.rec_name' in val:
@@ -501,14 +501,14 @@ class Record(SignalEvent):
for fieldname, value in res.items():
if fieldname not in self.group.fields:
continue
- if isinstance(self.group.fields[fieldname], field.O2MField):
+ if isinstance(self.group.fields[fieldname], fields.O2MField):
later[fieldname] = value
continue
- if isinstance(self.group.fields[fieldname], field.M2OField):
+ if isinstance(self.group.fields[fieldname], fields.M2OField):
if fieldname + '.rec_name' in res:
value = (value, res[fieldname + '.rec_name'])
elif isinstance(self.group.fields[fieldname],
- field.ReferenceField):
+ fields.ReferenceField):
if value:
ref_model, ref_id = value.split(',', 1)
if fieldname + '.rec_name' in res:
@@ -602,5 +602,8 @@ class Record(SignalEvent):
def destroy(self):
super(Record, self).destroy()
self.group = None
+ for v in self.value.itervalues():
+ if hasattr(v, 'destroy'):
+ v.destroy()
self.value = None
self.next = None
diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py
index fc383cd701..31559c45d5 100644
--- a/tryton/gui/window/view_form/screen/screen.py
+++ b/tryton/gui/window/view_form/screen/screen.py
@@ -6,7 +6,6 @@ try:
import simplejson as json
except ImportError:
import json
-import copy
import collections
import xml.dom.minidom
import tryton.rpc as rpc
@@ -14,7 +13,6 @@ from tryton.gui.window.view_form.model.group import Group
from tryton.gui.window.view_form.model.record import Record
from tryton.gui.window.view_form.view.screen_container import ScreenContainer
from tryton.signal_event import SignalEvent
-from tryton.common import node_attributes
from tryton.config import CONFIG
import tryton.common as common
from tryton.exceptions import TrytonServerError, TrytonServerUnavailable
@@ -368,13 +366,18 @@ class Screen(SignalEvent):
self.fields_view_tree = view
break
+ # Ensure that loading is always eager for fields on tree view
+ # and always lazy for fields only on form view
if node.localName == 'tree':
loading = 'eager'
else:
loading = 'lazy'
for field in fields:
- if field not in self.group.fields:
+ if field not in self.group.fields or loading == 'eager':
fields[field]['loading'] = loading
+ else:
+ fields[field]['loading'] = \
+ self.group.fields[field].attrs['loading']
children_field = view.get('field_childs')
@@ -436,9 +439,6 @@ class Screen(SignalEvent):
record = group.new(default, self.domain, ctx)
group.add(record, self.new_model_position())
self.current_record = record
- fields = None
- if self.current_view:
- fields = self.current_view.get_fields()
self.display()
self.set_cursor(new=True)
self.request_set()
@@ -505,7 +505,8 @@ class Screen(SignalEvent):
elif current_view.view_type == 'tree' and not self.current_record:
# The widget might have been destroyed
if self.screen_container:
- self.screen_container.set_cursor(new=new, reset_view=reset_view)
+ self.screen_container.set_cursor(new=new,
+ reset_view=reset_view)
elif current_view.view_type in ('tree', 'form'):
current_view.set_cursor(new=new, reset_view=reset_view)
@@ -528,7 +529,8 @@ class Screen(SignalEvent):
res = False
if self.current_view.view_type != 'tree':
if self.current_record:
- res = self.current_record.modified or self.current_record.id < 0
+ res = (self.current_record.modified
+ or self.current_record.id < 0)
else:
for record in self.group:
if record.modified or record.id < 0:
diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py
index 8c72e4dbc8..a26677a336 100644
--- a/tryton/gui/window/view_form/view/form.py
+++ b/tryton/gui/window/view_form/view/form.py
@@ -4,11 +4,9 @@ import operator
from functools import reduce
import gtk
import gettext
-from tryton.common import message, TRYTON_ICON
import tryton.rpc as rpc
import tryton.common as common
from interface import ParserView
-from tryton.config import CONFIG
from tryton.exceptions import TrytonServerError
from tryton.action import Action
@@ -196,4 +194,3 @@ class ViewForm(ParserView):
self.screen.reload(written=True)
else:
self.screen.display()
-
diff --git a/tryton/gui/window/view_form/view/form_gtk/binary.py b/tryton/gui/window/view_form/view/form_gtk/binary.py
index 982ab1d572..44127283ac 100644
--- a/tryton/gui/window/view_form/view/form_gtk/binary.py
+++ b/tryton/gui/window/view_form/view/form_gtk/binary.py
@@ -5,7 +5,7 @@ import gettext
import os
import tempfile
from tryton.common import common
-from tryton.common import file_selection, message, warning, Tooltips, file_open
+from tryton.common import file_selection, Tooltips, file_open
from interface import WidgetInterface
_ = gettext.gettext
@@ -24,12 +24,15 @@ class Binary(WidgetInterface):
self.widget = gtk.HBox(spacing=0)
self.wid_size = gtk.Entry()
self.wid_size.set_width_chars(10)
+ self.wid_size.set_alignment(1.0)
self.wid_size.props.sensitive = False
if self.filename and attrs.get('filename_visible'):
self.wid_text = gtk.Entry()
self.wid_text.set_property('activates_default', True)
- self.wid_text.connect('focus-in-event', lambda x, y: self._focus_in())
- self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out())
+ self.wid_text.connect('focus-in-event',
+ lambda x, y: self._focus_in())
+ self.wid_text.connect('focus-out-event',
+ lambda x, y: self._focus_out())
self.wid_text.connect_after('key_press_event', self.sig_key_press)
self.widget.pack_start(self.wid_text, expand=True, fill=True)
else:
@@ -136,7 +139,7 @@ class Binary(WidgetInterface):
filename = file_selection(_('Save As...'), filename=filename,
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if filename:
- with open(filename,'wb') as fp:
+ with open(filename, 'wb') as fp:
fp.write(self.field.get_data(self.record))
def sig_remove(self, widget=None):
diff --git a/tryton/gui/window/view_form/view/form_gtk/calendar.py b/tryton/gui/window/view_form/view/form_gtk/calendar.py
index 0966ee1d28..8408719b5a 100644
--- a/tryton/gui/window/view_form/view/form_gtk/calendar.py
+++ b/tryton/gui/window/view_form/view/form_gtk/calendar.py
@@ -4,10 +4,8 @@ import time
import datetime
import gtk
import gettext
-import locale
from interface import WidgetInterface
-import tryton.rpc as rpc
-from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, message, \
+from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, \
TRYTON_ICON, timezoned_date
from tryton.common import date_widget, Tooltips, datetime_strftime, \
get_toplevel_window
@@ -89,7 +87,7 @@ class Calendar(WidgetInterface):
if not value:
self.entry.clear()
else:
- if len(value)>10:
+ if len(value) > 10:
value = value[:10]
date = datetime.date(*time.strptime(value, DT_FORMAT)[:3])
value = datetime_strftime(date, self.format)
@@ -101,9 +99,9 @@ class Calendar(WidgetInterface):
def cal_open(self, widget):
parent = get_toplevel_window()
win = gtk.Dialog(_('Date Selection'), parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
+ gtk.RESPONSE_OK))
win.set_has_separator(True)
win.set_icon(TRYTON_ICON)
@@ -120,7 +118,7 @@ class Calendar(WidgetInterface):
try:
val = self.get_value(self.record)
if val:
- cal.select_month(int(val[5:7])-1, int(val[0:4]))
+ cal.select_month(int(val[5:7]) - 1, int(val[0:4]))
cal.select_day(int(val[8:10]))
except ValueError:
pass
@@ -220,9 +218,9 @@ class DateTime(WidgetInterface):
def cal_open(self, widget):
parent = get_toplevel_window()
win = gtk.Dialog(_('Date Time Selection'), parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
+ gtk.RESPONSE_OK))
win.set_has_separator(True)
win.set_icon(TRYTON_ICON)
win.vbox.set_spacing(2)
@@ -252,7 +250,7 @@ class DateTime(WidgetInterface):
if val:
widget_hour.set_value(int(val[11:13]))
widget_minute.set_value(int(val[-5:-3]))
- cal.select_month(int(val[5:7])-1, int(val[0:4]))
+ cal.select_month(int(val[5:7]) - 1, int(val[0:4]))
cal.select_day(int(val[8:10]))
else:
widget_hour.set_value(time.localtime()[3])
diff --git a/tryton/gui/window/view_form/view/form_gtk/checkbox.py b/tryton/gui/window/view_form/view/form_gtk/checkbox.py
index 1bdca3f739..2f994125f7 100644
--- a/tryton/gui/window/view_form/view/form_gtk/checkbox.py
+++ b/tryton/gui/window/view_form/view/form_gtk/checkbox.py
@@ -6,6 +6,7 @@ import gettext
_ = gettext.gettext
+
class CheckBox(WidgetInterface):
def __init__(self, field_name, model_name, attrs=None):
diff --git a/tryton/gui/window/view_form/view/form_gtk/float.py b/tryton/gui/window/view_form/view/form_gtk/float.py
index 26de08b29d..73a294cb27 100644
--- a/tryton/gui/window/view_form/view/form_gtk/float.py
+++ b/tryton/gui/window/view_form/view/form_gtk/float.py
@@ -67,4 +67,3 @@ class Float(Integer):
if len(new_int) > digits[0] \
or len(new_decimal) > digits[1]:
entry.stop_emission('insert-text')
-
diff --git a/tryton/gui/window/view_form/view/form_gtk/float_time.py b/tryton/gui/window/view_form/view/form_gtk/float_time.py
index 1644babecf..86c2d497eb 100644
--- a/tryton/gui/window/view_form/view/form_gtk/float_time.py
+++ b/tryton/gui/window/view_form/view/form_gtk/float_time.py
@@ -35,8 +35,9 @@ class FloatTime(WidgetInterface):
value = self.entry.get_text()
if not value:
return field.set_client(record, 0.0)
+ digits = record.expr_eval(field.attrs.get('digits', (16, 2)))
return field.set_client(record,
- common.text_to_float_time(value, self.conv))
+ round(common.text_to_float_time(value, self.conv), digits[1]))
def display(self, record, field):
super(FloatTime, self).display(record, field)
diff --git a/tryton/gui/window/view_form/view/form_gtk/image.py b/tryton/gui/window/view_form/view/form_gtk/image.py
index 3422406ae5..49cd276aa3 100644
--- a/tryton/gui/window/view_form/view/form_gtk/image.py
+++ b/tryton/gui/window/view_form/view/form_gtk/image.py
@@ -54,7 +54,8 @@ class Image(WidgetInterface):
if self.filename:
self.but_open = gtk.Button()
img_open = gtk.Image()
- img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ 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)
@@ -65,7 +66,8 @@ class Image(WidgetInterface):
self.but_save_as = gtk.Button()
img_save_as = gtk.Image()
- img_save_as.set_from_stock('tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ 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)
@@ -74,7 +76,8 @@ class Image(WidgetInterface):
self.but_remove = gtk.Button()
img_remove = gtk.Image()
- img_remove.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ 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)
@@ -193,7 +196,7 @@ class Image(WidgetInterface):
if self.field:
value = self.field.get_client(self.record)
if isinstance(value, (int, long)):
- if value > 10**6:
+ if value > 10 ** 6:
value = False
else:
value = self.field.get_data(self.record)
diff --git a/tryton/gui/window/view_form/view/form_gtk/interface.py b/tryton/gui/window/view_form/view/form_gtk/interface.py
index 9010889807..4924e6cc8b 100644
--- a/tryton/gui/window/view_form/view/form_gtk/interface.py
+++ b/tryton/gui/window/view_form/view/form_gtk/interface.py
@@ -9,7 +9,7 @@ class WidgetInterface(object):
def __init__(self, field_name, model_name, attrs=None):
self.field_name = field_name
self.model_name = model_name
- self.view = None # Filled by ViewForm
+ self.view = None # Filled by ViewForm
self.attrs = attrs or {}
for attr_name in ('readonly', 'invisible'):
if attr_name in self.attrs:
diff --git a/tryton/gui/window/view_form/view/form_gtk/many2many.py b/tryton/gui/window/view_form/view/form_gtk/many2many.py
index 3465071e5f..878c684db0 100644
--- a/tryton/gui/window/view_form/view/form_gtk/many2many.py
+++ b/tryton/gui/window/view_form/view/form_gtk/many2many.py
@@ -50,7 +50,6 @@ class Many2Many(WidgetInterface):
self.but_add.set_relief(gtk.RELIEF_NONE)
hbox.pack_start(self.but_add, expand=False, fill=False)
-
self.but_remove = gtk.Button()
tooltips.set_tip(self.but_remove, _('Remove'))
self.but_remove.connect('clicked', self._sig_remove)
@@ -130,7 +129,7 @@ class Many2Many(WidgetInterface):
else:
dom = domain
ids = rpc.execute('model', self.attrs['relation'], 'search',
- dom , 0, CONFIG['client.limit'], None, context)
+ dom, 0, CONFIG['client.limit'], None, context)
except TrytonServerError, exception:
common.process_exception(exception)
return False
diff --git a/tryton/gui/window/view_form/view/form_gtk/many2one.py b/tryton/gui/window/view_form/view/form_gtk/many2one.py
index 81d8bf5d85..f6b11d9b9f 100644
--- a/tryton/gui/window/view_form/view/form_gtk/many2one.py
+++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py
@@ -1,10 +1,8 @@
#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 gobject
import gtk
import gettext
from interface import WidgetInterface
-from tryton.common import TRYTON_ICON, COLOR_SCHEMES
import tryton.common as common
from tryton.gui.window.view_form.screen import Screen
from tryton.gui.window.win_search import WinSearch
@@ -14,7 +12,6 @@ from tryton.action import Action
from tryton.config import CONFIG
from tryton.pyson import PYSONEncoder
from tryton.exceptions import TrytonServerError
-import pango
_ = gettext.gettext
@@ -33,7 +30,8 @@ class Many2One(WidgetInterface):
self.wid_text.connect_after('key_press_event', self.sig_key_press)
self.wid_text.connect('populate-popup', self._populate_popup)
self.wid_text.connect('focus-in-event', lambda x, y: self._focus_in())
- self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out())
+ self.wid_text.connect('focus-out-event',
+ lambda x, y: self._focus_out())
self.wid_text.connect_after('changed', self.sig_changed)
self.changed = True
self.wid_text.connect('activate', self.sig_activate)
@@ -118,12 +116,13 @@ class Many2One(WidgetInterface):
common.process_exception(exception)
self.changed = True
return
- if len(ids)==1:
+ if len(ids) == 1:
self.field.set_client(self.record, ids[0],
force_change=True)
self.focus_out = True
self.display(self.record, self.field)
return
+
def callback(ids):
if ids:
self.field.set_client(self.record, ids[0],
@@ -150,6 +149,7 @@ class Many2One(WidgetInterface):
def sig_new(self, *args):
self.focus_out = False
screen = self.get_screen()
+
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
@@ -165,6 +165,7 @@ class Many2One(WidgetInterface):
if value:
screen = self.get_screen()
screen.load([self.field.get(self.record)])
+
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
@@ -200,7 +201,7 @@ class Many2One(WidgetInterface):
common.process_exception(exception)
self.changed = True
return False
- if ids and len(ids)==1:
+ if ids and len(ids) == 1:
self.field.set_client(self.record, ids[0],
force_change=True)
self.focus_out = True
@@ -230,7 +231,8 @@ class Many2One(WidgetInterface):
elif event.keyval == gtk.keysyms.F2:
self.sig_edit(widget)
return True
- elif event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return) and editable:
+ elif (event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return)
+ and editable):
self.sig_activate(widget, event, key_press=True)
return False
@@ -243,7 +245,7 @@ class Many2One(WidgetInterface):
return False
def set_value(self, record, field):
- pass # No update of the model, the model is updated in real time !
+ pass # No update of the model, the model is updated in real time !
def display(self, record, field):
self.changed = False
@@ -280,9 +282,9 @@ class Many2One(WidgetInterface):
menu_entries.append((None, None, None))
menu_entries.append((None, None, None))
menu_entries.append((_('Actions'),
- lambda x: self.click_and_action('form_action'),0))
+ lambda x: self.click_and_action('form_action'), 0))
menu_entries.append((_('Reports'),
- lambda x: self.click_and_action('form_print'),0))
+ lambda x: self.click_and_action('form_print'), 0))
menu_entries.append((None, None, None))
for relate in relates:
relate['string'] = relate['name']
diff --git a/tryton/gui/window/view_form/view/form_gtk/one2many.py b/tryton/gui/window/view_form/view/form_gtk/one2many.py
index 0862b8f2df..ee89d1a666 100644
--- a/tryton/gui/window/view_form/view/form_gtk/one2many.py
+++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py
@@ -2,7 +2,6 @@
#this repository contains the full copyright notices and license terms.
import gtk
import gettext
-from tryton.common import TRYTON_ICON, COLOR_SCHEMES
from interface import WidgetInterface
from tryton.gui.window.view_form.screen import Screen
from tryton.gui.window.win_search import WinSearch
@@ -11,7 +10,6 @@ from tryton.config import CONFIG
from tryton.exceptions import TrytonServerError
import tryton.common as common
import tryton.rpc as rpc
-import pango
_ = gettext.gettext
@@ -47,7 +45,8 @@ class One2Many(WidgetInterface):
tooltips.set_tip(self.but_add, _('Add'))
self.but_add.connect('clicked', self._sig_add)
img_add = gtk.Image()
- img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_add.set_from_stock('tryton-list-add',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_add.set_alignment(0.5, 0.5)
self.but_add.add(img_add)
self.but_add.set_relief(gtk.RELIEF_NONE)
@@ -57,7 +56,8 @@ class One2Many(WidgetInterface):
tooltips.set_tip(self.but_remove, _('Remove'))
self.but_remove.connect('clicked', self._sig_remove, True)
img_remove = gtk.Image()
- img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_remove.set_from_stock('tryton-list-remove',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_remove.set_alignment(0.5, 0.5)
self.but_remove.add(img_remove)
self.but_remove.set_relief(gtk.RELIEF_NONE)
@@ -111,7 +111,8 @@ class One2Many(WidgetInterface):
tooltips.set_tip(self.but_pre, _('Previous'))
self.but_pre.connect('clicked', self._sig_previous)
img_pre = gtk.Image()
- img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_pre.set_from_stock('tryton-go-previous',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_pre.set_alignment(0.5, 0.5)
self.but_pre.add(img_pre)
self.but_pre.set_relief(gtk.RELIEF_NONE)
@@ -136,7 +137,8 @@ class One2Many(WidgetInterface):
tooltips.set_tip(but_switch, _('Switch'))
but_switch.connect('clicked', self.switch_view)
img_switch = gtk.Image()
- img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_switch.set_from_stock('tryton-fullscreen',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_switch.set_alignment(0.5, 0.5)
but_switch.add(img_switch)
but_switch.set_relief(gtk.RELIEF_NONE)
@@ -304,7 +306,8 @@ class One2Many(WidgetInterface):
try:
if self.wid_text.get_text():
- dom = [('rec_name', 'ilike', '%' + self.wid_text.get_text() + '%'),
+ dom = [('rec_name', 'ilike',
+ '%' + self.wid_text.get_text() + '%'),
['OR', domain, ('id', 'in', removed_ids)]]
else:
dom = ['OR', domain, ('id', 'in', removed_ids)]
@@ -313,6 +316,7 @@ class One2Many(WidgetInterface):
except TrytonServerError, exception:
common.process_exception(exception)
return False
+
def callback(ids):
res_id = None
if ids:
@@ -328,7 +332,6 @@ class One2Many(WidgetInterface):
else:
callback(ids)
-
def _sig_label(self, screen, signal_data):
name = '_'
if signal_data[0] >= 1:
@@ -386,7 +389,7 @@ class One2Many(WidgetInterface):
def set_value(self, record, field):
self.screen.save_tree_state()
self.screen.current_view.set_value()
- if self.screen.modified(): # TODO check if required
+ if self.screen.modified(): # TODO check if required
record.modified_fields.setdefault(field.name)
record.signal('record-modified')
return True
diff --git a/tryton/gui/window/view_form/view/form_gtk/parser.py b/tryton/gui/window/view_form/view/form_gtk/parser.py
index 6e21691340..cd08b607fc 100644
--- a/tryton/gui/window/view_form/view/form_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/form_gtk/parser.py
@@ -72,7 +72,7 @@ class Image(gtk.Image):
class Frame(gtk.Frame):
def __init__(self, label=None, attrs=None):
- if not label: # label must be None to have no label widget
+ if not label: # label must be None to have no label widget
label = None
super(Frame, self).__init__(label=label)
self.attrs = attrs or {}
@@ -137,8 +137,8 @@ class _container(object):
table.set_col_spacings(0)
table.set_row_spacings(0)
table.set_border_width(0)
- self.cont.append( (table, 0, 0) )
- self.col.append( col )
+ self.cont.append((table, 0, 0))
+ self.col.append(col)
def get(self):
return self.cont[-1][0]
@@ -155,8 +155,8 @@ class _container(object):
table.resize(height + 1, self.col[-1])
def wid_add(self, widget, name='', yexpand=False, ypadding=2, rowspan=1,
- colspan=1, translate=False, fname=None, help_tip=False, yfill=False,
- xexpand=True, xfill=True, xpadding=3):
+ colspan=1, translate=False, fname=None, help_tip=False,
+ yfill=False, xexpand=True, xfill=True, xpadding=3):
(table, width, height) = self.cont[-1]
if colspan > self.col[-1]:
colspan = self.col[-1]
@@ -182,7 +182,8 @@ class _container(object):
img.set_from_stock('tryton-locale', gtk.ICON_SIZE_SMALL_TOOLBAR)
button.set_image(img)
button.set_relief(gtk.RELIEF_NONE)
- self.trans_box.append((button, name, fname, widget.get_children()[0]))
+ self.trans_box.append((button, name, fname,
+ widget.get_children()[0]))
widget.get_child().pack_start(button, fill=False, expand=False)
widget.show_all()
table.attach(widget, width, width + colspan,
@@ -355,9 +356,9 @@ class ParserForm(ParserInterface):
colspan=colspan,
yexpand=yexpand, yfill=yfill,
xexpand=xexpand, xfill=xfill)
- widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
- self.parse(model_name, node, fields, notebook,
- tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list2, cursor_widget2\
+ = self.parse(model_name, node, fields, notebook,
+ tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -369,7 +370,7 @@ class ParserForm(ParserInterface):
elif node.localName == 'page':
if CONFIG['client.form_tab'] == 'left':
angle = 90
- tab_box = gtk.VBox(spacing=3)
+ tab_box = gtk.VBox(spacing=3)
image_pos, image_rotate = ('end',
gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
elif CONFIG['client.form_tab'] == 'right':
@@ -412,9 +413,9 @@ class ParserForm(ParserInterface):
else:
tab_box.pack_start(icon)
tab_box.show_all()
- widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
- self.parse(model_name, node, fields, notebook,
- tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list2, cursor_widget2\
+ = self.parse(model_name, node, fields, notebook,
+ tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -482,8 +483,8 @@ class ParserForm(ParserInterface):
xexpand=xexpand, xfill=xfill)
elif node.localName == 'group':
- widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
- self.parse(model_name, node, fields, tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list2, cursor_widget2\
+ = self.parse(model_name, node, fields, tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -515,9 +516,9 @@ class ParserForm(ParserInterface):
hpaned = gtk.HPaned()
container.wid_add(hpaned, colspan=int(attrs.get('colspan', 4)),
yexpand=True, yfill=True)
- widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
- self.parse(model_name, node, fields, paned=hpaned,
- tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list2, cursor_widget2\
+ = self.parse(model_name, node, fields, paned=hpaned,
+ tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -531,9 +532,9 @@ class ParserForm(ParserInterface):
vpaned = gtk.VPaned()
container.wid_add(vpaned, colspan=int(attrs.get('colspan', 4)),
yexpand=True, yfill=True)
- widget, widgets, buttons, spam, notebook_list, cursor_widget2 = \
- self.parse(model_name, node, fields, paned=vpaned,
- tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list, cursor_widget2\
+ = self.parse(model_name, node, fields, paned=vpaned,
+ tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -544,9 +545,9 @@ class ParserForm(ParserInterface):
if 'position' in attrs:
vpaned.set_position(int(attrs['position']))
elif node.localName == 'child':
- widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
- self.parse(model_name, node, fields, paned=paned,
- tooltips=tooltips)
+ widget, widgets, buttons, spam, notebook_list2, cursor_widget2\
+ = self.parse(model_name, node, fields, paned=paned,
+ tooltips=tooltips)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -568,7 +569,7 @@ class ParserForm(ParserInterface):
obj_id = self.screen.current_record.id
if obj_id < 0:
common.message(
- _('You need to save the record before adding translations!'))
+ _('You need to save the record before adding translations!'))
return False
obj_id = self.screen.current_record.save(force_reload=False)
@@ -599,6 +600,7 @@ class ParserForm(ParserInterface):
widget_entry = widget_entry.get_children()[0]
if isinstance(widget_entry, gtk.ScrolledWindow):
widget_entry = widget_entry.get_child()
+
#widget accessor functions
def value_get(widget):
if isinstance(widget, gtk.Entry):
@@ -643,10 +645,9 @@ class ParserForm(ParserInterface):
else:
return None, False
-
parent = common.get_toplevel_window()
- win = gtk.Dialog(_('Add Translation'),parent,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ win = gtk.Dialog(_('Add Translation'), parent,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
win.set_has_separator(True)
win.vbox.set_spacing(5)
win.set_property('default-width', 600)
@@ -657,7 +658,7 @@ class ParserForm(ParserInterface):
accel_group = gtk.AccelGroup()
win.add_accel_group(accel_group)
- but_cancel = win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+ win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
but_ok = win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
but_ok.add_accelerator('clicked', accel_group, gtk.keysyms.Return,
@@ -689,17 +690,16 @@ class ParserForm(ParserInterface):
label.set_alignment(1.0, 0.5)
(entry, yoptions) = widget_duplicate(widget_entry)
- hbox = gtk.HBox(homogeneous=False)
if code == lang['code']:
value_set(entry, value_get(widget_entry))
else:
value_set(entry, val[name])
entries_list.append((val['id'], lang['code'], entry))
- table.attach(label, 0, 1, i, i+1, yoptions=False, xoptions=gtk.FILL,
- ypadding=2, xpadding=3)
- table.attach(entry, 1, 2, i, i+1, yoptions=yoptions,
- ypadding=2, xpadding=3)
+ table.attach(label, 0, 1, i, i + 1, yoptions=False,
+ xoptions=gtk.FILL, ypadding=2, xpadding=3)
+ table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions,
+ ypadding=2, xpadding=3)
i += 1
vbox.pack_start(table)
@@ -714,7 +714,6 @@ class ParserForm(ParserInterface):
win.vbox.add(scrolledwindow)
win.show_all()
- data = []
response = win.run()
if response == gtk.RESPONSE_OK:
to_save = [(x[0], x[1], value_get(x[2])) for x in entries_list]
@@ -776,11 +775,11 @@ WIDGETS_TYPE = {
'one2many': (One2Many, 1, True, True),
'many2many': (Many2Many, 1, True, True),
'many2one': (Many2One, 1, False, False),
- 'email' : (Email, 1, False, False),
- 'url' : (URL, 1, False, False),
- 'callto' : (CallTo, 1, False, False),
- 'sip' : (SIP, 1, False, False),
- 'image' : (Image2, 1, False, False),
+ 'email': (Email, 1, False, False),
+ 'url': (URL, 1, False, False),
+ 'callto': (CallTo, 1, False, False),
+ 'sip': (SIP, 1, False, False),
+ 'image': (Image2, 1, False, False),
'progressbar': (ProgressBar, 1, False, False),
'one2one': (One2One, 1, False, False),
}
diff --git a/tryton/gui/window/view_form/view/form_gtk/reference.py b/tryton/gui/window/view_form/view/form_gtk/reference.py
index b84f82ca85..e652bdf642 100644
--- a/tryton/gui/window/view_form/view/form_gtk/reference.py
+++ b/tryton/gui/window/view_form/view/form_gtk/reference.py
@@ -88,7 +88,7 @@ class Reference(WidgetInterface):
if selection:
pop = sorted((len(x) for x in selection), reverse=True)
average = sum(pop) / len(pop)
- deviation = int(math.sqrt(sum((x - average)**2 for x in pop) /
+ deviation = int(math.sqrt(sum((x - average) ** 2 for x in pop) /
len(pop)))
width = max(next((x for x in pop if x < (deviation * 4)), 10), 10)
else:
@@ -149,7 +149,6 @@ class Reference(WidgetInterface):
def sig_focus_out(self, widget, event, leave=False):
if not self.focus_out:
return
- child = self.widget_combo.get_child()
self.changed = False
value = self.field.get_client(self.record)
@@ -166,6 +165,7 @@ class Reference(WidgetInterface):
if not leave:
screen = Screen(model, mode=['form'])
screen.load([obj_id])
+
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
@@ -178,7 +178,7 @@ class Reference(WidgetInterface):
WinForm(screen, callback)
return
elif model:
- if not self._readonly and ( self.wid_text.get_text() or not leave):
+ if not self._readonly and (self.wid_text.get_text() or not leave):
domain = self.field.domain_get(self.record)
context = self.field.context_get(self.record)
@@ -205,7 +205,8 @@ class Reference(WidgetInterface):
def callback(ids):
if ids:
- self.field.set_client(self.record, (model, (ids[0], '')))
+ self.field.set_client(self.record,
+ (model, (ids[0], '')))
self.focus_out = True
self.changed = True
self.display(self.record, self.field)
@@ -223,6 +224,7 @@ class Reference(WidgetInterface):
if not model:
return
screen = Screen(model, mode=['form'])
+
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
@@ -238,7 +240,8 @@ class Reference(WidgetInterface):
elif event.keyval == gtk.keysyms.F2:
self.sig_focus_out(widget, event)
return True
- elif event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return) and editable:
+ elif (event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return)
+ and editable):
if self.field.get(self.record) or \
not self.wid_text.get_text():
return False
@@ -272,7 +275,7 @@ class Reference(WidgetInterface):
if not field:
child.set_text('')
child.set_position(0)
- self.changed =True
+ self.changed = True
return False
super(Reference, self).display(record, field)
value = field.get_client(record)
@@ -306,8 +309,8 @@ class Reference(WidgetInterface):
if self.last_key[0] == key:
self.last_key[1] += 1
else:
- self.last_key = [ key, 1 ]
- if not self.key_catalog.has_key(key):
+ self.last_key = [key, 1]
+ if key not in self.key_catalog:
return
self.widget_combo.set_active_iter(
self.key_catalog[key][self.last_key[1] \
diff --git a/tryton/gui/window/view_form/view/form_gtk/selection.py b/tryton/gui/window/view_form/view/form_gtk/selection.py
index 95ede546e9..d606d01973 100644
--- a/tryton/gui/window/view_form/view/form_gtk/selection.py
+++ b/tryton/gui/window/view_form/view/form_gtk/selection.py
@@ -7,7 +7,6 @@ import math
from interface import WidgetInterface
import tryton.rpc as rpc
import tryton.common as common
-from tryton.pyson import PYSONDecoder
from tryton.exceptions import TrytonServerError
@@ -61,8 +60,8 @@ class Selection(WidgetInterface):
if domain == self._last_domain:
return
- args = ('model', self.attrs['relation'], 'search_read', domain, 0, None,
- None, ['rec_name'], rpc.CONTEXT)
+ args = ('model', self.attrs['relation'], 'search_read', domain, 0,
+ None, None, ['rec_name'], rpc.CONTEXT)
try:
result = rpc.execute(*args)
except TrytonServerError, exception:
@@ -101,14 +100,15 @@ class Selection(WidgetInterface):
if self._selection:
pop = sorted((len(x) for x in self._selection), reverse=True)
average = sum(pop) / len(pop)
- deviation = int(math.sqrt(sum((x - average)**2 for x in pop) /
+ deviation = int(math.sqrt(sum((x - average) ** 2 for x in pop) /
len(pop)))
width = max(next((x for x in pop if x < (deviation * 4)), 10), 10)
else:
width = 10
self.entry.child.set_width_chars(width)
if self._selection:
- self.entry.child.set_max_length(max(len(x) for x in self._selection))
+ self.entry.child.set_max_length(
+ max(len(x) for x in self._selection))
completion.set_text_column(0)
return lst
diff --git a/tryton/gui/window/view_form/view/form_gtk/textbox.py b/tryton/gui/window/view_form/view/form_gtk/textbox.py
index ce4a3ede0b..acbc85422c 100644
--- a/tryton/gui/window/view_form/view/form_gtk/textbox.py
+++ b/tryton/gui/window/view_form/view/form_gtk/textbox.py
@@ -2,7 +2,6 @@
#this repository contains the full copyright notices and license terms.
import gtk
from interface import WidgetInterface
-import tryton.rpc as rpc
from tryton.config import CONFIG
try:
@@ -28,7 +27,8 @@ class TextBox(WidgetInterface):
#TODO better tab solution
self.textview.set_accepts_tab(False)
self.textview.connect('focus-in-event', lambda x, y: self._focus_in())
- self.textview.connect('focus-out-event', lambda x, y: self._focus_out())
+ self.textview.connect('focus-out-event',
+ lambda x, y: self._focus_out())
self.scrolledwindow.add(self.textview)
self.scrolledwindow.show_all()
diff --git a/tryton/gui/window/view_form/view/form_gtk/url.py b/tryton/gui/window/view_form/view/form_gtk/url.py
index 13be7537a8..98cf521c1c 100644
--- a/tryton/gui/window/view_form/view/form_gtk/url.py
+++ b/tryton/gui/window/view_form/view/form_gtk/url.py
@@ -1,6 +1,5 @@
#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 char import Char
import webbrowser
@@ -104,4 +103,3 @@ class SIP(URL):
else:
self.tooltips.set_tip(self.button, '')
self.tooltips.disable()
-
diff --git a/tryton/gui/window/view_form/view/graph_gtk/bar.py b/tryton/gui/window/view_form/view/graph_gtk/bar.py
index 73b248a003..493b65c594 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/bar.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/bar.py
@@ -1,8 +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.
-#This code is inspired by the pycha project (http://www.lorenzogil.com/projects/pycha/)
+#This code is inspired by the pycha project
+#(http://www.lorenzogil.com/projects/pycha/)
from graph import Graph
-from tryton.common import hex2rgb, lighten, float_time_to_text
+from tryton.common import float_time_to_text
import locale
import math
import cairo
@@ -21,8 +22,8 @@ class Bar(Graph):
w = self.area.w * bar.w
h = self.area.h * bar.h
- if w < 1 or h <1:
- return # don't draw too small
+ if w < 1 or h < 1:
+ return # don't draw too small
cr.set_source_rgba(0, 0, 0, 0.15)
rectangle = self._getShadowRectangle(x, y, w, h)
@@ -52,7 +53,8 @@ class Bar(Graph):
def sourceRectangle(self, x, y, w, h, r, g, b):
linear = cairo.LinearGradient((x + w) / 2, y, (x + w) / 2, y + h)
- linear.add_color_stop_rgb(0, 3.5 * r / 5.0, 3.5 * g / 5.0, 3.5 * b / 5.0)
+ linear.add_color_stop_rgb(0, 3.5 * r / 5.0, 3.5 * g / 5.0,
+ 3.5 * b / 5.0)
linear.add_color_stop_rgb(1, r, g, b)
return linear
@@ -71,8 +73,9 @@ class Bar(Graph):
highlight = False
draw_bars = []
- yfields_float_time = dict([(x.get('key', x['name']), x.get('float_time'))
- for x in self.yfields if x.get('widget')])
+ yfields_float_time = dict(
+ (x.get('key', x['name']), x.get('float_time'))
+ for x in self.yfields if x.get('widget'))
for bar in self.bars:
if intersect(bar, event):
if not bar.highlight:
@@ -179,7 +182,7 @@ class VerticalBar(Bar):
return ylabels
def _getShadowRectangle(self, x, y, w, h):
- return (x-2, y-2, w+4, h+2)
+ return (x - 2, y - 2, w + 4, h + 2)
class HorizontalBar(Bar):
@@ -236,7 +239,7 @@ class HorizontalBar(Bar):
return [(x[0], x[1]) for x in ylabels]
def _getShadowRectangle(self, x, y, w, h):
- return (x, y-2, w+2, h+4)
+ return (x, y - 2, w + 2, h + 4)
def _getLegendPosition(self, width, height):
return self.area.x + self.area.w * 0.95 - width, \
diff --git a/tryton/gui/window/view_form/view/graph_gtk/graph.py b/tryton/gui/window/view_form/view/graph_gtk/graph.py
index 854c1007be..260adac1be 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/graph.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/graph.py
@@ -1,20 +1,19 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
-#This code is inspired by the pycha project (http://www.lorenzogil.com/projects/pycha/)
+#This code is inspired by the pycha project
+#(http://www.lorenzogil.com/projects/pycha/)
import gtk
from functools import reduce
from tryton.common import hex2rgb, generateColorscheme, DT_FORMAT, \
- DHM_FORMAT, COLOR_SCHEMES, datetime_strftime
+ COLOR_SCHEMES, datetime_strftime
from tryton.pyson import PYSONDecoder
import locale
import math
import datetime
-import time
from dateutil.relativedelta import relativedelta
import tryton.rpc as rpc
import cairo
from tryton.action import Action
-from tryton.translate import date_format
from tryton.gui.window import Window
@@ -65,10 +64,11 @@ class Popup(object):
def enter(self, widget, event):
self.win.hide()
+
class Graph(gtk.DrawingArea):
'Graph'
- __gsignals__ = { "expose-event": "override" }
+ __gsignals__ = {"expose-event": "override"}
def __init__(self, xfield, yfields, attrs, model):
super(Graph, self).__init__()
@@ -167,13 +167,12 @@ class Graph(gtk.DrawingArea):
def drawGraph(self, cr, width, height):
pass
-
def YLabels(self):
ylabels = []
if self.yrange == 0.0:
base = 1
else:
- base = 10**int(math.log(self.yrange, 10))
+ base = 10 ** int(math.log(self.yrange, 10))
for i in xrange(int(self.yrange / base) + 1):
val = int(self.minyval / base) * base + i * base
h = (val - self.minyval) * self.yscale
@@ -356,7 +355,6 @@ class Graph(gtk.DrawingArea):
self.ids[x].append(model.id)
self.datas.setdefault(x, {})
for yfield in self.yfields:
- name = yfield['name']
key = yfield.get('key', yfield['name'])
self.datas[x].setdefault(key, 0.0)
if yfield.get('domain'):
@@ -411,7 +409,8 @@ class Graph(gtk.DrawingArea):
yLabelWidth = 0
width = width - self.leftPadding - yLabelWidth - self.rightPadding
height = height - self.topPadding - self.bottomPadding - xLabelHeight
- self.area = Area(self.leftPadding + yLabelWidth, self.topPadding, width, height)
+ self.area = Area(self.leftPadding + yLabelWidth, self.topPadding,
+ width, height)
def updateXY(self):
self.maxxval = len(self.datas)
@@ -458,6 +457,7 @@ class Graph(gtk.DrawingArea):
def _getDatasKeys(self):
return [x.get('key', x['name']) for x in self.yfields]
+
class Area(object):
def __init__(self, x, y, w, h):
diff --git a/tryton/gui/window/view_form/view/graph_gtk/line.py b/tryton/gui/window/view_form/view/graph_gtk/line.py
index d4b1694059..e843f01ddb 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/line.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/line.py
@@ -1,6 +1,7 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
-#This code is inspired by the pycha project (http://www.lorenzogil.com/projects/pycha/)
+#This code is inspired by the pycha project
+#(http://www.lorenzogil.com/projects/pycha/)
from graph import Graph
from tryton.common import hex2rgb, float_time_to_text, safe_eval
import locale
@@ -33,8 +34,8 @@ class Line(Graph):
if self.xrange == 0:
x = 1.0
- if not bool(safe_eval(yfield2attrs[yfield].get('empty', '1'))) \
- and yval == 0:
+ if (not bool(safe_eval(yfield2attrs[yfield].get('empty', '1')))
+ and yval == 0):
continue
point = Point(x, y, xval, yval, xfield, yfield)
@@ -140,8 +141,9 @@ class Line(Graph):
highlight = False
draw_points = []
- yfields_float_time = dict([(x.get('key', x['name']), x.get('float_time'))
- for x in self.yfields if x.get('widget')])
+ yfields_float_time = dict(
+ (x.get('key', x['name']), x.get('float_time'))
+ for x in self.yfields if x.get('widget'))
for point in self.points:
if point == nearest[0] and nearest[1] < dia / 100:
if not point.highlight:
diff --git a/tryton/gui/window/view_form/view/graph_gtk/parser.py b/tryton/gui/window/view_form/view/graph_gtk/parser.py
index 1311fb5bce..4f175cfbe3 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/parser.py
@@ -3,12 +3,12 @@
from tryton.gui.window.view_form.view.interface import ParserInterface
import tryton.common as common
import gtk
-from graph import Graph
from bar import VerticalBar, HorizontalBar
from line import Line
from pie import Pie
from tryton.config import TRYTON_ICON, CONFIG
-import sys, os
+import sys
+import os
import gettext
_ = gettext.gettext
@@ -20,12 +20,12 @@ GRAPH_TYPE = {
'pie': Pie,
}
+
def save(widget, graph):
parent = common.get_toplevel_window()
dia = gtk.Dialog(_('Save As'), parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK))
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
dia.set_icon(TRYTON_ICON)
dia.set_has_separator(True)
dia.set_default_response(gtk.RESPONSE_OK)
@@ -98,6 +98,7 @@ def save(widget, graph):
dia.destroy()
return
+
def button_press(widget, event, graph):
if event.button == 3:
menu = gtk.Menu()
@@ -132,7 +133,8 @@ class ParserGraph(ParserInterface):
continue
xfield = common.node_attributes(child)
if not xfield.get('string'):
- xfield['string'] = fields[xfield['name']].attrs['string']
+ xfield['string'] = fields[xfield['name']
+ ].attrs['string']
break
elif node.localName == 'y':
for child in node.childNodes:
@@ -140,10 +142,12 @@ class ParserGraph(ParserInterface):
continue
yattrs = common.node_attributes(child)
if not yattrs.get('string') and yattrs['name'] != '#':
- yattrs['string'] = fields[yattrs['name']].attrs['string']
+ yattrs['string'] = fields[yattrs['name']
+ ].attrs['string']
yfields.append(yattrs)
- widget = GRAPH_TYPE[attrs.get('type', 'vbar')](xfield, yfields, attrs, model)
+ widget = GRAPH_TYPE[attrs.get('type', 'vbar')
+ ](xfield, yfields, attrs, model)
event = gtk.EventBox()
event.add(widget)
event.connect('button-press-event', button_press, widget)
diff --git a/tryton/gui/window/view_form/view/graph_gtk/pie.py b/tryton/gui/window/view_form/view/graph_gtk/pie.py
index feb0e46da7..0ba4287c2d 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/pie.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/pie.py
@@ -1,6 +1,7 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
-#This code is inspired by the pycha project (http://www.lorenzogil.com/projects/pycha/)
+#This code is inspired by the pycha project
+#(http://www.lorenzogil.com/projects/pycha/)
from graph import Graph, Area
import math
import cairo
@@ -97,7 +98,8 @@ class Pie(Graph):
cr.set_source_rgba(*color)
slice.draw(cr, self.centerx, self.centery, self.radius)
cr.fill()
- cr.set_source_rgb(*hex2rgb(self.attrs.get('background', '#f5f5f5')))
+ cr.set_source_rgb(*hex2rgb(
+ self.attrs.get('background', '#f5f5f5')))
slice.draw(cr, self.centerx, self.centery, self.radius)
cr.set_line_width(2)
cr.stroke()
@@ -120,7 +122,8 @@ class Pie(Graph):
if event.y == self.centery:
angle = math.pi / 2
else:
- angle = math.atan((event.x - self.centerx)/(self.centery - event.y))
+ angle = math.atan((event.x - self.centerx)
+ / (self.centery - event.y))
if event.x >= self.centerx:
if event.y <= self.centery:
pass
@@ -139,12 +142,14 @@ class Pie(Graph):
if self.yfields[0].get('widget') == 'float_time':
conv = None
if self.yfields[0].get('float_time'):
- conv = rpc.CONTEXT.get(self.yfields[0]['float_time'])
+ conv = rpc.CONTEXT.get(
+ self.yfields[0]['float_time'])
value = float_time_to_text(slice.fraction * self.sum,
conv)
sum = float_time_to_text(self.sum, conv)
else:
- value = locale.format('%.2f', slice.fraction * self.sum)
+ value = locale.format('%.2f',
+ slice.fraction * self.sum)
sum = locale.format('%.2f', self.sum)
label = '%s (%s%%)\n%s/%s' % (self.labels[slice.xname],
locale.format('%.2f', slice.fraction * 100),
@@ -181,8 +186,8 @@ class Slice(object):
cr.new_path()
cr.move_to(centerx, centery)
cr.arc(centerx, centery, radius,
- self.startAngle - (math.pi/2),
- self.endAngle - (math.pi/2))
+ self.startAngle - (math.pi / 2),
+ self.endAngle - (math.pi / 2))
cr.line_to(centerx, centery)
cr.close_path()
diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py
index 30b4dee97e..37da0e8777 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -21,7 +21,6 @@ from tryton.common.cellrendererbinary import CellRendererBinary
from tryton.pyson import PYSONEncoder
from tryton.gui.window import Window
from tryton.exceptions import TrytonServerError
-import os
_ = gettext.gettext
@@ -34,7 +33,8 @@ def path_convert_id2pos(model, id_path):
current_id = id_path.pop(0)
try:
record = group.get(current_id)
- group = record.children_group(model.children_field, check_load=True)
+ group = record.children_group(model.children_field,
+ check_load=True)
except (KeyError, AttributeError):
return None
return model.on_get_path(record)
@@ -49,7 +49,7 @@ class AdaptModelGroup(gtk.GenericTreeModel):
self.sort_asc = True
self.set_property('leak_references', False)
self.children_field = children_field
- self.__removed = None # XXX dirty hack to allow update of has_child
+ self.__removed = None # XXX dirty hack to allow update of has_child
def added(self, group, record):
if (group is self.group
@@ -80,7 +80,7 @@ class AdaptModelGroup(gtk.GenericTreeModel):
len(record.children_group(self.children_field)) <= 1):
path = self.on_get_path(record.parent)
iter_ = self.get_iter(path)
- self.__removed = record # XXX check for thread
+ self.__removed = record # XXX check for thread
self.row_has_child_toggled(path, iter_)
self.__removed = None
@@ -313,30 +313,34 @@ class ViewList(ParserView):
if screen.readonly:
dnd = False
if dnd:
- self.widget_tree.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,
- [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),],
- gtk.gdk.ACTION_MOVE)
+ self.widget_tree.drag_source_set(
+ gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,
+ [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)],
+ gtk.gdk.ACTION_MOVE)
self.widget_tree.drag_dest_set(gtk.DEST_DEFAULT_ALL,
- [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),],
- gtk.gdk.ACTION_MOVE)
+ [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)],
+ gtk.gdk.ACTION_MOVE)
self.widget_tree.connect('drag-begin', self.drag_begin)
self.widget_tree.connect('drag-motion', self.drag_motion)
self.widget_tree.connect('drag-drop', self.drag_drop)
self.widget_tree.connect("drag-data-get", self.drag_data_get)
- self.widget_tree.connect('drag-data-received', self.drag_data_received)
+ self.widget_tree.connect('drag-data-received',
+ self.drag_data_received)
self.widget_tree.connect('drag-data-delete', self.drag_data_delete)
self.widget_tree.connect('key_press_event', self.on_keypress)
if self.children_field:
self.widget_tree.connect('test-expand-row', self.test_expand_row)
- self.widget_tree.set_expander_column(self.widget_tree.get_column(0))
+ self.widget_tree.set_expander_column(
+ self.widget_tree.get_column(0))
def get_fields(self):
return [col.name for col in self.widget_tree.get_columns() if col.name]
def on_keypress(self, widget, event):
- if event.keyval == gtk.keysyms.c and event.state & gtk.gdk.CONTROL_MASK:
+ if (event.keyval == gtk.keysyms.c
+ and event.state & gtk.gdk.CONTROL_MASK):
self.on_copy()
return False
if event.keyval in (gtk.keysyms.Down, gtk.keysyms.Up):
@@ -347,7 +351,7 @@ class ViewList(ParserView):
if event.keyval == gtk.keysyms.Down:
test = True
for i in xrange(len(path)):
- iter_ = model.get_iter(path[0:i+1])
+ iter_ = model.get_iter(path[0:i + 1])
if model.iter_next(iter_):
test = False
if test:
@@ -390,7 +394,7 @@ class ViewList(ParserView):
try:
for field in fields:
record.__getitem__(field, True)
- except TrytonServerError, exception:
+ except TrytonServerError:
return True
iter_ = model.iter_next(iter_)
return False
@@ -419,7 +423,7 @@ class ViewList(ParserView):
clipboard.set_with_data(targets, self.copy_get_func,
self.copy_clear_func, selection)
- def copy_foreach(self, treemodel, path,iter, data):
+ def copy_foreach(self, treemodel, path, iter, data):
record = treemodel.get_value(iter, 0)
values = []
for col in self.widget_tree.get_columns():
@@ -465,6 +469,7 @@ class ViewList(ParserView):
def drag_data_get(self, treeview, context, selection, target_id,
etime):
treeview.emit_stop_by_name('drag-data-get')
+
def _func_sel_get(store, path, iter_, data):
value = store.get_value(iter_, 0)
data.append(json.dumps(value.get_path(store.group)))
@@ -496,6 +501,7 @@ class ViewList(ParserView):
record = store.group.get_by_path(data)
record_path = store.on_get_path(record)
drop_info = treeview.get_dest_row_at_pos(x, y)
+
def check_recursion(from_, to):
if not from_ or not to:
return True
@@ -508,7 +514,8 @@ class ViewList(ParserView):
if drop_info:
path, position = drop_info
check_path = path
- if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_AFTER):
+ if position in (gtk.TREE_VIEW_DROP_BEFORE,
+ gtk.TREE_VIEW_DROP_AFTER):
check_path = path[:-1]
if not check_recursion(record_path, check_path):
return
@@ -634,28 +641,32 @@ class ViewList(ParserView):
def __getitem__(self, name):
return None
- def destroy(self):
- if CONFIG['client.save_width_height']:
- fields = {}
- last_col = None
- for col in self.widget_tree.get_columns():
- if col.get_visible():
- last_col = col
- if not hasattr(col, 'name') or not hasattr(col, 'width'):
- continue
- if col.get_width() != col.width and col.get_visible():
- fields[col.name] = col.get_width()
- #Don't set width for last visible columns
- #as it depends of the screen size
- if last_col and last_col.name in fields:
- del fields[last_col.name]
+ def save_width_height(self):
+ if not CONFIG['client.save_width_height']:
+ return
+ fields = {}
+ last_col = None
+ for col in self.widget_tree.get_columns():
+ if col.get_visible():
+ last_col = col
+ if not hasattr(col, 'name') or not hasattr(col, 'width'):
+ continue
+ if col.get_width() != col.width and col.get_visible():
+ fields[col.name] = col.get_width()
+ #Don't set width for last visible columns
+ #as it depends of the screen size
+ if last_col and last_col.name in fields:
+ del fields[last_col.name]
- if fields and any(fields.itervalues()):
- try:
- rpc.execute('model', 'ir.ui.view_tree_width', 'set_width',
- self.screen.model_name, fields, rpc.CONTEXT)
- except TrytonServerError:
- pass
+ if fields and any(fields.itervalues()):
+ try:
+ rpc.execute('model', 'ir.ui.view_tree_width', 'set_width',
+ self.screen.model_name, fields, rpc.CONTEXT)
+ except TrytonServerError:
+ pass
+
+ def destroy(self):
+ self.save_width_height()
self.widget_tree.destroy()
self.screen = None
self.widget_tree = None
@@ -710,7 +721,6 @@ class ViewList(ParserView):
return True
self.update_children()
-
def set_value(self):
if hasattr(self.widget_tree, 'editable') \
and self.widget_tree.editable:
@@ -773,11 +783,12 @@ class ViewList(ParserView):
value += field_value
if loaded:
- label_str = locale.format('%.' + str(self.children[child][3]) + 'f',
- value_selected, True)
+ label_str = locale.format(
+ '%.' + str(self.children[child][3]) + 'f', value_selected,
+ True)
label_str += ' / '
- label_str += locale.format('%.' + str(self.children[child][3]) + 'f',
- value, True)
+ label_str += locale.format(
+ '%.' + str(self.children[child][3]) + 'f', value, True)
else:
label_str = '-'
self.children[child][2].set_text(label_str)
@@ -807,7 +818,8 @@ class ViewList(ParserView):
break
if path[:-1]:
self.widget_tree.expand_to_path(path[:-1])
- self.widget_tree.scroll_to_cell(path, focus_column, use_align=False)
+ self.widget_tree.scroll_to_cell(path, focus_column,
+ use_align=False)
self.widget_tree.set_cursor(path, focus_column, new)
def sel_ids_get(self):
diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py
index d96c1bc1d4..00ed147198 100644
--- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py
+++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py
@@ -38,7 +38,6 @@ class EditableTreeView(gtk.TreeView):
def on_open_remote(self, current_record, fieldname, create, value,
entry=None, callback=None):
- field = current_record[fieldname]
cell = self.cells[fieldname]
if value != cell.get_textual_value(current_record) or not value:
changed = True
@@ -151,6 +150,7 @@ class EditableTreeView(gtk.TreeView):
else:
txt = entry.get_active_text()
entry.handler_block(entry.editing_done_id)
+
def callback():
entry.handler_unblock(entry.editing_done_id)
self.set_cursor(path, column, True)
@@ -201,9 +201,9 @@ class EditableTreeView(gtk.TreeView):
break
entry.handler_block(entry.editing_done_id)
if self.editable == 'top':
- new_path = self._key_up(path, model, col)
+ self._key_up(path, model, col)
else:
- new_path = self._key_down(path, model, column)
+ self._key_down(path, model, column)
entry.handler_unblock(entry.editing_done_id)
elif event.keyval in (gtk.keysyms.F3, gtk.keysyms.F2):
if isinstance(entry, gtk.Entry):
@@ -211,6 +211,7 @@ class EditableTreeView(gtk.TreeView):
else:
value = entry.get_active_text()
entry.handler_block(entry.editing_done_id)
+
def callback():
cell = self.cells[column.name]
value = cell.get_textual_value(record)
@@ -221,13 +222,14 @@ class EditableTreeView(gtk.TreeView):
entry.handler_unblock(entry.editing_done_id)
self.set_cursor(path, column, True)
self.on_open_remote(record, column.name,
- create=(event.keyval==gtk.keysyms.F3), value=value,
+ create=(event.keyval == gtk.keysyms.F3), value=value,
callback=callback)
else:
field = record[column.name]
if isinstance(entry, gtk.Entry):
entry.set_max_length(int(field.attrs.get('size', 0)))
- # store in the record the entry widget to get the value in set_value
+ # store in the record the entry widget to get the value in
+ # set_value
field.editabletree_entry = entry
record.modified_fields.setdefault(column.name)
return False
diff --git a/tryton/gui/window/view_form/view/list_gtk/parser.py b/tryton/gui/window/view_form/view/list_gtk/parser.py
index 9085e39fec..084e8e653d 100644
--- a/tryton/gui/window/view_form/view/list_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/list_gtk/parser.py
@@ -12,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, file_selection, file_open
+ HM_FORMAT, file_selection, file_open
import tryton.common as common
from tryton.exceptions import TrytonError, TrytonServerError
from tryton.common.cellrendererbutton import CellRendererButton
@@ -25,7 +25,6 @@ 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
import gtk
import locale
import datetime
@@ -35,6 +34,7 @@ import operator
_ = gettext.gettext
+
def send_keys(renderer, editable, position, treeview):
editable.connect('key_press_event', treeview.on_keypressed)
editable.editing_done_id = editable.connect('editing_done',
@@ -42,6 +42,7 @@ def send_keys(renderer, editable, position, treeview):
if isinstance(editable, (gtk.ComboBoxEntry, gtk.ComboBox)):
editable.connect('changed', treeview.on_editing_done)
+
def sort_model(column, treeview, screen):
for col in treeview.get_columns():
if col != column:
@@ -71,6 +72,7 @@ def sort_model(column, treeview, screen):
for record in unsaved_records:
store.group.append(record)
+
class ParserTree(ParserInterface):
def __init__(self, parent=None, attrs=None, screen=None,
@@ -142,6 +144,7 @@ class ParserTree(ParserInterface):
render_pixbuf = gtk.CellRendererPixbuf()
col.pack_start(render_pixbuf, expand=False)
icon = node_attrs['icon']
+
def setter(column, cell, store, iter):
record = store.get_value(iter, 0)
value = record[icon].get_client(record) or ''
@@ -242,6 +245,7 @@ class ParserTree(ParserInterface):
col.set_widget(label)
col._type = 'button'
+ col.set_cell_data_func(renderer, cell.setter)
if 'width' in node_attrs:
width = int(node_attrs['width'])
else:
@@ -328,7 +332,8 @@ class Char(object):
bg_color = 'white'
if not field.get_state_attrs(record).get('valid', True):
bg_color = COLORS.get('invalid', 'white')
- elif bool(int(field.get_state_attrs(record).get('required', 0))):
+ elif bool(int(
+ field.get_state_attrs(record).get('required', 0))):
bg_color = COLORS.get('required', 'white')
cell.set_property('background', bg_color)
if bg_color == 'white':
@@ -366,6 +371,7 @@ class Char(object):
if callback:
callback()
+
class Int(Char):
def __init__(self, field_name, model_name, treeview, attrs=None):
@@ -383,6 +389,7 @@ class Int(Char):
return locale.format('%d',
record[self.field_name].get_client(record) or 0, True)
+
class Boolean(Int):
def __init__(self, field_name, model_name, treeview, attrs=None):
@@ -484,7 +491,7 @@ class Float(Char):
def get_textual_value(self, record):
field = record[self.field_name]
digit = record.expr_eval(field.attrs.get('digits', (16, 2)))[1]
- return locale.format('%.'+str(digit)+'f',
+ return locale.format('%.' + str(digit) + 'f',
record[self.field_name].get_client(record) or 0.0, True)
def value_from_text(self, record, text, callback=None):
@@ -513,7 +520,9 @@ class FloatTime(Char):
def value_from_text(self, record, text, callback=None):
field = record[self.field_name]
- field.set_client(record, common.text_to_float_time(text, self.conv))
+ digits = record.expr_eval(field.attrs.get('digits', (16, 2)))
+ field.set_client(record,
+ round(common.text_to_float_time(text, self.conv), digits[1]))
if callback:
callback()
@@ -582,7 +591,7 @@ class Binary(Char):
filename = file_selection(_('Save As...'), filename=filename,
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if filename:
- with open(filename,'wb') as fp:
+ with open(filename, 'wb') as fp:
fp.write(field.get_data(record))
def clear_binary(self, renderer, path):
@@ -681,6 +690,7 @@ class M2O(Char):
def search_remote(self, record, relation, ids=None, domain=None,
context=None, callback=None):
field = record.group.fields[self.field_name]
+
def search_callback(found):
value = None
if found:
@@ -733,6 +743,7 @@ class O2M(Char):
screen = Screen(relation, mode=['tree', 'form'],
exclude_field=field.attrs.get('relation_field'))
screen.group = group
+
def open_callback(result):
if callback:
callback()
@@ -781,6 +792,7 @@ class M2M(Char):
return
if not callback:
return
+
def winsearch_callback(result):
field.set_client(record, result or [])
if callback:
@@ -807,20 +819,21 @@ class M2M(Char):
field.set_client(record, False)
if callback:
callback()
- if ids and len(ids)==1:
+ if ids and len(ids) == 1:
field.set_client(record, ids)
if callback:
callback()
return
else:
ids = [x.id for x in field.get_client(record)]
+
def open_callback(result):
if result:
field.set_client(record, result)
if callback:
callback()
- WinSearch(relation, open_callback, sel_multi=True, ids=ids, context=context,
- domain=domain)
+ WinSearch(relation, open_callback, sel_multi=True, ids=ids,
+ context=context, domain=domain)
class Selection(Char):
@@ -1002,6 +1015,15 @@ class Button(object):
self.renderer.connect('clicked', self.button_clicked)
+ def setter(self, column, cell, store, iter):
+ record = store.get_value(iter, 0)
+ states = record.expr_eval(self.attrs.get('states', {}),
+ check_load=False)
+ invisible = states.get('invisible', False)
+ cell.set_property('visible', not invisible)
+ # TODO readonly
+ # TODO icon
+
def button_clicked(self, widget, path):
if not path:
return True
diff --git a/tryton/gui/window/view_form/view/screen_container.py b/tryton/gui/window/view_form/view/screen_container.py
index bdb8bd4da1..77a38b0e9d 100644
--- a/tryton/gui/window/view_form/view/screen_container.py
+++ b/tryton/gui/window/view_form/view/screen_container.py
@@ -6,6 +6,7 @@ import tryton.common as common
_ = gettext.gettext
+
class ScreenContainer(object):
def __init__(self):
@@ -139,7 +140,7 @@ class ScreenContainer(object):
model.append([r.strip()])
def clear(self, widget=None):
- self.search_entry.set_text('');
+ self.search_entry.set_text('')
def get_text(self):
return self.search_entry.get_text().strip().decode('utf-8')
diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py
index 94499aa958..06a1f70521 100644
--- a/tryton/gui/window/win_export.py
+++ b/tryton/gui/window/win_export.py
@@ -20,11 +20,9 @@ class WinExport(object):
def __init__(self, model, ids, context=None):
self.parent = common.get_toplevel_window()
- self.dialog = gtk.Dialog(
- title= _("Export to CSV"),
- parent=self.parent,
- flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.WIN_POS_CENTER_ON_PARENT)
+ self.dialog = gtk.Dialog(title=_("Export to CSV"), parent=self.parent,
+ flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
+ gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.set_icon(TRYTON_ICON)
vbox = gtk.VBox()
@@ -327,7 +325,7 @@ class WinExport(object):
try:
new_id = rpc.execute(*args)
except TrytonServerError, exception:
- new_ids = common.process_exception(exception, self.dialog, *args)
+ new_id = common.process_exception(exception, self.dialog, *args)
if not new_id:
return
self.predef_model.append((
@@ -419,7 +417,7 @@ class WinExport(object):
row = []
for val in data:
if type(val) == types.StringType:
- row.append(val.replace('\n',' ').replace('\t',' '))
+ row.append(val.replace('\n', ' ').replace('\t', ' '))
else:
row.append(val)
writer.writerow(row)
diff --git a/tryton/gui/window/win_form.py b/tryton/gui/window/win_form.py
index bac42f0489..78f2b57fff 100644
--- a/tryton/gui/window/win_form.py
+++ b/tryton/gui/window/win_form.py
@@ -1,6 +1,6 @@
#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 tryton.common import TRYTON_ICON
+from tryton.common import TRYTON_ICON, COLOR_SCHEMES
import tryton.common as common
from tryton.config import CONFIG
import gtk
@@ -8,6 +8,7 @@ import pango
import gettext
from tryton.exceptions import TrytonServerError
from tryton.gui.window.nomodal import NoModal
+import tryton.rpc as rpc
_ = gettext.gettext
@@ -56,7 +57,7 @@ class WinForm(NoModal):
if new and many:
self.but_ok.add_accelerator('clicked',
self.accel_group, gtk.keysyms.Return,
- gtk.gdk.CONTROL_MASK|gtk.gdk.SHIFT_MASK,
+ gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK,
gtk.ACCEL_VISIBLE)
self.but_new = self.win.add_button(gtk.STOCK_NEW,
@@ -130,7 +131,8 @@ class WinForm(NoModal):
tooltips.set_tip(self.but_del, _('Delete selected record'))
self.but_del.connect('clicked', self._sig_remove)
img_del = gtk.Image()
- img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_del.set_from_stock('tryton-delete',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_del.set_alignment(0.5, 0.5)
self.but_del.add(img_del)
self.but_del.set_relief(gtk.RELIEF_NONE)
@@ -142,7 +144,8 @@ class WinForm(NoModal):
tooltips.set_tip(but_pre, _('Previous'))
but_pre.connect('clicked', self._sig_previous)
img_pre = gtk.Image()
- img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_pre.set_from_stock('tryton-go-previous',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_pre.set_alignment(0.5, 0.5)
but_pre.add(img_pre)
but_pre.set_relief(gtk.RELIEF_NONE)
@@ -155,7 +158,8 @@ class WinForm(NoModal):
tooltips.set_tip(but_next, _('Next'))
but_next.connect('clicked', self._sig_next)
img_next = gtk.Image()
- img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_next.set_from_stock('tryton-go-next',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_next.set_alignment(0.5, 0.5)
but_next.add(img_next)
but_next.set_relief(gtk.RELIEF_NONE)
@@ -167,7 +171,8 @@ class WinForm(NoModal):
tooltips.set_tip(but_switch, _('Switch'))
but_switch.connect('clicked', self.switch_view)
img_switch = gtk.Image()
- img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ img_switch.set_from_stock('tryton-fullscreen',
+ gtk.ICON_SIZE_SMALL_TOOLBAR)
img_switch.set_alignment(0.5, 0.5)
but_switch.add(img_switch)
but_switch.set_relief(gtk.RELIEF_NONE)
@@ -251,6 +256,7 @@ class WinForm(NoModal):
from tryton.gui.window.win_search import WinSearch
domain = []
context = rpc.CONTEXT.copy()
+ model_name = self.screen.model_name
try:
if self.wid_text.get_text():
@@ -258,7 +264,7 @@ class WinForm(NoModal):
'%' + self.wid_text.get_text() + '%'), domain]
else:
dom = domain
- ids = rpc.execute('model', self.attrs['relation'], 'search', dom,
+ ids = rpc.execute('model', model_name, 'search', dom,
0, CONFIG['client.limit'], None, context)
except TrytonServerError, exception:
common.process_exception(exception)
@@ -274,9 +280,8 @@ class WinForm(NoModal):
self.wid_text.set_text('')
if len(ids) != 1:
- WinSearch(self.attrs['relation'], callback, sel_multi=True,
- ids=ids, context=context, domain=domain,
- views_preload=self.attrs.get('views', {}))
+ WinSearch(model_name, callback, sel_multi=True,
+ ids=ids, context=context, domain=domain)
else:
callback(ids)
diff --git a/tryton/gui/window/win_import.py b/tryton/gui/window/win_import.py
index e9c9b3797a..80e8eb22f1 100644
--- a/tryton/gui/window/win_import.py
+++ b/tryton/gui/window/win_import.py
@@ -45,7 +45,7 @@ class WinImport(object):
hbox_mapping.pack_start(vbox_buttons, False, True, 0)
button_add = gtk.Button(_("_Add"), stock=None, use_underline=True)
- button_add.set_alignment(0.0,0.0)
+ button_add.set_alignment(0.0, 0.0)
img_button = gtk.Image()
img_button.set_from_stock('tryton-list-add', gtk.ICON_SIZE_BUTTON)
button_add.set_image(img_button)
@@ -54,7 +54,7 @@ class WinImport(object):
button_remove = gtk.Button(_("_Remove"), stock=None,
use_underline=True)
- button_remove.set_alignment(0.0,0.0)
+ button_remove.set_alignment(0.0, 0.0)
img_button = gtk.Image()
img_button.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_BUTTON)
button_remove.set_image(img_button)
@@ -63,7 +63,7 @@ class WinImport(object):
button_remove_all = gtk.Button(_("Clear"), stock=None,
use_underline=True)
- button_remove_all.set_alignment(0.0,0.0)
+ button_remove_all.set_alignment(0.0, 0.0)
img_button = gtk.Image()
img_button.set_from_stock('tryton-clear', gtk.ICON_SIZE_BUTTON)
button_remove_all.set_image(img_button)
@@ -75,7 +75,7 @@ class WinImport(object):
button_autodetect = gtk.Button(_("Auto-Detect"), stock=None,
use_underline=True)
- button_autodetect.set_alignment(0.0,0.0)
+ button_autodetect.set_alignment(0.0, 0.0)
img_button = gtk.Image()
img_button.set_from_stock('tryton-find', gtk.ICON_SIZE_BUTTON)
button_autodetect.set_image(img_button)
@@ -132,15 +132,15 @@ class WinImport(object):
table.attach(self.import_csv_sep, 1, 2, 0, 1)
label_import_csv_del = gtk.Label(_("Text Delimiter:"))
- label_import_csv_del.set_alignment( 1, 0.5)
+ label_import_csv_del.set_alignment(1, 0.5)
table.attach(label_import_csv_del, 2, 3, 0, 1)
self.import_csv_del = gtk.Entry()
- self.import_csv_del.set_text( "\"")
- self.import_csv_del.set_width_chars( 1)
+ self.import_csv_del.set_text("\"")
+ self.import_csv_del.set_width_chars(1)
table.attach(self.import_csv_del, 3, 4, 0, 1)
label_import_csv_enc = gtk.Label(_("Encoding:"))
- label_import_csv_enc.set_alignment( 1, 0.5)
+ label_import_csv_enc.set_alignment(1, 0.5)
table.attach(label_import_csv_enc, 0, 1, 1, 2)
self.import_csv_enc = gtk.combo_box_new_text()
self.import_csv_enc.append_text("UTF-8")
@@ -148,7 +148,7 @@ class WinImport(object):
table.attach(self.import_csv_enc, 1, 2, 1, 2)
label_import_csv_skip = gtk.Label(_("Lines to Skip:"))
- label_import_csv_skip.set_alignment( 1, 0.5)
+ label_import_csv_skip.set_alignment(1, 0.5)
table.attach(label_import_csv_skip, 2, 3, 1, 2)
self.import_csv_skip_adj = gtk.Adjustment(0, 0, 100, 1, 10)
@@ -266,7 +266,6 @@ class WinImport(object):
if word not in self.fields_invert and word not in self.fields:
iter = self.model1.get_iter_first()
prefix = ''
- prefix_name = ''
for parent in word.split('/')[:-1]:
while iter:
if self.model1.get_value(iter, 0) == parent or \
@@ -300,7 +299,7 @@ class WinImport(object):
def _sig_sel_add(self, store, path, iter):
num = self.model2.append()
name = self.fields[store.get_value(iter, 1)][0]
- self.model2.set(num, 0, name, 1, store.get_value(iter,1))
+ self.model2.set(num, 0, name, 1, store.get_value(iter, 1))
def sig_unsel(self, widget=None):
store, paths = self.view2.get_selection().get_selected_rows()
diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py
index 4712a6c75b..87ef2c4ddf 100644
--- a/tryton/gui/window/win_search.py
+++ b/tryton/gui/window/win_search.py
@@ -3,7 +3,6 @@
import gtk
import gettext
import tryton.common as common
-import tryton.rpc as rpc
from tryton.gui.window.view_form.screen import Screen
from tryton.config import TRYTON_ICON
from tryton.gui.window.win_form import WinForm
@@ -34,7 +33,8 @@ class WinSearch(NoModal):
self.accel_group = gtk.AccelGroup()
self.win.add_accel_group(self.accel_group)
- self.but_cancel = self.win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+ self.but_cancel = self.win.add_button(gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL)
self.but_find = self.win.add_button(gtk.STOCK_FIND, gtk.RESPONSE_APPLY)
self.but_ok = self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
self.but_ok.add_accelerator('clicked', self.accel_group,
@@ -118,6 +118,7 @@ class WinSearch(NoModal):
elif response_id == gtk.RESPONSE_ACCEPT:
screen = Screen(self.model_name, domain=self.domain,
context=self.context, mode=['form'])
+
def callback(result):
if result and screen.save_current():
res = [screen.current_record.id]
diff --git a/tryton/gui/window/window.py b/tryton/gui/window/window.py
index 4070cccb56..6d2f16162e 100644
--- a/tryton/gui/window/window.py
+++ b/tryton/gui/window/window.py
@@ -1,7 +1,5 @@
#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 tryton.rpc as rpc
-from preference import *
class Window(object):
diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py
index 46b34325f6..99dc116ea5 100644
--- a/tryton/gui/window/wizard.py
+++ b/tryton/gui/window/wizard.py
@@ -9,7 +9,6 @@ import tryton.common as common
from tryton.gui.window.view_form.screen import Screen
from tryton.gui import Main
from tryton.exceptions import TrytonServerError
-from tryton.config import CONFIG
from tryton.gui.window.nomodal import NoModal
from tryton.common.button import Button
_ = gettext.gettext
@@ -74,7 +73,9 @@ class Wizard(object):
ctx['active_ids'] = self.ids
ctx['active_model'] = self.model
if self.screen:
- data = {self.screen_state: self.screen.get_on_change_value()}
+ data = {
+ self.screen_state: self.screen.get_on_change_value(),
+ }
else:
data = {}
rpcprogress = common.RPCProgress('execute', ('wizard',
@@ -230,7 +231,7 @@ class Wizard(object):
self.screen.set_cursor()
-class WizardForm(Wizard,SignalEvent):
+class WizardForm(Wizard, SignalEvent):
"Wizard"
def __init__(self, name=False):
diff --git a/tryton/ipc.py b/tryton/ipc.py
index ea7e70e45e..1c0d6fb87b 100644
--- a/tryton/ipc.py
+++ b/tryton/ipc.py
@@ -12,6 +12,7 @@ from tryton.config import get_config_dir
__all__ = ['Server', 'Client']
+
class IPCServer(object):
thread = None
@@ -112,7 +113,7 @@ class FIFOServer(IPCServer):
pass
def _read(self):
- fifo = os.fdopen(os.open(self.filename, os.O_RDONLY|os.O_NONBLOCK))
+ fifo = os.fdopen(os.open(self.filename, os.O_RDONLY | os.O_NONBLOCK))
data = ''
while self.running:
try:
diff --git a/tryton/jsonrpc.py b/tryton/jsonrpc.py
index a38f4a97c0..d853a925dc 100644
--- a/tryton/jsonrpc.py
+++ b/tryton/jsonrpc.py
@@ -29,13 +29,14 @@ class ResponseError(xmlrpclib.ResponseError):
class Fault(xmlrpclib.Fault):
def __init__(self, faultCode, faultString='', **extra):
- super(Fault, self).__init__(faultCode, str(faultString), **extra)
+ super(Fault, self).__init__(faultCode, faultString, **extra)
self.args = faultString
class ProtocolError(xmlrpclib.ProtocolError):
pass
+
def object_hook(dct):
if '__class__' in dct:
if dct['__class__'] == 'datetime':
@@ -109,7 +110,7 @@ class JSONUnmarshaller(object):
class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport):
accept_gzip_encoding = True
- encode_threshold = 1400 # common MTU
+ encode_threshold = 1400 # common MTU
def __init__(self, fingerprints=None, ca_certs=None):
xmlrpclib.Transport.__init__(self)
@@ -123,7 +124,8 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport):
return parser, target
def get_host_info(self, host):
- host, extra_headers, x509 = xmlrpclib.Transport.get_host_info(self, host)
+ host, extra_headers, x509 = xmlrpclib.Transport.get_host_info(
+ self, host)
if extra_headers is None:
extra_headers = []
extra_headers.append(('Connection', 'keep-alive'))
@@ -151,11 +153,11 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport):
return self._connection[1]
host, extra_headers, x509 = self.get_host_info(host)
- ca_certs = self.__ca_certs
+ ca_certs = self.__ca_certs
cert_reqs = ssl.CERT_REQUIRED if ca_certs else ssl.CERT_NONE
-
class HTTPSConnection(httplib.HTTPSConnection):
+
def connect(self):
sock = socket.create_connection((self.host, self.port),
self.timeout)
@@ -180,12 +182,13 @@ class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport):
peercert = sock.getpeercert(True)
except socket.error:
peercert = None
+
def format_hash(value):
return reduce(lambda x, y: x + y[1].upper() +
- ((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
- enumerate(value), '')
+ ((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
+ enumerate(value), '')
return format_hash(hashlib.sha1(peercert).hexdigest())
- except ssl.SSLError, e:
+ except ssl.SSLError:
http_connection()
fingerprint = ''
diff --git a/tryton/plugins/__init__.py b/tryton/plugins/__init__.py
index 119eca5e7b..492786bb6b 100644
--- a/tryton/plugins/__init__.py
+++ b/tryton/plugins/__init__.py
@@ -21,11 +21,13 @@ if os.path.isdir(PLUGINS_PATH):
continue
module = os.path.splitext(plugin)[0]
try:
- module = imp.load_module(module, *imp.find_module(module, [PLUGINS_PATH]))
+ module = imp.load_module(module, *imp.find_module(module,
+ [PLUGINS_PATH]))
MODULES.append(module)
except ImportError, exception:
continue
+
def execute(datas):
result = {}
diff --git a/tryton/plugins/translation/__init__.py b/tryton/plugins/translation/__init__.py
index b21b318577..d88cf6e0b3 100644
--- a/tryton/plugins/translation/__init__.py
+++ b/tryton/plugins/translation/__init__.py
@@ -5,12 +5,14 @@ import gettext
_ = gettext.gettext
+
def translate_view(datas):
model = datas['model']
Window.create(False, 'ir.translation', res_id=False,
domain=[('model', '=', model)],
mode=['tree', 'form'])
+
def get_plugins(model):
return [
(_('Translate view'), translate_view),
diff --git a/tryton/plugins/workflow/__init__.py b/tryton/plugins/workflow/__init__.py
index 502e5d4c16..db0660d763 100644
--- a/tryton/plugins/workflow/__init__.py
+++ b/tryton/plugins/workflow/__init__.py
@@ -5,18 +5,21 @@ import gettext
_ = gettext.gettext
+
def workflow_print(datas):
datas = datas.copy()
datas['nested'] = False
Action.exec_report('workflow.instance.graph', datas)
return True
+
def workflow_print_complex(datas):
datas = datas.copy()
datas['nested'] = True
Action.exec_report('workflow.instance.graph', datas)
return True
+
def get_plugins(model):
return [
(_('Print Workflow'), workflow_print),
diff --git a/tryton/pyson.py b/tryton/pyson.py
index 9c7dde7e93..1e66d7f275 100644
--- a/tryton/pyson.py
+++ b/tryton/pyson.py
@@ -1,6 +1,5 @@
#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 sys
try:
import simplejson as json
except ImportError:
@@ -22,7 +21,7 @@ class PYSON(object):
raise NotImplementedError
def __invert__(self):
- if self.types()!= set([bool]):
+ if self.types() != set([bool]):
return Not(Bool(self))
else:
return Not(self)
@@ -307,7 +306,8 @@ class If(PYSON):
def __init__(self, condition, then_statement, else_statement=None):
super(If, self).__init__()
if isinstance(condition, PYSON):
- assert condition.types() == set([bool]), 'condition must be boolean'
+ assert condition.types() == set([bool]), \
+ 'condition must be boolean'
else:
assert isinstance(condition, bool), 'condition must be boolean'
if isinstance(then_statement, PYSON):
diff --git a/tryton/rpc.py b/tryton/rpc.py
index 01635ba4cb..32ec540dad 100644
--- a/tryton/rpc.py
+++ b/tryton/rpc.py
@@ -30,7 +30,9 @@ if not os.path.isfile(_CA_CERTS):
_CA_CERTS = None
_FINGERPRINTS = Fingerprints()
-ServerProxy = partial(ServerProxy, fingerprints=_FINGERPRINTS, ca_certs=_CA_CERTS)
+ServerProxy = partial(ServerProxy, fingerprints=_FINGERPRINTS,
+ ca_certs=_CA_CERTS)
+
def db_list(host, port):
try:
@@ -46,6 +48,7 @@ def db_list(host, port):
logging.getLogger('rpc.result').debug(repr(None))
return None
+
def db_exec(host, port, method, *args):
connection = ServerProxy(host, port)
logging.getLogger('rpc.request').info('common.db.%s(None, None, %s)' %
@@ -54,6 +57,7 @@ def db_exec(host, port, method, *args):
logging.getLogger('rpc.result').debug(repr(result))
return result
+
def server_version(host, port):
try:
connection = ServerProxy(host, port)
@@ -65,9 +69,10 @@ def server_version(host, port):
except (Fault, socket.error):
raise
+
def login(username, password, host, port, database):
- global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE, _VIEW_CACHE
- global _TOOLBAR_CACHE
+ global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE
+ global _VIEW_CACHE, _TOOLBAR_CACHE
_VIEW_CACHE = {}
_TOOLBAR_CACHE = {}
try:
@@ -99,9 +104,10 @@ def login(username, password, host, port, database):
IPCServer(host, port, database).run()
return 1
+
def logout():
- global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE, _VIEW_CACHE
- global _TOOLBAR_CACHE
+ global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE
+ global _VIEW_CACHE, _TOOLBAR_CACHE
if IPCServer.instance:
IPCServer.instance.stop()
if CONNECTION is not None:
@@ -125,6 +131,7 @@ def logout():
_VIEW_CACHE = {}
_TOOLBAR_CACHE = {}
+
def context_reload():
global CONTEXT, TIMEZONE, _HOST, _PORT
try:
@@ -142,6 +149,7 @@ def context_reload():
except Fault:
pass
+
def _execute(blocking, *args):
global CONNECTION, _USER, _SESSION
if CONNECTION is None:
@@ -186,8 +194,10 @@ def _execute(blocking, *args):
logging.getLogger('rpc.result').debug(repr(result))
return result
+
def execute(*args):
return _execute(True, *args)
+
def execute_nonblocking(*args):
return _execute(False, *args)
diff --git a/tryton/translate.py b/tryton/translate.py
index ac7971f577..583e65c5b2 100644
--- a/tryton/translate.py
+++ b/tryton/translate.py
@@ -5,7 +5,7 @@ import os
import locale
import gettext
from version import PACKAGE
-from tryton.client import CURRENT_DIR, PREFIX
+from tryton.config import CURRENT_DIR, PREFIX
import logging
import gtk
import sys
@@ -197,12 +197,14 @@ def setlang(lang=None, locale_dict=None):
conv[field] = locale_dict[field]
locale.localeconv = lambda: conv
+
def set_language_direction(direction):
if direction == 'rtl':
gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL)
else:
gtk.widget_set_default_direction(gtk.TEXT_DIR_LTR)
+
def date_format():
'''
Return the locale date format
diff --git a/tryton/version.py b/tryton/version.py
index 06169802f1..ebed2fb2b1 100644
--- a/tryton/version.py
+++ b/tryton/version.py
@@ -4,4 +4,3 @@ PACKAGE = "tryton"
VERSION = "2.3.0"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
-