Convert many popup to be no-modal

review71002
This commit is contained in:
Cédric Krier committed 2011-07-31 17:39:33 +02:00
1 parent 441b2c1b48
commit 7744d976f4
78 files changed
+1258 -1435

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Convert many popup to be no-modal
* Add window manager for:
- replace current window
- prevent simmilar window
+24 -34
View File
@@ -3,7 +3,6 @@
import time
import datetime
import tryton.rpc as rpc
from tryton.wizard import Wizard
from tryton.common import message, error, selection, file_open, mailto
from tryton.gui.window import Window
from tryton.pyson import PYSONDecoder
@@ -20,7 +19,7 @@ _ = gettext.gettext
class Action(object):
@staticmethod
def exec_report(name, data, window, direct_print=False, email_print=False,
def exec_report(name, data, direct_print=False, email_print=False,
email=None, context=None):
if context is None:
context = {}
@@ -36,19 +35,19 @@ class Action(object):
try:
ids = rpc.execute(*args)
except TrytonServerError, exception:
ids = common.process_exception(exception, window, *args)
ids = common.process_exception(exception, *args)
if not ids:
return False
if ids == []:
message(_('Nothing to print!'), window)
message(_('Nothing to print!'))
return False
data['id'] = ids[0]
args = ('report', name, 'execute', ids, data, ctx)
rpcprogress = common.RPCProgress('execute', args, window)
rpcprogress = common.RPCProgress('execute', args)
try:
res = rpcprogress.run()
except TrytonServerError, exception:
common.process_exception(exception, window)
common.process_exception(exception)
return False
if not res:
return False
@@ -66,11 +65,11 @@ class Action(object):
subject=email.get('subject'), body=email.get('body'),
attachment=fp_name)
else:
file_open(fp_name, type, window, print_p=print_p)
file_open(fp_name, type, print_p=print_p)
return True
@staticmethod
def execute(act_id, data, window, action_type=None, context=None):
def execute(act_id, data, action_type=None, context=None):
if context is None:
context = {}
ctx = rpc.CONTEXT.copy()
@@ -81,7 +80,7 @@ class Action(object):
res = rpc.execute('model', 'ir.action', 'read', act_id,
['type'], ctx)
except TrytonServerError, exception:
common.process_exception(exception, window)
common.process_exception(exception)
return
if not res:
raise Exception, 'ActionNotFound'
@@ -90,12 +89,12 @@ class Action(object):
res = rpc.execute('model', action_type, 'search_read',
[('action', '=', act_id)], 0, 1, None, None, ctx)
except TrytonServerError, exception:
common.process_exception(exception, window)
common.process_exception(exception)
return
Action._exec_action(res, window, data)
Action._exec_action(res, data)
@staticmethod
def _exec_action(action, window, data=None, context=None):
def _exec_action(action, data=None, context=None):
if context is None:
context = {}
if data is None:
@@ -145,30 +144,22 @@ class Action(object):
res_model = action.get('res_model', data.get('res_model'))
res_id = action.get('res_id', data.get('res_id'))
Window.create(view_ids, res_model, res_id, domain, window,
Window.create(view_ids, res_model, res_id, domain,
action_ctx, view_mode, name=name,
limit=action.get('limit'),
auto_refresh=action.get('auto_refresh'),
search_value=search_value,
icon=(action.get('icon.rec_name') or ''))
elif action['type'] == 'ir.action.wizard':
if action.get('window', False):
Window.create_wizard(action['wiz_name'], data, window,
direct_print=action.get('direct_print', False),
email_print=action.get('email_print', False),
email=action.get('email'), name=action.get('name', False),
context=context, icon=(action.get('icon.rec_name') or ''))
else:
Wizard.execute(action['wiz_name'], data, window,
direct_print=action.get('direct_print', False),
email_print=action.get('email_print', False),
email=action.get('email'), context=context)
if action['wiz_name'] == 'ir.ui.view_sc.add':
from tryton.gui.main import Main
Main.get_main().shortcut_set()
Window.create_wizard(action['wiz_name'], data,
direct_print=action.get('direct_print', False),
email_print=action.get('email_print', False),
email=action.get('email'), name=action.get('name', False),
context=context, icon=(action.get('icon.rec_name') or ''),
window=action.get('window', False))
elif action['type'] == 'ir.action.report':
Action.exec_report(action['report_name'], data, window,
Action.exec_report(action['report_name'], data,
direct_print=action.get('direct_print', False),
email_print=action.get('email_print', False),
email=action.get('email'), context=context)
@@ -178,7 +169,7 @@ class Action(object):
webbrowser.open(action['url'], new=2)
@staticmethod
def exec_keyword(keyword, window, data=None, context=None, warning=True,
def exec_keyword(keyword, data=None, context=None, warning=True,
alwaysask=False):
actions = []
if 'id' in data:
@@ -188,19 +179,18 @@ class Action(object):
'get_keyword', keyword, (data['model'], model_id),
rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, window)
common.process_exception(exception)
return False
keyact = {}
for action in actions:
keyact[action['name'].replace('_', '')] = action
res = selection(_('Select your action'), keyact, window,
alwaysask=alwaysask)
res = selection(_('Select your action'), keyact, alwaysask=alwaysask)
if res:
(name, action) = res
Action._exec_action(action, window, data, context=context)
Action._exec_action(action, data, context=context)
return (name, action)
elif not len(keyact) and warning:
message(_('No action defined!'), window)
message(_('No action defined!'))
return False
+1 -1
View File
@@ -107,7 +107,7 @@ class TrytonClient(object):
traceback.format_exception(exctyp, value, tb))
for path in sys.path:
tb_s = tb_s.replace(path, '')
common.error(str(value), main.window, tb_s)
common.error(str(value), tb_s)
sys.excepthook = excepthook
+100 -71
View File
@@ -178,8 +178,9 @@ def refresh_langlist(lang_widget, host, port):
lang_widget.set_active(index)
return lang_list
def request_server(server_widget, parent):
def request_server(server_widget):
result = False
parent = get_toplevel_window()
dialog = gtk.Dialog(
title= _('Tryton Connection'),
parent=parent,
@@ -239,14 +240,42 @@ def request_server(server_widget, parent):
dialog.destroy()
return result
def get_toplevel_window():
windows = [x for x in gtk.window_list_toplevels()
if x.window and x.props.visible]
trans2windows = dict((x.get_transient_for(), x) for x in windows)
for window in set(windows) - set(trans2windows.iterkeys()):
return window
return trans2windows[None]
def selection(title, values, parent, alwaysask=False):
def get_sensible_widget(window):
from tryton.gui.main import Main
main = Main.get_main()
if main and window == main.window:
focus_widget = window.get_focus()
page = main.get_page()
if page and focus_widget and focus_widget.is_ancestor(page.widget):
return page.widget
return window
def center_window(window, parent, sensible):
parent_x, parent_y = parent.window.get_origin()
window_allocation = window.get_allocation()
sensible_allocation = sensible.get_allocation()
x = (parent_x + sensible_allocation.x +
int((sensible_allocation.width - window_allocation.width) / 2))
y = (parent_y + sensible_allocation.y +
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:
return None
elif len(values)==1 and (not alwaysask):
key = values.keys()[0]
return (key, values[key])
parent = get_toplevel_window()
dialog = gtk.Dialog(_('Selection'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
@@ -300,9 +329,10 @@ def selection(title, values, parent, alwaysask=False):
dialog.destroy()
return res
def file_selection(title, filename='', parent=None,
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)
@@ -371,7 +401,7 @@ def file_selection(title, filename='', parent=None,
win.destroy()
return filenames
def file_open(filename, type, parent, print_p=False):
def file_open(filename, type, print_p=False):
if os.name == 'nt':
operation = 'open'
if print_p:
@@ -379,7 +409,7 @@ def file_open(filename, type, parent, print_p=False):
try:
os.startfile(os.path.normpath(filename), operation)
except WindowsError:
save_name = file_selection(_('Save As...'), parent=parent,
save_name = file_selection(_('Save As...'),
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if save_name:
file_p = open(filename, 'rb')
@@ -414,7 +444,7 @@ def file_open(filename, type, parent, print_p=False):
#TODO add dialog box
pass
if not cmd:
save_name = file_selection(_('Save As...'), parent=parent,
save_name = file_selection(_('Save As...'),
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if save_name:
file_p = open(filename, 'rb')
@@ -508,8 +538,8 @@ class UniqueDialog(object):
if self.running:
return
parent = args[1]
dialog = self.build_dialog(*args)
parent = get_toplevel_window()
dialog = self.build_dialog(parent, *args)
dialog.set_icon(TRYTON_ICON)
self.running = True
dialog.show_all()
@@ -522,21 +552,21 @@ class UniqueDialog(object):
class MessageDialog(UniqueDialog):
def build_dialog(self, message, parent, msg_type):
def build_dialog(self, parent, message, msg_type):
dialog = gtk.MessageDialog(parent,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, msg_type,
gtk.BUTTONS_OK, message)
return dialog
def __call__(self, message, parent, msg_type=gtk.MESSAGE_INFO):
super(MessageDialog, self).__call__(message, parent, msg_type)
def __call__(self, message, msg_type=gtk.MESSAGE_INFO):
super(MessageDialog, self).__call__(message, msg_type)
message = MessageDialog()
class WarningDialog(UniqueDialog):
def build_dialog(self, message, parent, title, buttons=gtk.BUTTONS_OK):
def build_dialog(self, parent, message, title, buttons=gtk.BUTTONS_OK):
dialog = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_WARNING, buttons)
if hasattr(dialog, 'format_secondary_markup'):
@@ -558,8 +588,8 @@ class UserWarningDialog(WarningDialog):
def _set_always(self, toggle):
self.always = toggle.get_active()
def build_dialog(self, message, parent, title):
dialog = super(UserWarningDialog, self).build_dialog(message, parent,
def build_dialog(self, parent, message, title):
dialog = super(UserWarningDialog, self).build_dialog(parent, message,
title, gtk.BUTTONS_OK_CANCEL)
check = gtk.CheckButton(_('Always ignore this warning.'))
check.connect_after('toggled', self._set_always)
@@ -568,9 +598,8 @@ class UserWarningDialog(WarningDialog):
dialog.vbox.pack_end(alignment, True, False)
return dialog
def __call__(self, message, parent, title):
response = super(UserWarningDialog, self).__call__(message, parent,
title)
def __call__(self, message, title):
response = super(UserWarningDialog, self).__call__(message, title)
if response == gtk.RESPONSE_OK:
if self.always:
return 'always'
@@ -582,7 +611,7 @@ userwarning = UserWarningDialog()
class ConfirmationDialog(UniqueDialog):
def build_dialog(self, message, parent):
def build_dialog(self, parent, message):
dialog = gtk.Dialog(_('Confirmation'), parent, gtk.DIALOG_MODAL
| gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT
| gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
@@ -596,22 +625,21 @@ class ConfirmationDialog(UniqueDialog):
label = gtk.Label('%s' % (to_xml(message)))
hbox.pack_start(label, True, True)
dialog.vbox.pack_start(hbox)
dialog.set_transient_for(parent)
return dialog
class SurDialog(ConfirmationDialog):
def build_dialog(self, message, parent):
dialog = super(SurDialog, self).build_dialog(message, parent)
def build_dialog(self, parent, message):
dialog = super(SurDialog, self).build_dialog(parent, message)
dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL)
dialog.add_button("gtk-ok", gtk.RESPONSE_OK | gtk.CAN_DEFAULT
| gtk.HAS_DEFAULT)
dialog.set_default_response(gtk.RESPONSE_OK)
return dialog
def __call__(self, message, parent):
response = super(SurDialog, self).__call__(message, parent)
def __call__(self, message):
response = super(SurDialog, self).__call__(message)
return response == gtk.RESPONSE_OK
sur = SurDialog()
@@ -625,8 +653,8 @@ class Sur3BDialog(ConfirmationDialog):
gtk.RESPONSE_CANCEL: 'cancel'
}
def build_dialog(self, message, parent):
dialog = super(Sur3BDialog, self).build_dialog(message, parent)
def build_dialog(self, parent, message):
dialog = super(Sur3BDialog, self).build_dialog(parent, message)
dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL)
dialog.add_button("gtk-no", gtk.RESPONSE_NO)
dialog.add_button("gtk-yes", gtk.RESPONSE_YES | gtk.CAN_DEFAULT
@@ -634,8 +662,8 @@ class Sur3BDialog(ConfirmationDialog):
dialog.set_default_response(gtk.RESPONSE_YES)
return dialog
def __call__(self, message, parent):
response = super(Sur3BDialog, self).__call__(message, parent)
def __call__(self, message):
response = super(Sur3BDialog, self).__call__(message)
return self.response_mapping.get(response, 'cancel')
sur_3b = Sur3BDialog()
@@ -643,7 +671,7 @@ sur_3b = Sur3BDialog()
class AskDialog(UniqueDialog):
def build_dialog(self, question, parent, visibility):
def build_dialog(self, parent, question, visibility):
win = gtk.Dialog('Tryton', parent,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
@@ -666,12 +694,12 @@ class AskDialog(UniqueDialog):
win.vbox.pack_start(hbox)
return win
def __call__(self, question, parent, visibility=True):
def __call__(self, question, visibility=True):
if self.running:
return
dialog = self.build_dialog(question, parent,
visibility=visibility)
parent = get_toplevel_window()
dialog = self.build_dialog(parent, question, visibility=visibility)
dialog.set_icon(TRYTON_ICON)
self.running = True
dialog.show_all()
@@ -689,7 +717,7 @@ ask = AskDialog()
class ConcurrencyDialog(UniqueDialog):
def build_dialog(self, resource, parent, obj_id, context):
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)
@@ -725,9 +753,8 @@ class ConcurrencyDialog(UniqueDialog):
dialog.add_action_widget(write_button, gtk.RESPONSE_OK)
return dialog
def __call__(self, resource, obj_id, context, parent):
# parent must be the second parameter
res = super(ConcurrencyDialog, self).__call__(resource, parent, obj_id,
def __call__(self, resource, obj_id, context):
res = super(ConcurrencyDialog, self).__call__(resource, obj_id,
context)
if res == gtk.RESPONSE_OK:
@@ -735,7 +762,7 @@ class ConcurrencyDialog(UniqueDialog):
if res == gtk.RESPONSE_APPLY:
from tryton.gui.window import Window
Window.create(False, resource, res_id=obj_id,
domain=[('id', '=', obj_id)], window=parent,
domain=[('id', '=', obj_id)],
context=context, mode=['form', 'tree'])
return False
@@ -744,7 +771,7 @@ concurrency = ConcurrencyDialog()
class ErrorDialog(UniqueDialog):
def build_dialog(self, title, parent, details):
def build_dialog(self, parent, title, details):
dialog = gtk.Dialog(_('Error'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
dialog.set_has_separator(True)
@@ -813,20 +840,21 @@ class ErrorDialog(UniqueDialog):
dialog.set_size_request(600, 400)
return dialog
def __call__(self, title, parent, details):
def __call__(self, title, details):
if title == details:
title = ''
log = logging.getLogger('common.message')
log.error(details)
response = super(ErrorDialog, self).__call__(title, parent, details)
response = super(ErrorDialog, self).__call__(title, details)
if response == gtk.RESPONSE_OK:
send_bugtracker(details, parent)
send_bugtracker(details)
error = ErrorDialog()
def send_bugtracker(msg, parent):
def send_bugtracker(msg):
from tryton import rpc
parent = get_toplevel_window()
win = gtk.Dialog(_('Bug Tracker'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
@@ -909,7 +937,7 @@ def send_bugtracker(msg, parent):
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, parent)
'%s' % issue_id)
else:
# create a new issue for this error-message
# first create message
@@ -919,49 +947,47 @@ def send_bugtracker(msg, parent):
issue_id = server.create('issue', *['messages=' + str(msg_id),
'nosy=' + user, 'title=' + title, 'priority=bug'])
message(_('Created new bug with ID ') + \
'issue%s' % issue_id, parent)
'issue%s' % issue_id)
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!'),
parent)
message(_('Connection error!\nBad username or password!'))
return send_bugtracker(msg, parent)
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, parent,
msg_type=gtk.MESSAGE_ERROR)
message(_('Exception:') + '\n' + tb_s, msg_type=gtk.MESSAGE_ERROR)
def to_xml(string):
return string.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
PLOCK = Lock()
def process_exception(exception, parent, *args):
def process_exception(exception, *args):
global _USERNAME, _DATABASE, _SOCK
if isinstance(exception, TrytonError):
if exception.ex_type == 'BadFingerprint':
warning(_('The server fingerprint has changed since last'
' connection!\nThe application will stop connecting to this'
' server until its fingerprint is fixed.'),
parent, _('Security risk!'))
warning(
_('The server fingerprint has changed since last connection!\n'
'The application will stop connecting to this server '
'until its fingerprint is fixed.'), _('Security risk!'))
from tryton.gui.main import Main
Main.sig_quit()
sys.exit()
elif exception.ex_type == 'NotLogged':
if not rpc._SOCK:
message(_('Connection error!\n' \
'Unable to connect to the server!'), parent)
'Unable to connect to the server!'))
return False
elif isinstance(exception, TrytonServerError):
if exception.ex_type == 'UserWarning':
msg = ''
if len(exception.args) > 4:
msg = exception.args[3]
res = userwarning(str(msg), parent, str(exception.args[2]))
res = userwarning(str(msg), str(exception.args[2]))
if res in ('always', 'ok'):
args2 = ('model', 'res.user.warning', 'create', {
'user': rpc._USER,
@@ -971,33 +997,32 @@ def process_exception(exception, parent, *args):
try:
rpc.execute(*args2)
except TrytonServerError, exception:
process_exception(exception, parent, *args2)
process_exception(exception, *args2)
if args:
try:
return rpc.execute(*args)
except TrytonServerError, exception:
return process_exception(exception, parent, *args)
return process_exception(exception, *args)
return True
return False
elif exception.ex_type == 'UserError':
msg = ''
if len(exception.args) > 3:
msg = exception.args[2]
warning(str(msg), parent, str(exception.args[1]))
warning(str(msg), str(exception.args[1]))
return False
elif exception.ex_type == 'ConcurrencyException':
if len(args) >= 6:
if concurrency(args[1], args[3][0], args[5], parent):
if concurrency(args[1], args[3][0], args[5]):
if '_timestamp' in args[5]:
del args[5]['_timestamp']
try:
return rpc.execute(*args)
except TrytonServerError, exception:
return process_exception(exception, parent, *args)
return process_exception(exception, *args)
return False
else:
message(_('Concurrency Exception'), parent,
msg_type=gtk.MESSAGE_ERROR)
message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR)
return False
elif exception.ex_type == 'NotLogged':
if not PLOCK.acquire(False):
@@ -1006,7 +1031,7 @@ def process_exception(exception, parent, *args):
port = rpc._SOCK.port
try:
while True:
password = ask(_('Password:'), parent, visibility=False)
password = ask(_('Password:'), visibility=False)
if password is None:
continue
res = rpc.login(rpc._USERNAME, password, hostname, port,
@@ -1015,7 +1040,7 @@ def process_exception(exception, parent, *args):
Main.get_main().refresh_ssl()
if res == -1:
message(_('Connection error!\n' \
'Unable to connect to the server!'), parent)
'Unable to connect to the server!'))
return False
if res < 0:
continue
@@ -1023,7 +1048,7 @@ def process_exception(exception, parent, *args):
try:
return rpc.execute(*args)
except TrytonServerError, exception:
return process_exception(exception, parent, *args)
return process_exception(exception, *args)
return True
finally:
PLOCK.release()
@@ -1031,7 +1056,7 @@ def process_exception(exception, parent, *args):
msg = ''
if len(exception.args) > 2:
msg = exception.args[1]
warning(msg, parent, _('Network Error!'))
warning(msg, _('Network Error!'))
return False
if isinstance(exception, TrytonServerError):
@@ -1039,7 +1064,7 @@ def process_exception(exception, parent, *args):
else:
error_title = str(exception)
error_detail = traceback.format_exc()
error(error_title, parent, error_detail)
error(error_title, error_detail)
return False
def node_attributes(node):
@@ -1151,10 +1176,10 @@ class DBProgress(object):
class RPCProgress(object):
def __init__(self, method, args, parent):
def __init__(self, method, args):
self.method = method
self.args = args
self.parent = parent
self.parent = get_toplevel_window()
self.res = None
self.error = False
self.exception = None
@@ -1176,6 +1201,8 @@ class RPCProgress(object):
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
self.parent.window.set_cursor(watch)
parent_sensitive = self.parent.props.sensitive
self.parent.props.sensitive = False
i = 0
win = None
progressbar = None
@@ -1219,10 +1246,12 @@ class RPCProgress(object):
win.window.set_cursor(watch)
with gtk.gdk.lock:
progressbar.pulse()
with gtk.gdk.lock:
while gtk.events_pending():
gtk.main_iteration()
if win:
with gtk.gdk.lock:
while gtk.events_pending():
gtk.main_iteration()
time.sleep(0.1)
self.parent.props.sensitive = parent_sensitive
self.parent.window.set_cursor(None)
if win:
win.destroy()
+93 -102
View File
@@ -17,7 +17,6 @@ from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, DATA_DIR, \
import tryton.common as common
from tryton.action import Action
from tryton.exceptions import TrytonServerError, TrytonError
from tryton.wizard import Wizard
from tryton.gui.window import Window
from tryton.gui.window.preference import Preference
from tryton.gui.window import Limit
@@ -163,6 +162,7 @@ class Main(object):
self.previous_pages = {}
self.current_page = 0
self.last_page = 0
self.dialogs = []
if CONFIG['client.modepda']:
self.radiomenuitem_pda.set_active(True)
@@ -251,6 +251,10 @@ class Main(object):
self.menuitem_shortcut.set_sensitive(False)
menubar.add(menuitem_shortcut)
menuitem_shortcut.set_accel_path('<tryton>/Shortcuts')
def shortcut_activate(widget):
if not menuitem_shortcut.get_submenu():
self.shortcut_set()
menuitem_shortcut.connect('select', shortcut_activate)
menuitem_help = gtk.MenuItem(_('_Help'))
menubar.add(menuitem_help)
@@ -679,13 +683,14 @@ class Main(object):
def get_main():
return _MAIN[0]
def shortcut_set(self, shortcuts=None):
def shortcut_set(self):
def _action_shortcut(widget, action):
Action.exec_keyword('tree_open', self.window, {
Action.exec_keyword('tree_open', {
'model': 'ir.ui.menu',
'id': action,
'ids': [action],
})
self.shortcut_unset()
def _add_shortcut(widget):
ids = self.menu_screen.sel_ids_get()
@@ -695,7 +700,7 @@ class Main(object):
values = rpc.execute('model', self.menu_screen.model_name,
'read', ids, ['rec_name'], rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return
try:
for value in values:
@@ -706,21 +711,21 @@ class Main(object):
'resource': self.menu_screen.model_name,
}, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
self.shortcut_set()
common.process_exception(exception)
self.shortcut_unset()
def _manage_shortcut(widget):
Window.create(False, 'ir.ui.view_sc', False,
domain=[('user_id', '=', rpc._USER)],
window=self.window, mode=['tree', 'form'])
mode=['tree', 'form'])
self.shortcut_unset()
if shortcuts is None:
user = rpc._USER
try:
shortcuts = rpc.execute('model', 'ir.ui.view_sc', 'get_sc',
user, 'ir.ui.menu', rpc.CONTEXT)
except TrytonServerError:
shortcuts = []
user = rpc._USER
try:
shortcuts = rpc.execute('model', 'ir.ui.view_sc', 'get_sc',
user, 'ir.ui.menu', rpc.CONTEXT)
except TrytonServerError:
shortcuts = []
menu = gtk.Menu()
for shortcut in shortcuts:
menuitem = gtk.MenuItem(shortcut['name'])
@@ -735,13 +740,9 @@ class Main(object):
menu.add(manage_shortcut)
menu.show_all()
self.menuitem_shortcut.set_submenu(menu)
self.menuitem_shortcut.set_sensitive(True)
def shortcut_unset(self):
menu = gtk.Menu()
menu.show_all()
self.menuitem_shortcut.set_submenu(menu)
self.menuitem_shortcut.set_sensitive(False)
self.menuitem_shortcut.remove_submenu()
def sig_accel_change(self, value):
CONFIG['client.can_change_accelerators'] = value
@@ -789,13 +790,13 @@ class Main(object):
CONFIG['client.form_tab'] = option
def sig_limit(self, widget):
Limit(self.window).run()
Limit().run()
def sig_file_actions(self, widget):
FileActions(self.window).run()
FileActions().run()
def sig_email(self, widget):
Email(self.window).run()
Email().run()
def sig_win_next(self, widget):
page = self.notebook.get_current_page()
@@ -810,7 +811,7 @@ class Main(object):
def sig_user_preferences(self, widget):
if not self.close_pages():
return False
win = Preference(rpc._USER, self.window)
win = Preference(rpc._USER)
if win.run():
rpc.context_reload()
prefs = rpc.execute('model', 'res.user',
@@ -823,13 +824,12 @@ class Main(object):
translate.setlang(prefs['language'], prefs.get('locale'))
if CONFIG['client.lang'] != prefs['language']:
self.set_menubar()
self.shortcut_set()
self.shortcut_unset()
self.set_statusbar()
self.request_set()
self.sig_win_menu()
CONFIG['client.lang'] = prefs['language']
CONFIG.save()
self.window.present()
self.sig_win_menu()
return True
@@ -842,7 +842,7 @@ class Main(object):
ctx.update(rpc.CONTEXT)
ctx['active_test'] = False
return Window.create(None, 'res.request', False, [ ],
mode=['form', 'tree'], window=self.window, context=ctx)
mode=['form', 'tree'], context=ctx)
def sig_request_open(self, widget):
ctx = {}
@@ -851,13 +851,13 @@ class Main(object):
try:
ids1, ids2 = self.request_set(True)
except TrytonServerError, exception:
if common.process_exception(exception, self.window):
if common.process_exception(exception):
ids1, ids2 = self.request_set(True)
else:
raise
ids = ids1 + ids2
return Window.create(False, 'res.request', ids, [ ],
mode=['tree', 'form'], window=self.window, context=ctx)
mode=['tree', 'form'], context=ctx)
def request_set(self, exception=False):
try:
@@ -887,19 +887,17 @@ class Main(object):
return
if not res:
try:
dblogin = DBLogin(self.window)
res = dblogin.run(self.window)
res = DBLogin().run()
except TrytonError, exception:
if exception.ex_type == 'QueryCanceled':
return False
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return
self.window.present()
try:
log_response = rpc.login(*res)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return
rpc.context_reload()
self.refresh_ssl()
@@ -921,20 +919,20 @@ class Main(object):
translate.setlang(prefs['language'], prefs.get('locale'))
if CONFIG['client.lang'] != prefs['language']:
self.set_menubar()
self.shortcut_set()
self.shortcut_unset()
self.set_statusbar()
self.request_set()
CONFIG['client.lang'] = prefs['language']
CONFIG.save()
elif log_response == -1:
common.message(_('Connection error!\n' \
'Unable to connect to the server!'), self.window)
'Unable to connect to the server!'))
elif log_response == -2:
common.message(_('Connection error!\n' \
'Bad username or password!'), self.window)
'Bad username or password!'))
return self.sig_login()
if not self.menuitem_shortcut.get_property('sensitive'):
self.shortcut_set()
self.shortcut_unset()
self.menuitem_shortcut.set_sensitive(True)
self.menuitem_user.set_sensitive(True)
#self.menuitem_form.set_sensitive(True)
self.menuitem_plugins.set_sensitive(True)
@@ -947,8 +945,7 @@ class Main(object):
if self.notebook.get_n_pages():
if not common.sur(
_('The following action requires to close all tabs.\n'
'Do you want to continue?'),
parent=self.window):
'Do you want to continue?')):
return False
res = True
while res:
@@ -975,6 +972,7 @@ class Main(object):
self.sb_servername.set_text('')
self.sb_requests.set_text('')
self.shortcut_unset()
self.menuitem_shortcut.set_sensitive(False)
self.menuitem_user.set_sensitive(False)
#self.menuitem_form.set_sensitive(False)
self.menuitem_plugins.set_sensitive(False)
@@ -996,13 +994,13 @@ class Main(object):
self.tooltips.set_tip(self.secure_img, '')
def sig_tips(self, *args):
Tips(self.window)
Tips()
def sig_about(self, widget):
About(self.window)
About()
def sig_shortcuts(self, widget):
Shortcuts(self.window).run()
Shortcuts().run()
def menu_toggle(self, nohide=False):
has_focus = True
@@ -1041,7 +1039,7 @@ class Main(object):
try:
prefs = rpc.execute(*args)
except TrytonServerError, exception:
prefs = common.process_exception(exception, self.window, *args)
prefs = common.process_exception(exception, *args)
if not prefs:
return False
self.sb_username.set_text(prefs.get('status_bar', ''))
@@ -1052,14 +1050,14 @@ class Main(object):
return False
common.warning(_('You can not log into the system!\n' \
'Verify if you have a menu defined on your user.'),
'Access Denied!', self.window)
'Access Denied!')
rpc.logout()
self.refresh_ssl()
return False
act_id = prefs[menu_type]
if except_id and act_id == except_id:
return act_id
Action.execute(act_id, {}, self.window)
Action.execute(act_id, {})
return act_id
def sig_home_new(self, widget=None, quiet=True, except_id=False,
@@ -1076,7 +1074,7 @@ class Main(object):
'ids': self.pages[page].ids_get(),
'id': self.pages[page].id_get(),
}
tryton.plugins.execute(datas, self.window)
tryton.plugins.execute(datas)
@classmethod
def sig_quit(cls, widget=None):
@@ -1244,24 +1242,30 @@ class Main(object):
def _sig_page_changt(self, notebook, page, page_num):
self.last_page = self.current_page
last_form = self.get_page(self.current_page)
if last_form:
for dialog in last_form.dialogs:
dialog.hide()
self.current_page = self.notebook.get_current_page()
current_form = self.get_page()
current_form = self.get_page(self.current_page)
for dialog in current_form.dialogs:
dialog.show()
def sig_db_new(self, widget):
if not self.sig_logout(widget):
return False
dia = DBCreate(CONFIG['login.server'], int(CONFIG['login.port']),
sig_login=self.sig_login)
res = dia.run(self.window)
res = dia.run()
if res:
CONFIG.save()
return res
def sig_db_drop(self, widget):
def sig_db_drop(self, widget=None):
if not self.sig_logout(widget):
return False
dialog = DBBackupDrop(self.window, function='drop')
url, dbname, passwd = dialog.run(self.window)
url, dbname, passwd = DBBackupDrop(function='drop').run()
if not dbname:
rpc.logout()
Main.get_main().refresh_ssl()
@@ -1269,44 +1273,42 @@ class Main(object):
host, port = url.rsplit(':', 1)
sure = common.sur_3b(_("You are going to delete a Tryton " \
"database.\nAre you really sure to proceed?"), self.window)
"database.\nAre you really sure to proceed?"))
if sure == "ko" or sure == "cancel":
return
rpcprogress = common.RPCProgress('db_exec', (host, int(port), 'drop',
dbname, passwd), self.window)
dbname, passwd))
try:
rpcprogress.run()
except TrytonServerError, exception:
self.refresh_ssl()
if exception.args[0] == "AccessDenied":
common.warning(_("Wrong Tryton Server Password" \
"\nPlease try again."), self.window,
"\nPlease try again."),
_('Access denied!'))
self.sig_db_drop(self.window)
self.sig_db_drop()
else:
common.warning(_('Database drop failed with ' \
'error message:\n') + str(exception.args[0]), \
self.window, _('Database drop failed!'))
common.warning(_('Database drop failed with error message:\n')
+ str(exception.args[0]), _('Database drop failed!'))
return
self.refresh_ssl()
common.message(_("Database dropped successfully!"), \
parent=self.window)
common.message(_("Database dropped successfully!"))
def sig_db_restore(self, widget):
if not self.sig_logout(widget):
return False
filename = common.file_selection(_('Open Backup File to Restore...'), \
parent=self.window, preview=False)
filename = common.file_selection(_('Open Backup File to Restore...'),
preview=False)
if not filename:
return
dialog = DBRestore(self.window, filename=filename)
url, dbname, passwd, update = dialog.run(self.window)
dialog = DBRestore(filename=filename)
url, dbname, passwd, update = dialog.run()
if dbname:
with open(filename, 'rb') as file_p:
data_b64 = base64.encodestring(file_p.read())
host, port = url.rsplit(':' , 1)
rpcprogress = common.RPCProgress('db_exec', (host, int(port),
'restore', dbname, passwd, data_b64, update), self.window)
'restore', dbname, passwd, data_b64, update))
try:
res = rpcprogress.run()
except TrytonServerError, exception:
@@ -1316,31 +1318,29 @@ class Main(object):
common.warning(_("It is not possible to restore a " \
"password protected database.\n" \
"Backup and restore needed to be proceed " \
"manual."), self.window, \
"manual."),
_('Database is password protected!'))
elif exception.args[0] == "AccessDenied":
common.warning(_("Wrong Tryton Server Password.\n" \
"Please try again."), self.window, \
"Please try again."),
_('Access denied!'))
self.sig_db_restore(self.window)
self.sig_db_restore()
else:
common.warning(_('Database restore failed with ' \
'error message:\n') + str(exception.args[0]), \
self.window, _('Database restore failed!'))
_('Database restore failed!'))
return
self.refresh_ssl()
if res:
common.message(_("Database restored successfully!"), \
parent=self.window)
common.message(_("Database restored successfully!"))
else:
common.message(_('Database restore failed!'), \
parent=self.window)
common.message(_('Database restore failed!'))
def sig_db_dump(self, widget):
if not self.sig_logout(widget):
return False
dialog = DBBackupDrop(self.window, function='backup')
url, dbname, passwd = dialog.run(self.window)
dialog = DBBackupDrop(function='backup')
url, dbname, passwd = dialog.run()
if not (dbname and url and passwd):
rpc.logout()
@@ -1349,7 +1349,7 @@ class Main(object):
host, port = url.rsplit(':', 1)
rpcprogress = common.RPCProgress('db_exec', (host, int(port), 'dump',
dbname, passwd), self.window)
dbname, passwd))
try:
dump_b64 = rpcprogress.run()
except TrytonServerError, exception:
@@ -1357,16 +1357,16 @@ class Main(object):
common.warning(_("It is not possible to dump a password " \
"protected Database.\nBackup and restore " \
"needed to be proceed manual."),
self.window, _('Database is password protected!'))
_('Database is password protected!'))
elif exception.args[0] == "AccessDenied":
common.warning(_("Wrong Tryton Server Password.\n" \
"Please try again."), self.window,
"Please try again."),
_('Access denied!'))
self.sig_db_dump(self.window)
self.sig_db_dump()
else:
common.warning(_('Database dump failed with ' \
'error message:\n') + str(exception.args[0]), \
self.window, _('Database dump failed!'))
'error message:\n') + str(exception.args[0]),
_('Database dump failed!'))
rpc.logout()
Main.get_main().refresh_ssl()
return
@@ -1374,16 +1374,14 @@ class Main(object):
self.refresh_ssl()
dump = base64.decodestring(dump_b64)
filename = common.file_selection(_('Save As...'), \
action=gtk.FILE_CHOOSER_ACTION_SAVE, parent=self.window, \
preview=False,
filename=dbname + '-' + time.strftime('%Y%m%d%H%M') + '.dump')
filename = common.file_selection(_('Save As...'),
action=gtk.FILE_CHOOSER_ACTION_SAVE, preview=False,
filename=dbname + '-' + time.strftime('%Y%m%d%H%M') + '.dump')
if filename:
with open(filename, 'wb') as file_:
file_.write(dump)
common.message(_("Database backuped successfully!"), \
parent=self.window)
common.message(_("Database backuped successfully!"))
else:
rpc.logout()
Main.get_main().refresh_ssl()
@@ -1435,9 +1433,8 @@ class Main(object):
mode = ['form', 'tree']
try:
Window.create(view_ids, model, res_id=res_id, domain=domain,
window=self.window, context=context, mode=mode,
name=name, limit=limit, auto_refresh=auto_refresh,
search_value=search_value)
context=context, mode=mode, name=name, limit=limit,
auto_refresh=auto_refresh, search_value=search_value)
except Exception:
# Prevent crashing the client
return
@@ -1456,14 +1453,9 @@ class Main(object):
except ValueError:
return
try:
if window:
Window.create_wizard(wizard, data, self.window,
direct_print=direct_print, email_print=email_print,
email=email, name=name, context=context)
else:
Wizard.execute(wizard, data, self.window,
direct_print=direct_print, email_print=email_print,
email=email, context=context)
Window.create_wizard(wizard, data, direct_print=direct_print,
email_print=email_print, email=email, name=name,
context=context, window=window)
except Exception:
# Prevent crashing the client
return
@@ -1481,9 +1473,8 @@ class Main(object):
except ValueError:
return
try:
Action.exec_report(report, data, self.window,
direct_print=direct_print, email_print=email_print,
email=email, context=context)
Action.exec_report(report, data, direct_print=direct_print,
email_print=email_print, email=email, context=context)
except Exception:
# Prevent crashing the client
return
+4 -2
View File
@@ -4,9 +4,10 @@
import gtk
import gettext
import os
import webbrowser
from tryton.config import TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
from tryton.version import VERSION, WEBSITE
import webbrowser
from tryton.common import get_toplevel_window
COPYRIGHT = '''\
Copyright (C) 2010-2011 Nicolas Évrard.
@@ -710,11 +711,12 @@ _ = gettext.gettext
class About(object):
def __init__(self, parent):
def __init__(self):
gtk.about_dialog_set_email_hook(lambda widget, link:
webbrowser.open(link, new=2))
gtk.about_dialog_set_url_hook(lambda widget, link:
webbrowser.open(link, new=2))
parent = get_toplevel_window()
self.win = gtk.AboutDialog()
self.win.set_transient_for(parent)
self.win.set_name('Tryton')
+6 -8
View File
@@ -8,19 +8,17 @@ from tryton.gui.window.win_form import WinForm
class Attachment(object):
"Attachment window"
def __init__(self, model_name, record_id, parent):
def __init__(self, model_name, record_id):
self.resource = '%s,%s' % (model_name, record_id)
self.parent = parent
def run(self):
screen = Screen('ir.attachment', self.parent, domain=[
screen = Screen('ir.attachment', domain=[
('resource', '=', self.resource),
], mode=['tree', 'form'], context={
'resource': self.resource,
}, exclude_field='resource')
screen.search_filter()
win = WinForm(screen, self.parent, view_type='tree')
if win.run():
screen.group.save()
self.parent.present()
win.destroy()
def callback(result):
if result:
screen.group.save()
WinForm(screen, callback, view_type='tree')
+4 -3
View File
@@ -40,7 +40,7 @@ class Board(SignalEvent, TabContent):
'<tryton>/Form/Close'),
]
def __init__(self, model, window, view_id, context=None, name=False,
def __init__(self, model, view_id, context=None, name=False,
auto_refresh=False):
super(Board, self).__init__()
@@ -48,14 +48,15 @@ class Board(SignalEvent, TabContent):
view = rpc.execute('model', 'ir.ui.view', 'read',
view_id, ['arch'], context)
except TrytonServerError, exception:
common.process_exception(exception, window)
common.process_exception(exception)
raise
self.board = ViewBoard(view['arch'], window, context=context)
self.board = ViewBoard(view['arch'], context=context)
self.model = model
self.view_id = view_id
self.context = context
self.auto_refresh = auto_refresh
self.dialogs = []
if not name:
self.name = self.board.name
else:
+12 -13
View File
@@ -54,13 +54,13 @@ class DBCreate(object):
"Click on 'Change' to change the address."))
return state
def server_change(self, widget, parent):
def server_change(self, widget):
"""
This method checks the server connection via host and port. If the
connection is successfull, it query the language list and pass true
state to the GUI. Otherwise it pass false state to the GUI.
"""
res = common.request_server(self.entry_server_connection, parent)
res = common.request_server(self.entry_server_connection)
if not res:
return False
host, port = res
@@ -287,7 +287,8 @@ class DBCreate(object):
self.dialog.vbox.pack_start(dialog_vbox)
self.sig_login = sig_login
def run(self, parent):
def run(self):
parent = common.get_toplevel_window()
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_transient_for(parent)
self.dialog.show_all()
@@ -296,7 +297,7 @@ class DBCreate(object):
change_button = self.button_server_change
admin_passwd = self.entry_adminpasswd
admin_passwd2 = self.entry_adminpasswd2
change_button.connect_after('clicked', self.server_change, self.dialog)
change_button.connect_after('clicked', self.server_change)
if self.host and self.port:
url = '%s:%d' % (self.host, self.port)
@@ -327,20 +328,19 @@ class DBCreate(object):
common.warning(_('The database name is restricted to ' \
'alpha-nummerical characters and "_" (underscore). ' \
'Avoid all accents, space ' \
'and any other special characters.'), self.dialog, \
'and any other special characters.'),
_('Wrong characters in database name!'))
continue
elif admin_passwd.get_text() != admin_passwd2.get_text():
common.warning(
_("The new admin password " \
"doesn't match the confirmation field.\n"),
self.dialog,
_("Passwords doesn't match!"))
continue
elif not admin_passwd.get_text():
common.warning(_("Admin password and confirmation are " \
"required to create a new database."), \
self.dialog, _('Missing admin password!'))
_('Missing admin password!'))
continue
elif url_m.group(1) \
and int(url_m.group(2)) \
@@ -352,12 +352,12 @@ class DBCreate(object):
exist = rpc.db_exec(url_m.group(1),
int(url_m.group(2)), 'db_exist', dbname)
except TrytonServerError, exception:
common.process_exception(exception, self.dialog)
common.process_exception(exception)
continue
if exist:
common.warning(_("A database with the same name " \
"already exists.\n" \
"Try another database name."), self.dialog,
"Try another database name."),
_("This database name already exist!"))
self.entry_dbname.set_text("")
self.entry_dbname.grab_focus()
@@ -368,14 +368,13 @@ class DBCreate(object):
try:
rpcprogress = common.RPCProgress('db_exec',
(host, int(port), 'create', dbname, passwd,
langreal, admin_passwd.get_text()),
self.dialog)
langreal, admin_passwd.get_text()))
rpcprogress.run()
except TrytonServerError, exception:
if str(exception.args[0]) == "AccessDenied":
common.warning(_("Sorry, wrong password for " \
"the Tryton server. Please try again."),
self.dialog, _("Access denied!"))
_("Access denied!"))
self.entry_serverpasswd.set_text("")
self.entry_serverpasswd.grab_focus()
continue
@@ -387,7 +386,7 @@ class DBCreate(object):
"Please check the error message for " \
"possible informations.\n" \
"Error message:\n") + str(exception.args[0]),
self.dialog, _("Error creating database!"))
_("Error creating database!"))
parent.present()
self.dialog.destroy()
rpc.logout()
+11 -14
View File
@@ -41,9 +41,8 @@ class DBBackupDrop(object):
return dbs
@staticmethod
def refreshlist_ask(widget, server_widget, db_widget, label, db_progress,
parent=None):
res = common.request_server(server_widget, parent)
def refreshlist_ask(widget, server_widget, db_widget, label, db_progress):
res = common.request_server(server_widget)
if not res:
return None
host, port = res
@@ -71,7 +70,7 @@ class DBBackupDrop(object):
else:
self.button_ok.set_sensitive(False)
def __init__(self, parent, function=None):
def __init__(self, function=None):
# This widget is used for creating and droping a database!
if function =="backup":
dialog_title = _("Backup a database")
@@ -88,11 +87,10 @@ class DBBackupDrop(object):
else:
return None
self.dialog = gtk.Dialog( \
title = dialog_title, \
parent = parent, \
flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT \
| gtk.WIN_POS_CENTER_ON_PARENT,)
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(title=dialog_title, parent=self.parent,
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)
self.dialog.connect("key-press-event", self.event_show_button_ok)
@@ -195,9 +193,8 @@ class DBBackupDrop(object):
self.entry_serverpasswd.grab_focus()
self.dialog.vbox.pack_start(self.dialog_vbox)
def run(self, parent):
def run(self):
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_transient_for(parent)
self.dialog.show_all()
pass_widget = self.entry_serverpasswd
@@ -215,8 +212,8 @@ class DBBackupDrop(object):
CONFIG['login.server'], CONFIG['login.port'])
change_button = self.button_server_change
change_button.connect_after('clicked', DBBackupDrop.refreshlist_ask, \
server_widget, db_widget, label, db_progress, self.dialog)
change_button.connect_after('clicked', DBBackupDrop.refreshlist_ask,
server_widget, db_widget, label, db_progress)
while True:
database = False
@@ -232,7 +229,7 @@ class DBBackupDrop(object):
self.dialog.destroy()
rpc.logout()
break
parent.present()
self.parent.present()
self.dialog.destroy()
return (url, database, passwd)
+6 -7
View File
@@ -356,9 +356,10 @@ class DBListEditor(object):
class DBLogin(object):
def __init__(self, parent):
def __init__(self):
# GTK Stuffs
self.dialog = gtk.Dialog(title=_('Login'), parent=parent,
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(title=_('Login'), parent=self.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)
@@ -566,7 +567,7 @@ class DBLogin(object):
else:
return 8070
def run(self, parent):
def run(self):
profile_name = CONFIG['login.profile']
can_use_profile = self.profiles.has_section(profile_name)
if can_use_profile:
@@ -637,14 +638,12 @@ class DBLogin(object):
result = (self.entry_login.get_text(),
self.entry_password.get_text(), host, port, database)
self.parent.present()
self.dialog.destroy()
if res != gtk.RESPONSE_OK:
parent.present()
self.dialog.destroy()
rpc.logout()
from tryton.gui.main import Main
Main.get_main().refresh_ssl()
raise TrytonError('QueryCanceled')
parent.present()
self.dialog.destroy()
return result
+10 -12
View File
@@ -55,15 +55,14 @@ class DBRestore(object):
gobject.idle_add(_move_cursor)
entry.stop_emission("insert-text")
def __init__(self, parent=None, filename=None):
def __init__(self, filename=None):
"""
Database restore widget
"""
self.dialog = gtk.Dialog( \
title = _("Restore Database"), \
parent=parent, \
flags = gtk.DIALOG_MODAL \
| gtk.WIN_POS_CENTER_ON_PARENT)
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(title=_("Restore Database"),
parent=self.parent, flags=gtk.DIALOG_MODAL
| gtk.WIN_POS_CENTER_ON_PARENT)
vbox = gtk.VBox()
self.dialog.vbox.pack_start(vbox)
self.tooltips = common.Tooltips()
@@ -165,11 +164,10 @@ class DBRestore(object):
self.entry_server_password.grab_focus()
def run(self, parent):
def run(self):
"""
Database Restore widget run part
"""
self.dialog.set_transient_for(parent)
self.dialog.show_all()
self.entry_server_url.set_text('%(login.server)s:%(login.port)s' %
@@ -180,9 +178,9 @@ class DBRestore(object):
url = False
update = False
#TODO: This needs to be unified with the other widgets
self.button_server_change.connect_after('clicked', \
lambda a, b: common.request_server(b, self.dialog), \
self.entry_server_url)
self.button_server_change.connect_after('clicked',
lambda a, b: common.request_server(b),
self.entry_server_url)
res = self.dialog.run()
if res == gtk.RESPONSE_OK:
database = self.entry_db_name.get_text()
@@ -194,7 +192,7 @@ class DBRestore(object):
self.dialog.destroy()
rpc.logout()
break
parent.present()
self.parent.present()
self.dialog.destroy()
return url, database, passwd, update
+4 -4
View File
@@ -4,22 +4,22 @@
import gtk
import gettext
from tryton.config import TRYTON_ICON, CONFIG
from tryton.common import get_toplevel_window
_ = gettext.gettext
class Email(object):
def __init__(self, parent):
self.win = gtk.Dialog(_('Email'), parent,
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))
self.parent = parent
self.win.set_default_response(gtk.RESPONSE_OK)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
self.win.set_transient_for(parent)
self.win.vbox.set_spacing(3)
self.win.vbox.pack_start(gtk.Label(
_('Email Program Settings')), expand=False, fill=True)
+4 -5
View File
@@ -4,7 +4,7 @@
import gtk
import gettext
from tryton.config import TRYTON_ICON, CONFIG
from tryton.common import safe_eval
from tryton.common import safe_eval, get_toplevel_window
_ = gettext.gettext
@@ -12,16 +12,15 @@ _ = gettext.gettext
class FileActions(object):
"File actions window"
def __init__(self, parent):
self.win = gtk.Dialog(_('File Actions'), parent,
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.parent = parent
self.win.set_default_response(gtk.RESPONSE_OK)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
self.win.set_transient_for(parent)
self.win.vbox.pack_start(gtk.Label(
_('Edit Files Actions')), expand=False, fill=True)
self.win.vbox.pack_start(gtk.HSeparator())
+29 -33
View File
@@ -93,7 +93,7 @@ class Form(SignalEvent, TabContent):
'<tryton>/Form/Import Data'),
]
def __init__(self, model, window, res_id=False, domain=None, mode=None,
def __init__(self, model, res_id=False, domain=None, mode=None,
view_ids=None, context=None, name=False, limit=None,
auto_refresh=False, search_value=None):
super(Form, self).__init__()
@@ -108,18 +108,17 @@ class Form(SignalEvent, TabContent):
context = {}
self.model = model
self.window = window
self.res_id = res_id
self.domain = domain
self.mode = mode
self.context = context
self.auto_refresh = auto_refresh
self.view_ids = view_ids
self.dialogs = []
self.screen = Screen(self.model, self.window, mode=mode,
context=self.context, view_ids=view_ids, domain=domain,
limit=limit, readonly=bool(auto_refresh),
search_value=search_value)
self.screen = Screen(self.model, mode=mode, context=self.context,
view_ids=view_ids, domain=domain, limit=limit,
readonly=bool(auto_refresh), search_value=search_value)
self.screen.widget.show()
if not name:
@@ -159,8 +158,7 @@ class Form(SignalEvent, TabContent):
try:
toolbars = rpc.execute(*args)
except TrytonServerError, exception:
toolbars = common.process_exception(exception, self.window,
*args)
toolbars = common.process_exception(exception, *args)
toolbars = toolbars if toolbars else {}
self._toolbar_cache[self.model] = toolbars
return self._toolbar_cache[self.model]
@@ -174,7 +172,6 @@ class Form(SignalEvent, TabContent):
if not isinstance(value, Form):
return False
return (self.model == value.model
and self.window == value.window
and self.res_id == value.res_id
and self.domain == value.domain
and self.mode == value.mode
@@ -188,7 +185,8 @@ class Form(SignalEvent, TabContent):
def sig_goto(self, widget=None):
if not self.modified_save():
return
win = gtk.Dialog(_('Go to ID'), self.window,
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))
@@ -224,7 +222,7 @@ class Form(SignalEvent, TabContent):
if response == gtk.RESPONSE_OK:
self.screen.display(locale.atoi(entry.get_text()), set_cursor=True)
win.destroy()
self.window.present()
parent.present()
def destroy(self):
self.screen.signal_unconnect(self)
@@ -246,8 +244,7 @@ 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:
win = Attachment(self.model, obj_id, self.window)
win.run()
Attachment(self.model, obj_id).run()
else:
self.message_info(_('No record selected!'))
self.update_attachment_count(reload=True)
@@ -295,7 +292,7 @@ class Form(SignalEvent, TabContent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
return
message_str = ''
@@ -309,7 +306,7 @@ class Form(SignalEvent, TabContent):
value = common.datetime_strftime(date, display_format)
message_str += val + ' ' + value +'\n'
message_str += _('Model:') + ' ' + self.model
message(message_str, self.window)
message(message_str)
return True
def sig_remove(self, widget=None):
@@ -317,7 +314,7 @@ class Form(SignalEvent, TabContent):
msg = _('Are you sure to remove this record?')
else:
msg = _('Are you sure to remove those records?')
if sur(msg, self.window):
if sur(msg):
if not self.screen.remove(delete=True, force_remove=True):
self.message_info(_('Records not removed!'))
else:
@@ -329,7 +326,7 @@ class Form(SignalEvent, TabContent):
fields = {}
for name, field in self.screen.group.fields.iteritems():
fields[name] = field.attrs
win = WinImport(self.model, self.window)
win = WinImport(self.model)
win.run()
def sig_save_as(self, widget=None):
@@ -338,7 +335,7 @@ class Form(SignalEvent, TabContent):
fields = {}
for name, field in self.screen.group.fields.iteritems():
fields[name] = field.attrs
win = WinExport(self.model, self.ids_get(), self.window,
win = WinExport(self.model, self.ids_get(),
context=self.context)
win.run()
@@ -360,7 +357,7 @@ class Form(SignalEvent, TabContent):
try:
new_ids = rpc.execute(*args)
except TrytonServerError, exception:
new_ids = common.process_exception(exception, self.window, *args)
new_ids = common.process_exception(exception, *args)
if new_ids:
self.screen.load(new_ids)
self.message_info(_('Working now on the duplicated record(s)!'),
@@ -391,7 +388,7 @@ class Form(SignalEvent, TabContent):
return False
if test_modified and self.screen.modified():
res = sur_3b(_('This record has been modified\n' \
'do you want to save it ?'), self.window)
'do you want to save it ?'))
if res == 'ok':
self.sig_save(None)
elif res == 'ko':
@@ -429,6 +426,8 @@ class Form(SignalEvent, TabContent):
self.buttons['relate'].props.active = True
def action_popup(self, widget):
button, = widget.get_children()
button.grab_focus()
menu = widget._menu
if not widget.props.active:
menu.popdown()
@@ -449,12 +448,12 @@ class Form(SignalEvent, TabContent):
def sig_search(self, widget=None):
if not self.modified_save():
return
win = WinSearch(self.model, domain=self.domain,
context=self.context, parent=self.window)
res = win.run()
if res:
self.screen.clear()
self.screen.load(res)
def callback(result):
if result:
self.screen.clear()
self.screen.load(result)
WinSearch(self.model, callback, domain=self.domain,
context=self.context)
def message_info(self, message, color='red'):
if message:
@@ -495,8 +494,7 @@ class Form(SignalEvent, TabContent):
if self.screen.modified():
value = sur_3b(
_('This record has been modified\n' \
'do you want to save it ?'),
self.window)
'do you want to save it ?'))
if value == 'ok':
return self.sig_save(None)
elif value == 'ko':
@@ -508,6 +506,8 @@ class Form(SignalEvent, TabContent):
return True
def sig_close(self, widget=None):
for dialog in self.dialogs[:]:
dialog.destroy()
return self.modified_save(reload=False)
def _action(self, action, atype):
@@ -544,11 +544,7 @@ class Form(SignalEvent, TabContent):
'id': record_id,
'ids': record_ids,
}
value = Action._exec_action(action, self.window, data, {})
if atype in ('print', 'action'):
if self.screen:
self.screen.reload(written=True)
return value
Action._exec_action(action, data, {})
def activate_save(self):
self.buttons['save'].props.sensitive = self.screen.modified()
+4 -4
View File
@@ -4,6 +4,7 @@ import sys
import gtk
import gettext
from tryton.config import TRYTON_ICON, CONFIG
from tryton.common import get_toplevel_window
_ = gettext.gettext
@@ -11,16 +12,15 @@ _ = gettext.gettext
class Limit(object):
'Set Search Limit'
def __init__(self, parent):
self.win = gtk.Dialog(_('Limit'), parent,
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))
self.parent = parent
self.win.set_default_response(gtk.RESPONSE_OK)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
self.win.set_transient_for(parent)
self.win.vbox.set_spacing(3)
self.win.vbox.pack_start(gtk.Label(
_('Search Limit Settings')), expand=False, fill=True)
+27
View File
@@ -0,0 +1,27 @@
#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.gui.main import Main
import tryton.common as common
class NoModal(object):
def __init__(self):
self.parent = common.get_toplevel_window()
self.sensible_widget = common.get_sensible_widget(self.parent)
self.page = None
self.parent_focus = self.parent.get_focus()
def register(self):
main = Main.get_main()
self.page = main.get_page()
if not self.page:
self.page = main
self.page.dialogs.append(self)
self.sensible_widget.props.sensitive = False
def destroy(self):
self.page.dialogs.remove(self)
self.sensible_widget.props.sensitive = True
self.parent.present()
self.parent_focus.grab_focus()
+10 -10
View File
@@ -16,13 +16,13 @@ _ = gettext.gettext
class Preference(object):
"Preference window"
def __init__(self, user, parent):
self.win = gtk.Dialog(_('Preferences'), parent,
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)
self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.win.set_has_separator(False)
self.win.set_icon(TRYTON_ICON)
self.parent = parent
self.accel_group = gtk.AccelGroup()
self.win.add_accel_group(self.accel_group)
@@ -40,7 +40,7 @@ class Preference(object):
try:
view = rpc.execute(*args)
except TrytonServerError, exception:
view = common.process_exception(exception, parent, *args)
view = common.process_exception(exception, *args)
if not view:
self.win.destroy()
self.win = None
@@ -49,7 +49,7 @@ class Preference(object):
title = gtk.Label(_('Edit User Preferences'))
title.show()
self.win.vbox.pack_start(title, expand=False, fill=True)
self.screen = Screen('res.user', self.win, mode=[])
self.screen = Screen('res.user', mode=[])
self.screen.new(default=False)
self.screen.add_view(view)
@@ -57,7 +57,7 @@ class Preference(object):
try:
preferences = rpc.execute(*args)
except TrytonServerError, exception:
preferences = common.process_exception(exception, parent, *args)
preferences = common.process_exception(exception, *args)
if not preferences:
self.win.destroy()
raise
@@ -66,13 +66,13 @@ class Preference(object):
self.screen.screen_container.set(self.screen.current_view.widget)
self.screen.display(set_cursor=True)
width, height = self.screen.screen_container.size_get()
parent_width, parent_height = parent.get_size()
self.screen.widget.set_size_request(min(parent_width - 20, width + 20),
min(parent_height - 60, height + 25))
self.screen.widget.show()
self.win.vbox.pack_start(self.screen.widget)
self.win.set_title(_('Preference'))
width, height = self.parent.get_size()
self.win.set_default_size(int(width * 0.9), int(height * 0.9))
self.win.show()
def run(self):
+7 -6
View File
@@ -4,6 +4,7 @@
import gtk
import gettext
from tryton.config import TRYTON_ICON
from tryton.common import get_toplevel_window
_ = gettext.gettext
@@ -11,12 +12,12 @@ _ = gettext.gettext
class Shortcuts(object):
'Shortcuts window'
def __init__(self, parent):
self.dialog = gtk.Dialog(_('Keyboard Shortcuts'), parent, gtk.DIALOG_MODAL
| gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT
| gtk.gdk.WINDOW_TYPE_HINT_DIALOG,
(gtk.STOCK_OK, gtk.RESPONSE_OK))
self.parent = parent
def __init__(self):
self.parent = get_toplevel_window()
self.dialog = gtk.Dialog(_('Keyboard Shortcuts'), self.parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
| gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG,
(gtk.STOCK_OK, gtk.RESPONSE_OK))
self.dialog.set_icon(TRYTON_ICON)
self.dialog.set_has_separator(True)
self.dialog.set_default_response(gtk.RESPONSE_OK)
+3 -1
View File
@@ -5,13 +5,14 @@ import gtk
import gettext
import os
from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR
from tryton.common import get_toplevel_window
_ = gettext.gettext
class Tips(object):
def __init__(self, parent):
def __init__(self):
self.tips = [
_('''<b>Welcome to Tryton</b>
@@ -41,6 +42,7 @@ 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)
self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
+12 -13
View File
@@ -19,10 +19,9 @@ _ = gettext.gettext
class Action(SignalEvent):
def __init__(self, window, attrs=None, context=None):
def __init__(self, attrs=None, context=None):
super(Action, self).__init__()
self.act_id = int(attrs['name'])
self._window = window
self.screen = None
self.context = context or {}
@@ -30,7 +29,7 @@ class Action(SignalEvent):
self.action = rpc.execute('model', 'ir.action.act_window', 'read',
self.act_id, False, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self._window)
common.process_exception(exception)
raise
view_ids = False
@@ -147,7 +146,7 @@ class Action(SignalEvent):
if self.action['res_model']:
self.screen = Screen(self.action['res_model'],
self._window, mode=self.action['view_mode'],
mode=self.action['view_mode'],
context=self.context, view_ids=view_ids,
domain=self.domain, readonly=True, alternate_view=True)
alignment.add(self.screen.screen_container.alternate_viewport)
@@ -174,21 +173,21 @@ class Action(SignalEvent):
ctx = {}
ctx.update(rpc.CONTEXT)
ctx.update(self.context)
win = WinSearch(self.action['res_model'], domain=self.domain,
context=ctx, parent=self._window)
res = win.run()
if res:
self.screen.clear()
self.screen.load(res)
def callback(result):
if result:
self.screen.clear()
self.screen.load(res)
WinSearch(self.action['res_model'], callback, domain=self.domain,
context=ctx)
def _sig_open(self, widget):
try:
action_id = rpc.execute('model', 'ir.action',
'get_action_id', self.act_id, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self._window)
common.process_exception(exception)
if action_id:
Action2.execute(action_id, {}, self._window)
Action2.execute(action_id, {})
def _sig_previous(self, widget):
self.screen.display_prev()
@@ -213,7 +212,7 @@ class Action(SignalEvent):
self.domain, 0, self.action['limit'] or
CONFIG['client.limit'], None, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self._window)
common.process_exception(exception)
return False
if self.screen:
self.screen.clear()
+2 -3
View File
@@ -10,8 +10,7 @@ from tryton.config import CONFIG, TRYTON_ICON
class ParserBoard(object):
def __init__(self, window, context=None):
self.window = window
def __init__(self, context=None):
self.title = None
self.context = context
@@ -176,7 +175,7 @@ class ParserBoard(object):
paned.pack2(widget, resize=True, shrink=True)
elif node.localName == 'action':
name = str(attrs['name'])
widget_act = Action(self.window, attrs, self.context)
widget_act = Action(attrs, self.context)
widgets.append(widget_act)
container.wid_add(widget_act.widget,
colspan=int(attrs.get('colspan', 1)),
+2 -3
View File
@@ -9,12 +9,11 @@ from tryton.gui.window.view_board.action import Action
class ViewBoard(object):
'View board'
def __init__(self, arch, window, context=None):
self.window = window
def __init__(self, arch, context=None):
self.context = context
xml_dom = xml.dom.minidom.parseString(arch)
parser = ParserBoard(window, context)
parser = ParserBoard(context)
for node in xml_dom.childNodes:
if not node.nodeType == node.ELEMENT_NODE:
continue
+8 -12
View File
@@ -338,8 +338,7 @@ class M2OField(CharField):
try:
result = rpc.execute(*args)
except TrytonServerError, exception:
result = common.process_exception(exception, record.window,
*args)
result = common.process_exception(exception, *args)
if not result:
return
value = value, result['rec_name']
@@ -435,7 +434,7 @@ class O2MField(CharField):
return
from group import Group
parent_name = self.attrs.get('relation_field', '')
group = Group(self.attrs['relation'], {}, record.window,
group = Group(self.attrs['relation'], {},
parent=record,
parent_name=parent_name,
child_name=self.name,
@@ -506,7 +505,7 @@ class O2MField(CharField):
elif record.model_name == self.attrs['relation']:
fields = record.group.fields
parent_name = self.attrs.get('relation_field', '')
group = Group(self.attrs['relation'], {}, record.window,
group = Group(self.attrs['relation'], {},
parent=record, parent_name=parent_name,
child_name=self.name,
context=self.context,
@@ -557,13 +556,12 @@ class O2MField(CharField):
try:
fields_dict = rpc.execute(*args)
except TrytonServerError, exception:
fields_dict = common.process_exception(exception,
record.window, *args)
fields_dict = common.process_exception(exception, *args)
if not fields_dict:
return False
parent_name = self.attrs.get('relation_field', '')
group = Group(self.attrs['relation'], fields, record.window,
group = Group(self.attrs['relation'], fields_dict,
parent=record, parent_name=parent_name, child_name=self.name,
context=self.context,
parent_datetime_field=self.attrs.get('datetime_field'))
@@ -598,8 +596,7 @@ class O2MField(CharField):
try:
fields = rpc.execute(*args)
except TrytonServerError, exception:
fields = common.process_exception(exception, record.window,
*args)
fields = common.process_exception(exception, *args)
if not fields:
return False
@@ -691,7 +688,7 @@ class M2MField(O2MField):
elif record.model_name == self.attrs['relation']:
fields = record.group.fields
parent_name = self.attrs.get('relation_field', '')
group = Group(self.attrs['relation'], {}, record.window,
group = Group(self.attrs['relation'], {},
parent=record, parent_name=parent_name,
child_name=self.name,
context=self.context,
@@ -756,8 +753,7 @@ class ReferenceField(CharField):
try:
result = rpc.execute(*args)
except TrytonServerError, exception:
result = common.process_exception(exception, record.window,
*args)
result = common.process_exception(exception, *args)
if not result:
return
result = result['rec_name']
+5 -19
View File
@@ -12,7 +12,7 @@ from tryton.common.domain_inversion import is_leaf
class Group(SignalEvent, list):
def __init__(self, model_name, fields, window, ids=None, parent=None,
def __init__(self, model_name, fields, ids=None, parent=None,
parent_name='', child_name='', context=None, domain=None,
readonly=False, parent_datetime_field=None):
super(Group, self).__init__()
@@ -21,7 +21,6 @@ class Group(SignalEvent, list):
self.__domain = domain
self.__domain4inversion = None
self.lock_signal = False
self.__window = window
self.parent = parent
self.parent_name = parent_name or ''
self.child_name = child_name
@@ -41,16 +40,6 @@ class Group(SignalEvent, list):
self.__field_childs = None
self.exclude_field = None
def __get_window(self):
return self.__window
def __set_window(self, window):
for record in self:
record.window = window
self.__window = window
window = property(__get_window, __set_window)
@property
def domain(self):
if self.parent and self.child_name:
@@ -194,7 +183,7 @@ class Group(SignalEvent, list):
try:
res += rpc.execute(*args)
except TrytonServerError, exception:
res2 = common.process_exception(exception, self.window, *args)
res2 = common.process_exception(exception, *args)
if not res2:
return False
res += res2
@@ -211,8 +200,7 @@ class Group(SignalEvent, list):
for id in ids:
if self.get(id):
continue
new_record = Record(self.model_name, id, self.window,
group=self)
new_record = Record(self.model_name, id, group=self)
self.append(new_record)
new_records.append(new_record)
new_record.signal_connect(self, 'record-changed',
@@ -255,7 +243,6 @@ class Group(SignalEvent, list):
if record.group is not self:
record.signal_unconnect(record.group)
record.group = self
record.window = self.window
record.signal_connect(self, 'record-changed', self._record_changed)
record.signal_connect(self, 'record-modified', self._record_modified)
if position == -1:
@@ -287,7 +274,7 @@ class Group(SignalEvent, list):
def new(self, default=True, domain=None, context=None, signal=True,
obj_id=None):
record = Record(self.model_name, obj_id, self.window, group=self)
record = Record(self.model_name, obj_id, group=self)
record.signal_connect(self, 'record-changed', self._record_changed)
record.signal_connect(self, 'record-modified', self._record_modified)
if default:
@@ -387,7 +374,7 @@ class Group(SignalEvent, list):
try:
values = rpc.execute(*args)
except TrytonServerError, exception:
values = common.process_exception(exception, self.window, *args)
values = common.process_exception(exception, *args)
if not values:
return False
for name in to_add:
@@ -408,7 +395,6 @@ class Group(SignalEvent, list):
def destroy(self):
super(Group, self).destroy()
self.__window = None
self.parent = None
self.fields = {}
self.record_deleted, self.record_removed = [], []
+10 -29
View File
@@ -16,9 +16,8 @@ class Record(SignalEvent):
id = -1
def __init__(self, model_name, obj_id, window, group=None):
def __init__(self, model_name, obj_id, group=None):
super(Record, self).__init__()
self.__window = window
self.model_name = model_name
self.id = obj_id or Record.id
if self.id < 0:
@@ -79,7 +78,7 @@ class Record(SignalEvent):
except TrytonServerError, exception:
if raise_exception:
raise
values = common.process_exception(exception, self.window, *args)
values = common.process_exception(exception, *args)
if not values:
values = [{'id': x} for x in ids]
id2value = dict((value['id'], value) for value in values)
@@ -129,8 +128,6 @@ class Record(SignalEvent):
group.on_write = self.group.on_write
group.readonly = self.group.readonly
group._context.update(self.group._context)
if group.window != self.window:
group.window = self.window
return group
def get_path(self, group):
@@ -146,19 +143,6 @@ class Record(SignalEvent):
path.reverse()
return tuple(path)
def _get_window(self):
return self.__window
def _set_window(self, window):
self.__window = window
for fieldname, value in self.value.iteritems():
if fieldname not in self.group.fields:
continue
if isinstance(self.group.fields[fieldname], field.O2MField):
value.window = window
window = property(_get_window, _set_window)
def get_removed(self):
if self.group is not None:
return self in self.group.record_removed
@@ -248,8 +232,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window,
*args)
res = common.process_exception(exception, *args)
if not res:
return False
old_id = self.id
@@ -269,8 +252,7 @@ class Record(SignalEvent):
if not rpc.execute(*args):
return False
except TrytonServerError, exception:
res = common.process_exception(exception, self.window,
*args)
res = common.process_exception(exception, *args)
if not res:
return False
self._loaded.clear()
@@ -291,7 +273,7 @@ class Record(SignalEvent):
try:
vals = rpc.execute(*args)
except TrytonServerError, exception:
vals = common.process_exception(exception, self.window, *args)
vals = common.process_exception(exception, *args)
if not vals:
return
if (self.parent
@@ -312,7 +294,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
return ''
return res['rec_name']
@@ -464,7 +446,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
return
later = {}
@@ -514,7 +496,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
return
self.group.fields[fieldname].set_on_change(self, res)
@@ -537,7 +519,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
# ensure res is a list
res = []
@@ -551,7 +533,7 @@ class Record(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
res = common.process_exception(exception, *args)
if not res:
return
self.set_default(res)
@@ -571,7 +553,6 @@ class Record(SignalEvent):
def destroy(self):
super(Record, self).destroy()
self.window = None
self.group = None
self.value = None
self.next = None
+21 -28
View File
@@ -18,10 +18,10 @@ from tryton.exceptions import TrytonServerError
class Screen(SignalEvent):
"Screen"
def __init__(self, model_name, window, view_ids=None, mode=None,
context=None, views_preload=None, domain=None, row_activate=None,
limit=None, readonly=False, exclude_field=None, sort=None,
search_value=None, alternate_view=False):
def __init__(self, model_name, view_ids=None, mode=None, context=None,
views_preload=None, domain=None, row_activate=None, limit=None,
readonly=False, exclude_field=None, sort=None, search_value=None,
alternate_view=False):
if view_ids is None:
view_ids = []
if mode is None:
@@ -50,7 +50,6 @@ class Screen(SignalEvent):
self.parent = None
self.parent_name = None
self.exclude_field = exclude_field
self.__window = window
self.filter_widget = None
self.__group = None
self.new_group()
@@ -92,8 +91,8 @@ class Screen(SignalEvent):
except TrytonServerError:
return
self.filter_widget = Form(self.fields_view_tree,
self.model_name, self.window, self.domain,
(self, self.search_filter), self.context)
self.model_name, self.domain, (self, self.search_filter),
self.context)
self.screen_container.add_filter(self.filter_widget.widget,
self.search_filter, self.search_clear,
self.search_prev, self.search_next)
@@ -138,8 +137,7 @@ class Screen(SignalEvent):
try:
ids = rpc.execute(*rpc_args)
except TrytonServerError, exception:
ids = (common.process_exception(exception, self.window, *rpc_args)
or [])
ids = (common.process_exception(exception, *rpc_args) or [])
if not only_ids:
if len(ids) == limit:
rpc_args = ('model', self.model_name, 'search_count', values,
@@ -148,7 +146,7 @@ class Screen(SignalEvent):
self.search_count = rpc.execute(*rpc_args)
except TrytonServerError, exception:
self.search_count = (common.process_exception(exception,
self.window, *rpc_args) or 0)
*rpc_args) or 0)
else:
self.search_count = len(ids)
self.screen_container.but_prev.set_sensitive(bool(offset))
@@ -193,7 +191,7 @@ class Screen(SignalEvent):
group = property(__get_group, __set_group)
def new_group(self):
self.group = Group(self.model_name, {}, self.window, domain=self.domain,
self.group = Group(self.model_name, {}, domain=self.domain,
context=self.context, readonly=self.readonly)
def _group_cleared(self, group, signal):
@@ -243,15 +241,6 @@ class Screen(SignalEvent):
current_record = property(__get_current_record, __set_current_record)
def __get_window(self):
return self.__window
def __set_window(self, window):
self.group.window = window
self.__window = window
window = property(__get_window, __set_window)
def update_attachment(self, record):
if record != self.current_record:
return False
@@ -266,7 +255,6 @@ class Screen(SignalEvent):
self.group.signal_unconnect(self)
self.group.destroy()
self.parent = None
self.__window = None
self.__group = None
self.__current_record = None
self.screen_container = None
@@ -274,9 +262,16 @@ class Screen(SignalEvent):
def default_row_activate(self):
from tryton.action import Action
from tryton.gui.main import Main
main = Main.get_main()
current_form = main.get_page()
if current_form:
for dialog in current_form.dialogs:
dialog.hide()
if (self.current_view.view_type == 'tree' and
self.current_view.widget_tree.keyword_open):
return Action.exec_keyword('tree_open', self.window, {
return Action.exec_keyword('tree_open', {
'model': self.model_name,
'id': self.id_get(),
'ids': [self.id_get()],
@@ -338,7 +333,7 @@ class Screen(SignalEvent):
try:
view = rpc.execute(*args)
except TrytonServerError, exception:
view = common.process_exception(exception, self.window, *args)
view = common.process_exception(exception, *args)
if not view:
return
return self.add_view(view, display, context=context)
@@ -366,7 +361,7 @@ class Screen(SignalEvent):
from tryton.gui.window.view_form.view.widget_parse import WidgetParse
self.group.add_fields(fields, context=context)
parser = WidgetParse(parent=self.parent, window=self.window)
parser = WidgetParse(parent=self.parent)
view = parser.parse(self, xml_dom, self.group.fields,
children_field=children_field)
@@ -537,8 +532,7 @@ class Screen(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window,
*args)
res = common.process_exception(exception, *args)
if not res:
return False
self.current_view.set_cursor()
@@ -583,8 +577,7 @@ class Screen(SignalEvent):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window,
*args)
res = common.process_exception(exception, *args)
if not res:
return False
if not records:
+4 -14
View File
@@ -15,11 +15,10 @@ _ = gettext.gettext
class ViewForm(ParserView):
def __init__(self, window, screen, widget, children=None,
buttons=None, notebooks=None, cursor_widget='',
children_field=None):
super(ViewForm, self).__init__(window, screen, widget, children,
buttons, notebooks, cursor_widget, children_field)
def __init__(self, screen, widget, children=None, buttons=None,
notebooks=None, cursor_widget='', children_field=None):
super(ViewForm, self).__init__(screen, widget, children, buttons,
notebooks, cursor_widget, children_field)
self.view_type = 'form'
for button in self.buttons:
@@ -41,15 +40,6 @@ class ViewForm(ParserView):
viewport = gtk.Viewport()
viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN)
viewport.add(scroll)
if isinstance(self.screen.window, gtk.Dialog):
width, height = self.widget.size_request()
if self.screen.window:
parent = self.screen.window.get_transient_for()
if parent:
parent_width, parent_height = parent.get_size()
width = min(parent_width - 40, width)
height = min(parent_height - 80, height)
vbox.set_size_request(width or -1, height or -1)
vbox.pack_start(viewport, expand=True, fill=True)
self.widget = vbox
@@ -20,9 +20,8 @@ def humanize(size):
class Binary(WidgetInterface):
"Binary"
def __init__(self, field_name, model_name, window, attrs=None):
super(Binary, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Binary, self).__init__(field_name, model_name, attrs=attrs)
self.filename = attrs.get('filename')
@@ -136,7 +135,7 @@ class Binary(WidgetInterface):
root, type_ = os.path.splitext(filename)
if type_:
type_ = type_[1:]
file_open(file_path, type_, self.window)
file_open(file_path, type_)
def sig_save_as(self, widget=None):
filename = ''
@@ -9,7 +9,8 @@ from interface import WidgetInterface
import tryton.rpc as rpc
from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, message, \
TRYTON_ICON, timezoned_date
from tryton.common import date_widget, Tooltips, datetime_strftime
from tryton.common import date_widget, Tooltips, datetime_strftime, \
get_toplevel_window
from tryton.translate import date_format
_ = gettext.gettext
@@ -18,9 +19,8 @@ _ = gettext.gettext
class Calendar(WidgetInterface):
"Calendar"
def __init__(self, field_name, model_name, window, attrs=None):
super(Calendar, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Calendar, self).__init__(field_name, model_name, attrs=attrs)
self.format = date_format()
self.widget = date_widget.ComplexEntry(self.format, spacing=0)
@@ -106,7 +106,8 @@ class Calendar(WidgetInterface):
return True
def cal_open(self, widget):
win = gtk.Dialog(_('Date Selection'), self.window,
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))
@@ -144,16 +145,15 @@ class Calendar(WidgetInterface):
format = format.replace('%Y', '0%Y')
self.entry.set_text(datetime_strftime(date, format))
self._focus_out()
self.window.present()
parent.present()
win.destroy()
class DateTime(WidgetInterface):
"DateTime"
def __init__(self, field_name, model_name, window, attrs=None):
super(DateTime, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(DateTime, self).__init__(field_name, model_name, attrs=attrs)
self.format = date_format() + ' ' + HM_FORMAT
self.widget = date_widget.ComplexEntry(self.format, spacing=0)
@@ -239,7 +239,8 @@ class DateTime(WidgetInterface):
return True
def cal_open(self, widget):
win = gtk.Dialog(_('Date Time Selection'), self.window,
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))
@@ -290,5 +291,5 @@ class DateTime(WidgetInterface):
value = datetime_strftime(date, DHM_FORMAT)
self.show(value, timezone=False)
self._focus_out()
self.window.present()
parent.present()
win.destroy()
@@ -13,8 +13,8 @@ _ = gettext.gettext
class Char(WidgetInterface):
"Char"
def __init__(self, field_name, model_name, window, attrs=None):
super(Char, self).__init__(field_name, model_name, window, attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Char, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox()
self.autocomplete = bool(attrs.get('autocomplete'))
@@ -95,8 +95,8 @@ class Char(WidgetInterface):
class Sha(Char):
def __init__(self, field_name, model_name, window, attrs=None):
super(Sha, self).__init__(field_name, model_name, window, attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Sha, self).__init__(field_name, model_name, attrs=attrs)
self.entry.props.visibility = False
self.visibility_checkbox = gtk.CheckButton()
@@ -8,9 +8,8 @@ _ = gettext.gettext
class CheckBox(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(CheckBox, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(CheckBox, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.CheckButton()
self.widget.connect('focus-in-event', lambda x, y: self._focus_in())
self.widget.connect('focus-out-event', lambda x, y: self._focus_out())
@@ -8,9 +8,8 @@ from integer import Integer
class Float(Integer):
"Float"
def __init__(self, field_name, model_name, window, attrs=None):
super(Float, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Float, self).__init__(field_name, model_name, attrs=attrs)
self.digits = (16, 2)
self.entry.connect('key-press-event', self.key_press_event)
@@ -8,9 +8,8 @@ import tryton.rpc as rpc
class FloatTime(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(FloatTime, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(FloatTime, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox()
self.entry = gtk.Entry()
@@ -18,9 +18,8 @@ NOIMAGE = open(os.path.join(PIXMAPS_DIR, 'tryton-noimage.png'), 'rb').read()
class Image(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(Image, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Image, self).__init__(field_name, model_name, attrs=attrs)
self.filename = attrs.get('filename')
self.height = int(attrs.get('img_height', 100))
@@ -127,8 +126,8 @@ class Image(WidgetInterface):
for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"):
filter_image.add_pattern(pat)
filename = file_selection(_('Open...'), parent=self.window,
preview=True, filters=[filter_image, filter_all])
filename = file_selection(_('Open...'), preview=True,
filters=[filter_image, filter_all])
if filename:
self.field.set_client(self.record,
encodestring(open(filename, 'rb').read()))
@@ -149,14 +148,14 @@ class Image(WidgetInterface):
root, type_ = os.path.splitext(filename)
if type_:
type_ = type_[1:]
file_open(file_path, type_, self.window)
file_open(file_path, type_)
def sig_save_as(self, widget):
filename = ''
if self.filename_field:
filename = self.filename_field.get(self.record)
filename = file_selection(_('Save As...'), filename=filename,
parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if filename:
with open(filename, 'wb') as fp:
fp.write(decodestring(self.field.get(self.record)))
@@ -7,9 +7,8 @@ import locale
class Integer(Char):
"Integer"
def __init__(self, field_name, model_name, window, attrs=None):
super(Integer, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Integer, self).__init__(field_name, model_name, attrs=attrs)
self.entry.set_max_length(0)
self.entry.set_alignment(1.0)
self.entry.connect('insert_text', self.sig_insert_text)
@@ -6,10 +6,9 @@ from tryton.common import COLORS
class WidgetInterface(object):
def __init__(self, field_name, model_name, window, attrs=None):
def __init__(self, field_name, model_name, attrs=None):
self.field_name = field_name
self.model_name = model_name
self.window = window
self.view = None # Filled by ViewForm
self.attrs = attrs or {}
for attr_name in ('readonly', 'invisible'):
@@ -16,9 +16,8 @@ _ = gettext.gettext
class Many2Many(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(Many2Many, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Many2Many, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.VBox(homogeneous=False, spacing=5)
self._readonly = True
@@ -71,13 +70,11 @@ class Many2Many(WidgetInterface):
frame.set_shadow_type(gtk.SHADOW_OUT)
self.widget.pack_start(frame, expand=False, fill=True)
self.screen = Screen(attrs['relation'], self.window,
mode=['tree'], views_preload=attrs.get('views', {}),
row_activate=self._on_activate)
self.screen = Screen(attrs['relation'], mode=['tree'],
views_preload=attrs.get('views', {}),
row_activate=self._on_activate)
self.screen.signal_connect(self, 'record-message', self._sig_label)
if not isinstance(self.screen.window, gtk.Dialog):
self.screen.widget.set_size_request(0, 0)
self.widget.pack_start(self.screen.widget, expand=True, fill=True)
self.screen.widget.connect('key_press_event', self.on_keypress)
@@ -130,23 +127,24 @@ class Many2Many(WidgetInterface):
ids = rpc.execute('model', self.attrs['relation'], 'search',
dom , 0, CONFIG['client.limit'], None, context)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
if len(ids) != 1 or not value:
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
context=context, domain=domain,
parent=self.widget.get_toplevel(),
views_preload=self.attrs.get('views', {}))
ids = win.run()
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
self.wid_text.set_text('')
def callback(ids):
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
self.wid_text.set_text('')
if len(ids) != 1 or not value:
WinSearch(self.attrs['relation'], callback, sel_multi=True,
ids=ids, context=context, domain=domain,
views_preload=self.attrs.get('views', {}))
else:
callback(ids)
def _sig_remove(self, *args):
self.screen.remove(remove=True)
@@ -160,12 +158,12 @@ class Many2Many(WidgetInterface):
def _sig_edit(self):
if self.screen.current_record:
win = WinForm(self.screen, self.widget.get_toplevel())
if win.run():
self.screen.current_record.save()
else:
self.screen.current_record.cancel()
win.destroy()
def callback(result):
if result:
self.screen.current_record.save()
else:
self.screen.current_record.cancel()
WinForm(self.screen, callback)
def _readonly_set(self, value):
self._readonly = value
@@ -21,9 +21,8 @@ _ = gettext.gettext
class Many2One(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(Many2One, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Many2One, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox(spacing=0)
self.widget.set_property('sensitive', True)
@@ -116,55 +115,48 @@ class Many2One(WidgetInterface):
context)
except TrytonServerError, exception:
self.focus_out = True
common.process_exception(exception, self.window)
common.process_exception(exception)
self.changed = True
return False
return
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 True
return
def callback(ids):
if ids:
self.field.set_client(self.record, ids[0],
force_change=True)
self.focus_out = True
self.display(self.record, self.field)
win = WinSearch(self.attrs['relation'], sel_multi=False,
ids=ids, context=context, domain=domain,
parent=self.widget.get_toplevel(),
views_preload=self.attrs.get('views', {}))
ids = win.run()
if ids:
self.field.set_client(self.record, ids[0],
force_change=True)
self.focus_out = True
self.display(self.record, self.field)
return True
else:
self.focus_out = True
self.display(self.record, self.field)
return False
WinSearch(self.attrs['relation'], callback, sel_multi=False,
ids=ids, context=context, domain=domain,
views_preload=self.attrs.get('views', {}))
return
self.focus_out = True
self.display(self.record, self.field)
self.changed = True
return True
return
def get_screen(self):
domain = self.field.domain_get(self.record)
context = self.field.context_get(self.record)
return Screen(self.attrs['relation'], self.window, domain=domain,
context=context, mode=['form'],
views_preload=self.attrs.get('views', {}),
readonly=self._readonly)
return Screen(self.attrs['relation'], domain=domain, context=context,
mode=['form'], views_preload=self.attrs.get('views', {}),
readonly=self._readonly)
def sig_new(self, *args):
self.focus_out = False
screen = self.get_screen()
win = WinForm(screen, self.widget.get_toplevel(), new=True)
if win.run():
if screen.save_current():
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
screen.current_record.rec_name())
self.field.set_client(self.record, value)
win.destroy()
self.focus_out = True
self.focus_out = True
WinForm(screen, callback, new=True)
def sig_edit(self, widget):
self.changed = False
@@ -173,53 +165,59 @@ class Many2One(WidgetInterface):
if value:
screen = self.get_screen()
screen.load([self.field.get(self.record)])
win = WinForm(screen, self.widget.get_toplevel())
while win.run():
if screen.save_current():
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
screen.current_record.rec_name())
self.field.set_client(self.record, value, force_change=True)
break
else:
self.field.set_client(self.record, value,
force_change=True)
elif result:
screen.display()
win.destroy()
else:
if not self._readonly:
domain = self.field.domain_get(self.record)
context = rpc.CONTEXT.copy()
context.update(self.field.context_get(self.record))
self.wid_text.grab_focus()
return WinForm(screen, callback)
self.focus_out = True
self.display(self.record, self.field)
self.changed = True
WinForm(screen, callback)
return
elif not self._readonly:
domain = self.field.domain_get(self.record)
context = rpc.CONTEXT.copy()
context.update(self.field.context_get(self.record))
self.wid_text.grab_focus()
try:
if self.wid_text.get_text():
dom = [('rec_name', 'ilike',
'%' + self.wid_text.get_text() + '%'),
domain]
else:
dom = domain
ids = rpc.execute('model', self.attrs['relation'],
'search', dom, 0, CONFIG['client.limit'], None,
context)
except TrytonServerError, exception:
self.focus_out = True
common.process_exception(exception, self.window)
self.changed = True
return False
if ids and 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 True
try:
if self.wid_text.get_text():
dom = [('rec_name', 'ilike',
'%' + self.wid_text.get_text() + '%'),
domain]
else:
dom = domain
ids = rpc.execute('model', self.attrs['relation'],
'search', dom, 0, CONFIG['client.limit'], None,
context)
except TrytonServerError, exception:
self.focus_out = True
common.process_exception(exception)
self.changed = True
return False
if ids and 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 True
win = WinSearch(self.attrs['relation'], sel_multi=False,
ids=ids, context=context,
domain=domain, parent=self.widget.get_toplevel(),
views_preload=self.attrs.get('views', {}))
ids = win.run()
def callback(ids):
if ids:
self.field.set_client(self.record, ids[0],
force_change=True)
self.focus_out = True
self.display(self.record, self.field)
self.changed = True
WinSearch(self.attrs['relation'], callback, sel_multi=False,
ids=ids, context=context, domain=domain,
views_preload=self.attrs.get('views', {}))
return
self.focus_out = True
self.display(self.record, self.field)
self.changed = True
@@ -233,7 +231,7 @@ class Many2One(WidgetInterface):
self.sig_edit(widget)
return True
elif event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return) and editable:
return not self.sig_activate(widget, event, key_press=True)
self.sig_activate(widget, event, key_press=True)
return False
def sig_changed(self, *args):
@@ -273,7 +271,7 @@ class Many2One(WidgetInterface):
try:
relates = rpc.execute(*args)
except TrytonServerError, exception:
relates = common.process_exception(exception, self.window)
relates = common.process_exception(exception)
if not relates:
return False
menu_entries = []
@@ -308,10 +306,9 @@ class Many2One(WidgetInterface):
act = action.copy()
obj_id = self.field.get(self.record)
if not obj_id:
common.message(_('You must select a record to use the relation!'),
self.window)
common.message(_('You must select a record to use the relation!'))
return False
screen = Screen(self.attrs['relation'], self.window)
screen = Screen(self.attrs['relation'])
screen.load([obj_id])
encoder = PYSONEncoder()
act['domain'] = encoder.encode(screen.current_record.expr_eval(
@@ -321,11 +318,11 @@ class Many2One(WidgetInterface):
data['model'] = self.attrs['relation']
data['id'] = obj_id
data['ids'] = [obj_id]
return Action._exec_action(act, self.window, data, context)
return Action._exec_action(act, data, context)
def click_and_action(self, atype):
obj_id = self.field.get(self.record)
return Action.exec_keyword(atype, self.window, {
return Action.exec_keyword(atype, {
'model': self.attrs['relation'],
'id': obj_id or False,
'ids': [obj_id],
@@ -18,9 +18,8 @@ _ = gettext.gettext
class One2Many(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(One2Many, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(One2Many, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.VBox(homogeneous=False, spacing=2)
self._readonly = True
@@ -154,15 +153,13 @@ class One2Many(WidgetInterface):
frame.set_shadow_type(gtk.SHADOW_OUT)
self.widget.pack_start(frame, expand=False, fill=True)
self.screen = Screen(attrs['relation'], self.window,
mode=attrs.get('mode', 'tree,form').split(','),
views_preload=attrs.get('views', {}),
row_activate=self._on_activate,
exclude_field=attrs.get('relation_field', None))
self.screen = Screen(attrs['relation'],
mode=attrs.get('mode', 'tree,form').split(','),
views_preload=attrs.get('views', {}),
row_activate=self._on_activate,
exclude_field=attrs.get('relation_field', None))
self.screen.signal_connect(self, 'record-message', self._sig_label)
if not isinstance(self.screen.window, gtk.Dialog):
self.screen.widget.set_size_request(0, 0)
self.widget.pack_start(self.screen.widget, expand=True, fill=True)
self.screen.widget.connect('key_press_event', self.on_keypress)
@@ -236,17 +233,19 @@ class One2Many(WidgetInterface):
sequence = None
if self.screen.current_view.view_type == 'tree':
sequence = self.screen.current_view.widget_tree.sequence
def update_sequence():
if sequence:
self.screen.group.set_sequence(field=sequence)
if (self.screen.current_view.view_type == 'form') \
or self.screen.editable_get():
self.screen.new(context=ctx)
self.screen.current_view.widget.set_sensitive(True)
update_sequence()
else:
win = WinForm(self.screen, self.widget.get_toplevel(), new=True,
WinForm(self.screen, lambda a: update_sequence(), new=True,
many=True, context=ctx)
win.run()
win.destroy()
if sequence:
self.screen.group.set_sequence(field=sequence)
def _sig_edit(self, widget=None):
self.view.set_value()
@@ -256,9 +255,7 @@ class One2Many(WidgetInterface):
if not record.validate(fields):
self.screen.display()
return
win = WinForm(self.screen, self.widget.get_toplevel())
win.run()
win.destroy()
WinForm(self.screen, lambda a: None)
def _sig_next(self, widget):
self.view.set_value()
@@ -309,22 +306,24 @@ class One2Many(WidgetInterface):
ids = rpc.execute('model', self.attrs['relation'], 'search', dom,
0, CONFIG['client.limit'], None, context)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
def callback(ids):
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
self.wid_text.set_text('')
if len(ids) != 1:
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
context=context, domain=domain, parent=self.window,
views_preload=self.attrs.get('views', {}))
ids = win.run()
WinSearch(self.attrs['relation'], callback, sel_multi=True,
ids=ids, context=context, domain=domain,
views_preload=self.attrs.get('views', {}))
else:
callback(ids)
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
self.wid_text.set_text('')
def _sig_label(self, screen, signal_data):
name = '_'
@@ -46,7 +46,7 @@ class Button(object):
obj_id = self.form.screen.save_current()
if obj_id:
if not self.attrs.get('confirm', False) or \
common.sur(self.attrs['confirm'], self.form.window):
common.sur(self.attrs['confirm']):
button_type = self.attrs.get('type', 'workflow')
ctx = rpc.CONTEXT.copy()
ctx.update(record.context_get())
@@ -57,16 +57,14 @@ class Button(object):
try:
rpc.execute(*args)
except TrytonServerError, exception:
common.process_exception(exception, self.form.window,
*args)
common.process_exception(exception, *args)
elif button_type == 'object':
args = ('model', self.form.screen.model_name, self.attrs['name'],
[obj_id], ctx)
try:
rpc.execute(*args)
except TrytonServerError, exception:
common.process_exception(exception, self.form.window,
*args)
common.process_exception(exception, *args)
elif button_type == 'action':
action_id = None
args = ('model', 'ir.action', 'get_action_id',
@@ -74,14 +72,13 @@ class Button(object):
try:
action_id = rpc.execute(*args)
except TrytonServerError, exception:
action_id = common.process_exception(exception, self.form.window,
*args)
action_id = common.process_exception(exception, *args)
if action_id:
Action.execute(action_id, {
'model': self.form.screen.model_name,
'id': obj_id,
'ids': [obj_id],
}, self.form.window, context=ctx)
}, context=ctx)
else:
raise Exception('Unallowed button type')
self.form.screen.reload(written=True)
@@ -289,10 +286,10 @@ class _container(object):
class ParserForm(ParserInterface):
def __init__(self, window, parent=None, attrs=None, screen=None,
def __init__(self, parent=None, attrs=None, screen=None,
children_field=None):
super(ParserForm, self).__init__(window, parent=parent, attrs=attrs,
screen=screen, children_field=children_field)
super(ParserForm, self).__init__(parent=parent, attrs=attrs,
screen=screen, children_field=children_field)
self.widget_id = 0
def parse(self, model_name, root_node, fields, notebook=None, paned=None,
@@ -445,16 +442,6 @@ class ParserForm(ParserInterface):
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
self.parse(model_name, node, fields, notebook,
tooltips=tooltips)
max_width, max_height = -1, -1
window_width, window_height = Main.get_main().window.get_size()
for i in xrange(notebook.get_n_pages()):
width, height = notebook.get_nth_page(i)\
.get_child().get_child().size_request()
if width > max_width and width < window_width - 50:
max_width = width
if height > max_height and height < window_height - 50:
max_height = height
notebook.set_size_request(max_width + 20, max_height + 20)
if not cursor_widget:
cursor_widget = cursor_widget2
notebook_list.extend(notebook_list2)
@@ -555,8 +542,7 @@ class ParserForm(ParserInterface):
not attr_name in attrs:
attrs[attr_name] = fields[name].attrs[attr_name]
widget_act = WIDGETS_TYPE[ftype][0](name, model_name,
self.window, attrs)
widget_act = WIDGETS_TYPE[ftype][0](name, model_name, attrs)
self.widget_id += 1
widget_act.position = self.widget_id
dict_widget.setdefault(name, [])
@@ -674,8 +660,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!'),
parent=self.window)
_('You need to save the record before adding translations!'))
return False
obj_id = self.screen.current_record.save(force_reload=False)
@@ -684,12 +669,11 @@ class ParserForm(ParserInterface):
'search', [('translatable', '=', '1')],
rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
if not lang_ids:
common.message(_('No other language available!'),
parent=self.window)
common.message(_('No other language available!'))
return False
try:
lang_ids += rpc.execute('model', 'ir.lang',
@@ -699,7 +683,7 @@ class ParserForm(ParserInterface):
'read', lang_ids, ['code', 'name'],
rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
code = rpc.CONTEXT.get('language', 'en_US')
@@ -749,7 +733,8 @@ class ParserForm(ParserInterface):
return None, False
win = gtk.Dialog(_('Add Translation'), self.window,
parent = common.get_toplevel_window()
win = gtk.Dialog(_('Add Translation'),parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
win.set_has_separator(True)
win.vbox.set_spacing(5)
@@ -783,7 +768,7 @@ class ParserForm(ParserInterface):
val = rpc.execute('model', model_name,
'read', [obj_id], [name], context)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
val = val[0]
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
@@ -836,15 +821,12 @@ class ParserForm(ParserInterface):
try:
rpc.execute(*args)
except TrytonServerError, exception:
common.process_exception(exception, self.window, *args)
if response == gtk.RESPONSE_CANCEL:
self.window.present()
win.destroy()
return
self.screen.current_record.reload()
self.window.present()
common.process_exception(exception, *args)
if response != gtk.RESPONSE_CANCEL:
self.screen.current_record.reload()
win.destroy()
return True
parent.present()
return response != gtk.RESPONSE_CANCEL
from calendar import Calendar, DateTime
from float import Float
@@ -14,9 +14,8 @@ class ProgressBar(WidgetInterface):
'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM,
}
def __init__(self, field_name, model_name, window, attrs=None):
super(ProgressBar, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(ProgressBar, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.ProgressBar()
orientation = self.orientations.get(attrs.get('orientation',
'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT)
@@ -18,9 +18,8 @@ _ = gettext.gettext
class Reference(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(Reference, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Reference, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox(spacing=0)
@@ -83,7 +82,7 @@ class Reference(WidgetInterface):
selection = rpc.execute('model',
self.model_name, selection, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
selection = []
selection.sort(key=operator.itemgetter(1))
self.set_popdown(selection)
@@ -152,19 +151,22 @@ class Reference(WidgetInterface):
model, (obj_id, name) = value
except ValueError:
self.focus_out = True
return False
return
if model and obj_id:
if not leave:
screen = Screen(model, self.window, mode=['form'])
screen = Screen(model, mode=['form'])
screen.load([obj_id])
win = WinForm(screen, self.widget.get_toplevel())
if win.run():
if screen.save_current():
def callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
screen.current_record.rec_name())
self.field.set_client(self.record, (model, value),
force_change=True)
win.destroy()
self.focus_out = True
self.changed = True
self.display(self.record, self.field)
WinForm(screen, callback)
return
elif model:
if not self._readonly and ( self.wid_text.get_text() or not leave):
domain = self.field.domain_get(self.record)
@@ -182,22 +184,25 @@ class Reference(WidgetInterface):
except TrytonServerError, exception:
self.focus_out = True
self.changed = True
common.process_exception(exception, self.window)
return False
common.process_exception(exception)
return
if ids and len(ids) == 1:
self.field.set_client(self.record, (model, (ids[0], '')))
self.display(self.record, self.field)
self.focus_out = True
self.changed = True
return True
return
win = WinSearch(model, sel_multi=False, ids=ids, context=context,
domain=domain, parent=self.widget.get_toplevel())
ids = win.run()
if ids:
self.field.set_client(self.record, (model, (ids[0], '')))
else:
self.field.set_client(self.record, ('', (name, name)))
def callback(ids):
if ids:
self.field.set_client(self.record, (model, (ids[0], '')))
self.focus_out = True
self.changed = True
self.display(self.record, self.field)
WinSearch(model, callback, sel_multi=False, ids=ids,
context=context, domain=domain)
return
self.field.set_client(self.record, ('', (name, name)))
self.focus_out = True
self.changed = True
self.display(self.record, self.field)
@@ -206,7 +211,7 @@ class Reference(WidgetInterface):
model = self.get_model()
if not model:
return
screen = Screen(model, self.window, mode=['form'])
screen = Screen(model, mode=['form'])
win = WinForm(screen, self.widget.get_toplevel(), new=True)
if win.run():
if screen.save_current():
@@ -272,8 +277,7 @@ class Reference(WidgetInterface):
try:
name = rpc.execute(*args)
except TrytonServerError, exception:
name = common.process_exception(exception, self.window,
*args)
name = common.process_exception(exception, *args)
if not name:
name = '???'
self.wid_text.set_text(name)
@@ -12,9 +12,8 @@ from tryton.exceptions import TrytonServerError
class Selection(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(Selection, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(Selection, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox(spacing=3)
self.entry = gtk.ComboBoxEntry()
@@ -45,7 +44,7 @@ class Selection(WidgetInterface):
selection = rpc.execute('model',
self.model_name, selection, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
selection = []
self.selection = selection[:]
if self.attrs.get('sort', True):
@@ -67,7 +66,7 @@ class Selection(WidgetInterface):
try:
result = rpc.execute(*args)
except TrytonServerError, exception:
result = common.process_exception(exception, self.window, args)
result = common.process_exception(exception, args)
if isinstance(result, list):
selection = [(x['id'], x['rec_name']) for x in result]
selection.append((False, ''))
@@ -13,9 +13,8 @@ except ImportError:
class TextBox(WidgetInterface):
def __init__(self, field_name, model_name, window, attrs=None):
super(TextBox, self).__init__(field_name, model_name, window,
attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(TextBox, self).__init__(field_name, model_name, attrs=attrs)
self.widget = gtk.HBox()
self.scrolledwindow = gtk.ScrolledWindow()
@@ -10,8 +10,8 @@ import tryton.common as common
class URL(Char):
"url"
def __init__(self, field_name, model_name, window, attrs=None):
super(URL, self).__init__(field_name, model_name, window, attrs=attrs)
def __init__(self, field_name, model_name, attrs=None):
super(URL, self).__init__(field_name, model_name, attrs=attrs)
self.tooltips = common.Tooltips()
self.button = gtk.Button()
+4 -5
View File
@@ -5,11 +5,10 @@ from interface import ParserView
class ViewGraph(ParserView):
def __init__(self, window, screen, widget, children=None,
buttons=None, notebooks=None, cursor_widget=None,
children_field=None):
super(ViewGraph, self).__init__(window, screen, widget, children,
buttons, notebooks, cursor_widget, children_field)
def __init__(self, screen, widget, children=None, buttons=None,
notebooks=None, cursor_widget=None, children_field=None):
super(ViewGraph, self).__init__(screen, widget, children, buttons,
notebooks, cursor_widget, children_field)
self.view_type = 'graph'
self.widgets = children
@@ -115,12 +115,12 @@ class Bar(Graph):
self.queue_draw_area(minx - 1, miny - 1,
maxx - minx + 2, maxy - miny + 2)
def action(self, window):
super(Bar, self).action(window)
def action(self):
super(Bar, self).action()
for bar in self.bars:
if bar.highlight:
ids = self.ids[bar.xname]
self.action_keyword(ids, window)
self.action_keyword(ids)
class VerticalBar(Bar):
@@ -128,10 +128,10 @@ class Graph(gtk.DrawingArea):
self.queue_draw()
def action(self, window):
def action(self):
self.popup.hide()
def action_keyword(self, ids, window):
def action_keyword(self, ids):
if not ids:
return
ctx = self.group.context.copy()
@@ -146,7 +146,7 @@ class Graph(gtk.DrawingArea):
else:
hide = False
with Window(hide_current=hide):
return Action.exec_keyword('graph_open', window, {
return Action.exec_keyword('graph_open', {
'model': self.model,
'id': ids[0],
'ids': ids,
@@ -201,12 +201,12 @@ class Line(Graph):
super(Line, self).drawAxis(cr, width, height)
self.drawLine(cr, 1.0, 0)
def action(self, window):
super(Line, self).action(window)
def action(self):
super(Line, self).action()
for point in self.points:
if point.highlight:
ids = self.ids[point.xname]
self.action_keyword(ids, window)
self.action_keyword(ids)
def YLabels(self):
ylabels = super(Line, self).YLabels()
@@ -20,8 +20,9 @@ GRAPH_TYPE = {
'pie': Pie,
}
def save(widget, graph, window):
dia = gtk.Dialog(_('Save As'), window,
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))
@@ -93,24 +94,24 @@ def save(widget, graph, window):
gtk.MESSAGE_ERROR)
else:
break
window.present()
parent.present()
dia.destroy()
return
def button_press(widget, event, graph, window):
def button_press(widget, event, graph):
if event.button == 3:
menu = gtk.Menu()
item = gtk.ImageMenuItem(_('Save As...'))
img = gtk.Image()
img.set_from_stock('tryton-save-as', gtk.ICON_SIZE_MENU)
item.set_image(img)
item.connect('activate', save, graph, window)
item.connect('activate', save, graph)
item.show()
menu.append(item)
menu.popup(None, None, None, event.button, event.time)
return True
elif event.button == 1:
graph.action(window)
graph.action()
class ParserGraph(ParserInterface):
@@ -145,6 +146,6 @@ class ParserGraph(ParserInterface):
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, self.window)
event.connect('button-press-event', button_press, widget)
return event, {'root': widget}, [], '', [], None
@@ -156,12 +156,12 @@ class Pie(Graph):
slice.highlight = False
self.queue_draw()
def action(self, window):
super(Pie, self).action(window)
def action(self):
super(Pie, self).action()
for slice in self.slices:
if slice.highlight:
ids = self.ids[slice.xname]
self.action_keyword(ids, window)
self.action_keyword(ids)
class Slice(object):
@@ -5,9 +5,8 @@
class ParserInterface(object):
def __init__(self, window, parent=None, attrs=None, screen=None,
def __init__(self, parent=None, attrs=None, screen=None,
children_field=None):
self.window = window
self.parent = parent
self.attrs = attrs
self.title = None
@@ -18,9 +17,8 @@ class ParserInterface(object):
class ParserView(object):
def __init__(self, window, screen, widget, children=None, buttons=None,
def __init__(self, screen, widget, children=None, buttons=None,
notebooks=None, cursor_widget=None, children_field=None):
self.window = window
self.screen = screen
self.widget = widget
self.children = children
+8 -13
View File
@@ -238,10 +238,10 @@ class AdaptModelGroup(gtk.GenericTreeModel):
class ViewList(ParserView):
def __init__(self, window, screen, widget, children=None, buttons=None,
def __init__(self, screen, widget, children=None, buttons=None,
notebooks=None, cursor_widget=None, children_field=None):
super(ViewList, self).__init__(window, screen, widget, children,
buttons, notebooks, cursor_widget, children_field)
super(ViewList, self).__init__(screen, widget, children, buttons,
notebooks, cursor_widget, children_field)
self.store = None
self.view_type = 'tree'
@@ -255,9 +255,6 @@ class ViewList(ParserView):
viewport.add(scroll)
self.widget_tree = self.widget
if isinstance(self.screen.window, gtk.Dialog):
width, height = self.widget_tree.size_request()
vbox.set_size_request(width or -1, height or -1)
vbox.pack_start(viewport, expand=True, fill=True)
self.widget_tree.screen = screen
@@ -536,8 +533,7 @@ class ViewList(ParserView):
try:
relates = rpc.execute(*args)
except TrytonServerError, exception:
relates = common.process_exception(exception, self.window,
*args)
relates = common.process_exception(exception, *args)
if not relates:
return False
menu_entries = []
@@ -579,12 +575,11 @@ class ViewList(ParserView):
context = {}
act = action.copy()
if not(value):
message(_('You must select a record to use the relation!'),
self.window)
message(_('You must select a record to use the relation!'))
return False
from tryton.gui.window.view_form.screen import Screen
screen = Screen(self.screen.group.fields[
path[1].name].attrs['relation'], self.window)
path[1].name].attrs['relation'])
screen.load([value])
encoder = PYSONEncoder()
act['domain'] = encoder.encode(screen.current_record.expr_eval(
@@ -594,10 +589,10 @@ class ViewList(ParserView):
data['model'] = self.screen.model_name
data['id'] = value
data['ids'] = [value]
return Action._exec_action(act, self.window, data, context)
return Action._exec_action(act, data, context)
def click_and_action(self, atype, value, path):
return Action.exec_keyword(atype, self.window, {
return Action.exec_keyword(atype, {
'model': self.screen.group.fields[
path[1].name].attrs['relation'],
'id': value or False,
@@ -32,12 +32,12 @@ class EditableTreeView(gtk.TreeView):
return
try:
real_value = cell.value_from_text(current_record, value)
field.set_client(current_record, real_value)
cell.value_from_text(current_record, value)
except parser.UnsettableColumn:
return
def on_open_remote(self, current_record, fieldname, create, value):
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:
@@ -45,13 +45,10 @@ class EditableTreeView(gtk.TreeView):
else:
changed = False
try:
valid, value = cell.open_remote(current_record, create,
changed, value)
if valid:
field.set_client(current_record, value)
cell.open_remote(current_record, create, changed, value,
callback=callback)
except NotImplementedError:
pass
return cell.get_textual_value(current_record)
def on_create_line(self):
model = self.get_model()
@@ -228,15 +225,19 @@ class EditableTreeView(gtk.TreeView):
else:
value = entry.get_active_text()
entry.disconnect(entry.editing_done_id)
newval = self.on_open_remote(record, column.name,
create=(event.keyval==gtk.keysyms.F3), value=value)
if isinstance(entry, gtk.Entry):
entry.set_text(newval)
else:
entry.set_active_text(newval)
entry.editing_done_id = entry.connect('editing_done',
self.on_editing_done)
self.set_cursor(path, column, True)
def callback():
cell = self.cells[column.name]
value = cell.get_textual_value(record)
if isinstance(entry, gtk.Entry):
entry.set_text(value)
else:
entry.set_active_text(value)
entry.editing_done_id = entry.connect('editing_done',
self.on_editing_done)
self.set_cursor(path, column, True)
self.on_open_remote(record, column.name,
create=(event.keyval==gtk.keysyms.F3), value=value,
callback=callback)
else:
field = record[column.name]
if isinstance(entry, gtk.Entry):
@@ -69,9 +69,9 @@ def sort_model(column, treeview, screen):
class ParserTree(ParserInterface):
def __init__(self, window, parent=None, attrs=None, screen=None,
def __init__(self, parent=None, attrs=None, screen=None,
children_field=None):
super(ParserTree, self).__init__(window, parent, attrs, screen,
super(ParserTree, self).__init__(parent, attrs, screen,
children_field=children_field)
self.treeview = None
@@ -113,7 +113,7 @@ class ParserTree(ParserInterface):
node_attrs[attr_name] = fields[fname].attrs[attr_name]
cell = CELLTYPES.get(node_attrs.get('widget',
fields[fname].attrs['type']))(fname, model_name,
treeview, self.window, node_attrs)
treeview, node_attrs)
treeview.cells[fname] = cell
renderer = cell.renderer
@@ -214,7 +214,7 @@ class ParserTree(ParserInterface):
dict_widget[i] = (fname, label, label_sum, digits)
elif node.localName == 'button':
#TODO add shortcut
cell = Button(treeview, self.window, self.screen, node_attrs)
cell = Button(treeview, self.screen, node_attrs)
button_list.append(cell)
renderer = cell.renderer
string = node_attrs.get('string', _('Unknown'))
@@ -259,14 +259,13 @@ class ParserTree(ParserInterface):
class Char(object):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Char, self).__init__()
self.field_name = field_name
self.model_name = model_name
self.attrs = attrs or {}
self.renderer = CellRendererText()
self.treeview = treeview
self.window = window
def setter(self, column, cell, store, iter):
record = store.get_value(iter, 0)
@@ -338,7 +337,8 @@ class Char(object):
def get_color(self, record):
return record.expr_eval(self.treeview.colors, check_load=False)
def open_remote(self, record, create, changed=False, text=None):
def open_remote(self, record, create, changed=False, text=None,
callback=None):
raise NotImplementedError
def get_textual_value(self, record):
@@ -347,17 +347,19 @@ class Char(object):
return record[self.field_name].get_client(record) or ''
def value_from_text(self, record, text):
return text
field = record[self.field_name]
field.set_client(record, text)
class Int(Char):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
super(Int, self).__init__(field_name, model_name, treeview, window,
attrs=attrs)
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Int, self).__init__(field_name, model_name, treeview,
attrs=attrs)
self.renderer = CellRendererInteger()
def value_from_text(self, record, text):
return int(text)
field = record[self.field_name]
field.set_client(record, int(text))
def get_textual_value(self, record):
return locale.format('%d',
@@ -365,9 +367,9 @@ class Int(Char):
class Boolean(Int):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
super(Boolean, self).__init__(field_name, model_name, treeview, window,
attrs=attrs)
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Boolean, self).__init__(field_name, model_name, treeview,
attrs=attrs)
self.renderer = CellRendererToggle()
self.renderer.connect('toggled', self._sig_toggled)
@@ -388,9 +390,9 @@ class Boolean(Int):
class Date(Char):
server_format = DT_FORMAT
def __init__(self, field_name, model_name, treeview, window, attrs=None):
super(Date, self).__init__(field_name, model_name, treeview, window,
attrs=attrs)
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Date, self).__init__(field_name, model_name, treeview,
attrs=attrs)
self.display_format = date_format()
self.renderer = CellRendererDate(self.display_format)
@@ -402,21 +404,22 @@ class Date(Char):
return common.datetime_strftime(date, self.display_format)
def value_from_text(self, record, text):
if not text:
return False
field = record[self.field_name]
date = False
try:
date = datetime.date(*time.strptime(text, self.display_format)[:3])
date = common.datetime_strftime(date, self.server_format)
except ValueError:
return False
return common.datetime_strftime(date, self.server_format)
date = False
field.set_client(record, date)
class Datetime(Date):
server_format = DHM_FORMAT
def __init__(self, field_name, model_name, treeview, window, attrs=None):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Datetime, self).__init__(field_name, model_name, treeview,
window, attrs=attrs)
attrs=attrs)
self.display_format = date_format() + ' ' + HM_FORMAT
self.renderer.format = self.display_format
@@ -430,22 +433,23 @@ class Datetime(Date):
return common.datetime_strftime(date, self.display_format)
def value_from_text(self, record, text):
if not text:
return False
field = record[self.field_name]
date = False
try:
date = datetime.datetime(*time.strptime(text,
self.display_format)[:6])
date = common.timezoned_date(date)
date = common.datetime_strftime(date, self.server_format)
except ValueError:
return False
date = common.timezoned_date(date)
return common.datetime_strftime(date, self.server_format)
date = False
field.set_client(record, date)
class Float(Char):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
super(Float, self).__init__(field_name, model_name, treeview, window,
attrs=attrs)
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Float, self).__init__(field_name, model_name, treeview,
attrs=attrs)
self.renderer = CellRendererFloat()
def setter(self, column, cell, store, iter):
@@ -468,17 +472,19 @@ class Float(Char):
record[self.field_name].get_client(record) or 0.0, True)
def value_from_text(self, record, text):
field = record[self.field_name]
try:
return locale.atof(text)
value = locale.atof(text)
except ValueError:
return 0.0
value = 0.0
field.set_client(record, value)
class FloatTime(Char):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(FloatTime, self).__init__(field_name, model_name, treeview,
window, attrs=attrs)
attrs=attrs)
self.conv = None
if attrs and attrs.get('float_time'):
self.conv = rpc.CONTEXT.get(attrs['float_time'])
@@ -488,7 +494,8 @@ class FloatTime(Char):
return common.float_time_to_text(val, self.conv)
def value_from_text(self, record, text):
return common.text_to_float_time(text, self.conv)
field = record[self.field_name]
field.set_client(record, common.text_to_float_time(text, self.conv))
class M2O(Char):
@@ -508,18 +515,23 @@ class M2O(Char):
dom = domain
args = ('model', relation, 'search', dom, 0, None, None,
context)
def callback(value):
field.set_client(record, value)
try:
ids = rpc.execute(*args)
except TrytonServerError, exception:
ids = common.process_exception(exception, self.window, *args)
ids = common.process_exception(exception, *args)
if not ids:
return '???'
callback('???')
return
if len(ids) != 1:
return self.search_remote(relation, ids,
domain=domain, context=context)[0]
return ids[0]
self.search_remote(record, relation, ids, domain=domain,
context=context)
return
callback(ids[0])
def open_remote(self, record, create=True, changed=False, text=None):
def open_remote(self, record, create=True, changed=False, text=None,
callback=None):
field = record.group.fields[self.field_name]
relation = field.attrs['relation']
@@ -538,54 +550,61 @@ class M2O(Char):
try:
ids = rpc.execute(*args)
except TrytonServerError, exception:
ids = common.process_exception(exception, self.window, *args)
ids = common.process_exception(exception, *args)
if not ids:
return False, False
field.set_client(record, False)
if callback:
callback()
return
if len(ids) == 1:
return True, ids[0]
searched = self.search_remote(relation, ids, domain=domain,
context=context)
if searched[0]:
return True, searched
return False, False
screen = Screen(relation, self.window, domain=domain, context=context,
mode=['form'])
field.set_client(record, ids[0])
if callback:
callback()
return
self.search_remote(record, relation, ids, domain=domain,
context=context, callback=callback)
return
screen = Screen(relation, domain=domain, context=context,
mode=['form'])
def open_callback(result):
if result and screen.save_current():
value = (screen.current_record.id,
screen.current_record.rec_name())
field.set_client(record, value)
if callback:
callback()
if obj_id:
screen.load([obj_id])
win = WinForm(screen, self.window)
WinForm(screen, open_callback)
else:
win = WinForm(screen, self.window, new=True)
value = False
if win.run():
if screen.save_current():
value = (screen.current_record.id,
screen.current_record.rec_name())
win.destroy()
if value:
return True, value
else:
return False, False
WinForm(screen, open_callback, new=True)
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:
args = ('model', relation, 'read', found[0], ['rec_name'],
context)
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, *args)
if res:
value = (found[0], res['rec_name'])
field.set_client(record, value)
if callback:
callback()
WinSearch(relation, search_callback, sel_multi=False, ids=ids,
context=context, domain=domain)
def search_remote(self, relation, ids=None, domain=None, context=None):
win = WinSearch(relation, sel_multi=False, ids=ids, context=context,
domain=domain, parent=self.window)
found = win.run()
if found:
args = ('model', relation, 'read', found[0], ['rec_name'],
context)
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window, *args)
if not res:
return False, None
return found[0], res['rec_name']
else:
return False, None
class O2O(M2O):
pass
class UnsettableColumn(Exception):
def __init__(self):
@@ -605,19 +624,20 @@ class O2M(Char):
def value_from_text(self, record, text):
pass
def open_remote(self, record, create=True, changed=False, text=None):
def open_remote(self, record, create=True, changed=False, text=None,
callback=None):
group = record.value[self.field_name]
field = record.group.fields[self.field_name]
relation = field.attrs['relation']
context = field.context_get(record)
screen = Screen(relation, self.window, mode=['tree', 'form'],
exclude_field=field.attrs.get('relation_field'))
screen = Screen(relation, mode=['tree', 'form'],
exclude_field=field.attrs.get('relation_field'))
screen.group = group
win = WinForm(screen, self.window, view_type='tree', context=context)
win.run()
win.destroy()
return False, False
def open_callback(result):
if callback:
callback()
WinForm(screen, open_callback, view_type='tree', context=context)
class M2M(Char):
@@ -631,11 +651,12 @@ class M2M(Char):
get_client(record))) + ' )'
def value_from_text(self, record, text):
if not text:
return []
if not (text[0] != '('):
return record[self.field_name].get(record)
field = record[self.field_name]
if not text:
field.set_client(record, [])
return
if not (text[0] != '('):
return
relation = field.attrs['relation']
domain = field.domain_get(record)
context = field.context_get(record)
@@ -649,15 +670,18 @@ class M2M(Char):
try:
ids = rpc.execute(*args)
except TrytonServerError, exception:
ids = common.process_exception(exception, self.window, *args)
ids = common.process_exception(exception, *args)
if ids is False:
return []
win = WinSearch(relation, sel_multi=True, ids=ids, context=context,
domain=domain, parent=self.window)
found = win.run()
return found or []
field.set_client(record, [])
return
def callback(result):
field.set_client(record, result or [])
WinSearch(relation, callback, sel_multi=True, ids=ids, context=context,
domain=domain)
return
def open_remote(self, record, create=True, changed=False, text=None):
def open_remote(self, record, create=True, changed=False, text=None,
callback=None):
field = record[self.field_name]
relation = field.attrs['relation']
context = field.context_get(record)
@@ -669,20 +693,26 @@ class M2M(Char):
try:
ids = rpc.execute(*args)
except TrytonServerError, exception:
ids = common.process_exception(exception, self.window, *args)
ids = common.process_exception(exception, *args)
if ids is False:
return False, None
field.set_client(record, False)
if callback:
callback()
if ids and len(ids)==1:
return True, ids
field.set_client(record, ids)
if callback:
callback()
return
else:
ids = [x.id for x in field.get_client(record)]
win = WinSearch(relation, sel_multi=True, ids=ids, context=context,
domain=domain, parent=self.window)
found = win.run()
if found:
return True, found
else:
return False, None
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)
class Selection(Char):
@@ -698,8 +728,7 @@ class Selection(Char):
try:
selection = rpc.execute(*args)
except TrytonServerError, exception:
selection = (common.process_exception(exception, self.window,
args) or [])
selection = (common.process_exception(exception, args) or [])
self.selection = selection[:]
if self.attrs.get('sort', True):
selection.sort(key=operator.itemgetter(1))
@@ -726,7 +755,8 @@ class Selection(Char):
return dict(self.selection).get(value, '')
def value_from_text(self, record, text):
return self._selection.get(text, False), text
field = record[self.field_name]
field.set_client(record, self._selection.get(text, False))
def editing_started(self, cell, editable, path):
store = self.treeview.get_model()
@@ -758,7 +788,7 @@ class Selection(Char):
try:
result = rpc.execute(*args)
except TrytonServerError, exception:
result = common.process_exception(exception, self.window, *args)
result = common.process_exception(exception, *args)
if isinstance(result, list):
selection = [(x['id'], x['rec_name']) for x in result]
@@ -775,9 +805,9 @@ class Selection(Char):
class Reference(Char):
def __init__(self, field_name, model_name, treeview, window, attrs=None):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(Reference, self).__init__(field_name, model_name, treeview,
window, attrs=attrs)
attrs=attrs)
self._selection = {}
selection = attrs.get('selection', [])
if not isinstance(selection, (list, tuple)):
@@ -785,7 +815,7 @@ class Reference(Char):
selection = rpc.execute('model',
model_name, selection, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
selection = []
selection.sort(key=operator.itemgetter(1))
for i, j in selection:
@@ -804,8 +834,7 @@ class Reference(Char):
try:
res = rpc.execute(*args)
except TrytonServerError, exception:
res = common.process_exception(exception, self.window,
*args)
res = common.process_exception(exception, *args)
if not res:
name = '???'
else:
@@ -826,7 +855,7 @@ class ProgressBar(object):
'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM,
}
def __init__(self, field_name, model_name, treeview, window, attrs=None):
def __init__(self, field_name, model_name, treeview, attrs=None):
super(ProgressBar, self).__init__()
self.field_name = field_name
self.model_name = model_name
@@ -836,7 +865,6 @@ class ProgressBar(object):
'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT)
self.renderer.set_property('orientation', orientation)
self.treeview = treeview
self.window = window
def setter(self, column, cell, store, iter):
record = store.get_value(iter, 0)
@@ -849,24 +877,25 @@ class ProgressBar(object):
text = locale.format('%.' + str(digit) + 'f', value, True)
cell.set_property('text', text + '%')
def open_remote(self, record, create, changed=False, text=None):
def open_remote(self, record, create, changed=False, text=None,
callback=None):
raise NotImplementedError
def get_textual_value(self, record):
return record[self.field_name].get_client(record) or ''
def value_from_text(self, record, text):
return float(text)
field = record[self.field_name]
field.set_client(record, float(text))
class Button(object):
def __init__(self, treeview, window, screen, attrs=None):
def __init__(self, treeview, screen, attrs=None):
super(Button, self).__init__()
self.attrs = attrs or {}
self.renderer = CellRendererButton(attrs.get('string', _('Unknown')))
self.treeview = treeview
self.window = window
self.screen = screen
self.renderer.connect('clicked', self.button_clicked)
@@ -887,7 +916,7 @@ class Button(object):
obj_id = self.screen.save_current()
if obj_id:
if not self.attrs.get('confirm', False) or \
common.sur(self.attrs['confirm'], self.window):
common.sur(self.attrs['confirm']):
button_type = self.attrs.get('type', 'workflow')
ctx = rpc.CONTEXT.copy()
ctx.update(record.context_get())
@@ -898,14 +927,14 @@ class Button(object):
try:
rpc.execute(*args)
except TrytonServerError, exception:
common.process_exception(exception, self.window, *args)
common.process_exception(exception, *args)
elif button_type == 'object':
args = ('model', self.screen.model_name,
self.attrs['name'], [obj_id], ctx)
try:
rpc.execute(*args)
except TrytonServerError, exception:
common.process_exception(exception, self.window, *args)
common.process_exception(exception, *args)
elif button_type == 'action':
action_id = None
args = ('model', 'ir.action', 'get_action_id',
@@ -913,14 +942,13 @@ class Button(object):
try:
action_id = rpc.execute(*args)
except TrytonServerError, exception:
action_id = common.process_exception(exception,
self.window, *args)
action_id = common.process_exception(exception, *args)
if action_id:
Action.execute(action_id, {
'model': self.screen.model_name,
'id': obj_id,
'ids': [obj_id],
}, self.window, context=ctx)
}, context=ctx)
else:
raise TrytonError('Unallowed button type')
self.screen.reload(written=True)
@@ -114,6 +114,3 @@ class ScreenContainer(object):
self.viewport.remove(self.viewport.get_child())
self.viewport.add(widget)
self.viewport.show_all()
def size_get(self):
return self.viewport.get_child().size_request()
@@ -34,13 +34,13 @@ class WidgetParse(ParserInterface):
if not node.nodeType == node.ELEMENT_NODE:
continue
if node.localName in PARSERS:
widget = PARSERS[node.localName](self.window, self.parent,
self.attrs, screen, children_field)
widget = PARSERS[node.localName](self.parent, self.attrs,
screen, children_field)
wid, child, buttons, on_write, notebooks, cursor_widget = \
widget.parse(screen.model_name, node, fields)
screen.set_on_write(on_write)
res = PARSERS2[node.localName](self.window, screen, wid, child,
buttons, notebooks, cursor_widget, children_field)
res = PARSERS2[node.localName](screen, wid, child, buttons,
notebooks, cursor_widget, children_field)
res.title = widget.title
widget = res
break
@@ -8,6 +8,7 @@ import locale
from interface import Interface
from tryton.common import DT_FORMAT, DHM_FORMAT, TRYTON_ICON
from tryton.common import date_widget, Tooltips, datetime_strftime
from tryton.common import get_toplevel_window
from tryton.translate import date_format
import gobject
@@ -16,10 +17,10 @@ _ = gettext.gettext
class Calendar(Interface):
def __init__(self, name, parent, attrs=None, context=None,
def __init__(self, name, attrs=None, context=None,
on_change=None):
super(Calendar, self).__init__(name, parent, attrs=attrs,
context=context, on_change=on_change)
super(Calendar, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
tooltips = Tooltips()
self.widget = gtk.HBox(spacing=3)
@@ -54,8 +55,7 @@ class Calendar(Interface):
self.eb1 = gtk.EventBox()
tooltips.set_tip(self.eb1, _('Open the calendar'))
self.eb1.set_events(gtk.gdk.BUTTON_PRESS)
self.eb1.connect('button_press_event', self.cal_open, self.entry1,
parent)
self.eb1.connect('button_press_event', self.cal_open, self.entry1)
img = gtk.Image()
img.set_from_stock('tryton-find', gtk.ICON_SIZE_BUTTON)
img.set_alignment(0.5, 0.5)
@@ -76,8 +76,7 @@ class Calendar(Interface):
self.eb2 = gtk.EventBox()
tooltips.set_tip(self.eb2, _('Open the calendar'))
self.eb2.set_events(gtk.gdk.BUTTON_PRESS)
self.eb2.connect('button_press_event', self.cal_open, self.entry2,
parent)
self.eb2.connect('button_press_event', self.cal_open, self.entry2)
img = gtk.Image()
img.set_from_stock('tryton-find', gtk.ICON_SIZE_BUTTON)
img.set_alignment(0.5, 0.5)
@@ -161,7 +160,8 @@ class Calendar(Interface):
value = property(_value_get, _value_set)
def cal_open(self, widget, event, dest, parent=None):
def cal_open(self, widget, event, dest):
parent = get_toplevel_window()
win = gtk.Dialog(_('Date selection'), parent,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
@@ -193,6 +193,7 @@ class Calendar(Interface):
dest.set_text(datetime_strftime(date, self.format))
self.on_change()
win.destroy()
parent.present()
def clear(self):
self.value = ('=', '')
@@ -10,10 +10,9 @@ _ = gettext.gettext
class Char(Interface):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(Char, self).__init__(name, parent, attrs=attrs, context=context,
on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(Char, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
self.widget = gtk.HBox()
@@ -9,10 +9,9 @@ _ = gettext.gettext
class CheckBox(Interface):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(CheckBox, self).__init__(name, parent, attrs=attrs,
context=context, on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(CheckBox, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
self.widget = gtk.combo_box_entry_new_text()
self.widget.child.set_editable(True)
@@ -10,10 +10,9 @@ _ = gettext.gettext
class Float(Integer):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(Float, self).__init__(name, parent, attrs=attrs, context=context,
on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(Float, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
if isinstance(self.attrs.get('digits'), str):
self.digits = (16, 2)
else:
@@ -69,10 +69,8 @@ class _container(object):
class Parse(object):
def __init__(self, parent, fields, model='', context=None,
on_change=None):
def __init__(self, fields, model='', context=None, on_change=None):
self.fields = fields
self.parent = parent
self.model = model
self.col = CONFIG['client.modepda'] and 1 or 6
self.focusable = None
@@ -111,7 +109,7 @@ class Parse(object):
self.fields[str(attrs['name'])]['model']=self.model
if ftype not in WIDGETS_TYPE:
return False
widget_act = WIDGETS_TYPE[ftype][0](str(attrs['name']), self.parent,
widget_act = WIDGETS_TYPE[ftype][0](str(attrs['name']),
attrs=self.fields[attrs['name']], context=self.context,
on_change=self.on_change)
if 'string' in self.fields[str(attrs['name'])]:
@@ -195,15 +193,13 @@ class Parse(object):
class Form(object):
def __init__(self, view, model=None, parent=None, domain=None,
call=None, context=None):
def __init__(self, view, model=None, domain=None, call=None, context=None):
if domain is None:
domain = []
if context is None:
context = {}
parser = Parse(parent, view['fields'], model=model, context=context,
on_change=self.on_change)
self.parent = parent
parser = Parse(view['fields'], model=model, context=context,
on_change=self.on_change)
self.fields = view['fields']
self.model = model
self.parser = parser
@@ -11,10 +11,9 @@ _ = gettext.gettext
class Integer(Interface):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(Integer, self).__init__(name, parent, attrs=attrs,
context=context, on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(Integer, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
self.widget = gtk.HBox(spacing=3)
self.liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
@@ -8,11 +8,10 @@ _ = gettext.gettext
class Interface(object):
"Interface for search widget"
def __init__(self, name, parent, attrs=None, context=None, on_change=None):
def __init__(self, name, attrs=None, context=None, on_change=None):
if attrs is None:
attrs = {}
self._value = None
self.parent = parent
self.name = name
self.model = attrs.get('model', None)
self.attrs = attrs or {}
@@ -13,10 +13,9 @@ _ = gettext.gettext
class Reference(Interface):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(Reference, self).__init__(name, parent, attrs=attrs,
context=context, on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(Reference, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
self.widget = gtk.HBox()
@@ -49,7 +48,7 @@ class Reference(Interface):
0, None, None, ['rec_name'], rpc.CONTEXT)
selection = [(x['id'], x['rec_name']) for x in result]
except TrytonServerError, exception:
common.process_exception(exception, parent)
common.process_exception(exception)
selection = []
else:
if not isinstance(selection, (list, tuple)):
@@ -57,7 +56,7 @@ class Reference(Interface):
selection = rpc.execute('model',
self.attrs['model'], selection, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, parent)
common.process_exception(exception)
selection = []
selection.sort(lambda x, y: cmp(x[1], y[1]))
self.attrs['selection'] = selection
@@ -14,10 +14,9 @@ _ = gettext.gettext
class Selection(Interface):
def __init__(self, name, parent, attrs=None, context=None,
on_change=None):
super(Selection, self).__init__(name, parent, attrs=attrs,
context=context, on_change=on_change)
def __init__(self, name, attrs=None, context=None, on_change=None):
super(Selection, self).__init__(name, attrs=attrs, context=context,
on_change=on_change)
self.widget = gtk.HBox()
@@ -53,7 +52,7 @@ class Selection(Interface):
['rec_name'], rpc.CONTEXT)
selection = [(x['id'], x['rec_name']) for x in result]
except TrytonServerError, exception:
common.process_exception(exception, parent)
common.process_exception(exception)
selection = []
else:
if not isinstance(selection, (list, tuple)):
@@ -61,7 +60,7 @@ class Selection(Interface):
selection = rpc.execute('model',
self.attrs['model'], selection, rpc.CONTEXT)
except TrytonServerError, exception:
common.process_exception(exception, parent)
common.process_exception(exception)
selection = []
selection.sort(key=operator.itemgetter(1))
self.attrs['selection'] = selection
+12 -17
View File
@@ -18,10 +18,11 @@ _ = gettext.gettext
class WinExport(object):
"Window export"
def __init__(self, model, ids, parent, context=None):
def __init__(self, model, ids, context=None):
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(
title= _("Export to CSV"),
parent=parent,
parent=self.parent,
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
| gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.set_icon(TRYTON_ICON)
@@ -162,8 +163,6 @@ class WinExport(object):
self.fields_data = {}
self.context = context
self.parent = parent
self.view1 = gtk.TreeView()
self.view1.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.view1.connect('row-expanded', self.on_row_expanded)
@@ -241,7 +240,7 @@ class WinExport(object):
try:
return rpc.execute(*args)
except TrytonServerError, exception:
return common.process_exception(exception, self.parent, *args)
return common.process_exception(exception, *args)
def on_row_expanded(self, treeview, iter, path):
child = self.model1.iter_children(iter)
@@ -279,15 +278,14 @@ class WinExport(object):
try:
export_ids = rpc.execute(*args)
except TrytonServerError, exception:
export_ids = common.process_exception(exception, self.parent,
*args)
export_ids = common.process_exception(exception, *args)
if not export_ids:
return
args = ('model', 'ir.export', 'read', export_ids, None, rpc.CONTEXT)
try:
exports = rpc.execute(*args)
except TrytonServerError, exception:
exports = common.process_exception(exception, self.parent, *args)
exports = common.process_exception(exception, *args)
if not exports:
return
args = ('model', 'ir.export.line', 'read',
@@ -296,7 +294,7 @@ class WinExport(object):
try:
lines = rpc.execute(*args)
except TrytonServerError, exception:
lines = common.process_exception(exception, self.parent, *args)
lines = common.process_exception(exception, *args)
if not lines:
return
id2lines = {}
@@ -310,7 +308,7 @@ class WinExport(object):
self.pref_export.set_model(self.predef_model)
def add_predef(self, widget):
name = common.ask(_('What is the name of this export?'), self.parent)
name = common.ask(_('What is the name of this export?'))
if not name:
return
iter = self.model2.get_iter_root()
@@ -398,10 +396,9 @@ class WinExport(object):
self.export_csv(fname, fields2, result,
self.wid_write_field_names.get_active(), popup=False)
os.close(fileno)
common.file_open(fname, 'csv', self.parent)
common.file_open(fname, 'csv')
else:
fname = common.file_selection(_('Save As...'),
parent=self.parent,
action=gtk.FILE_CHOOSER_ACTION_SAVE)
if fname:
self.export_csv(fname, fields2, result,
@@ -429,15 +426,13 @@ class WinExport(object):
file_p.close()
if popup:
if len(result) == 1:
common.message(_('%d record saved!') % len(result),
self.parent)
common.message(_('%d record saved!') % len(result))
else:
common.message(_('%d records saved!') % len(result),
self.parent)
common.message(_('%d records saved!') % len(result))
return True
except IOError, exception:
common.warning(_("Operation failed!\nError message:\n%s") \
% (exception.args[0],), self.parent, _('Error'))
% (exception.args[0],), _('Error'))
return False
def datas_read(self, ids, model, fields, context=None):
+52 -47
View File
@@ -7,18 +7,19 @@ import gtk
import pango
import gettext
from tryton.exceptions import TrytonServerError
from tryton.gui.window.nomodal import NoModal
_ = gettext.gettext
class WinForm(object):
class WinForm(NoModal):
"Form window"
def __init__(self, screen, parent, view_type='form', new=False,
many=False, context=None):
self.parent = parent
def __init__(self, screen, callback, view_type='form',
new=False, many=False, context=None):
NoModal.__init__(self)
self.screen = screen
self.callback = callback
self.context = context
self.prev_view = self.screen.current_view
self.screen.screen_container.alternate_view = True
@@ -32,13 +33,12 @@ class WinForm(object):
self.screen.switch_view(view_type=view_type, context=context)
if new and not switch_new:
self.screen.new(context=self.context)
self.win = gtk.Dialog(_('Link'), parent,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
self.win.set_property('default-width', 760)
self.win.set_property('default-height', 500)
self.win = gtk.Dialog(_('Link'), self.parent,
gtk.DIALOG_DESTROY_WITH_PARENT)
self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(False)
self.win.connect('response', self.response)
self.accel_group = gtk.AccelGroup()
self.win.add_accel_group(self.accel_group)
@@ -190,23 +190,19 @@ class WinForm(object):
scroll.add(self.screen.screen_container.alternate_viewport)
width, height = self.screen.current_view.widget.size_request()
scroll.set_size_request(width, height + 30)
parent_width, parent_height = parent.get_size()
win_width, win_height = self.win.get_size()
self.widget_width = min(parent_width - 20, max(win_width, width + 20))
self.widget_height = min(parent_height - 60, height + win_height + 20)
self.win.set_default_size(self.widget_width, self.widget_height)
sensible_allocation = self.sensible_widget.get_allocation()
self.win.set_default_size(int(sensible_allocation.width * 0.9),
int(sensible_allocation.height * 0.9))
if view_type == 'tree':
self.screen.signal_connect(self, 'record-message', self._sig_label)
self.screen.screen_container.alternate_viewport.connect(
'key-press-event', self.on_keypress)
self.register()
self.win.show()
self.prev_window = self.screen.window
self.screen.window = self.win
common.center_window(self.win, self.parent, self.sensible_widget)
self.screen.display()
self.screen.current_view.set_cursor()
@@ -265,22 +261,25 @@ class WinForm(object):
ids = rpc.execute('model', self.attrs['relation'], 'search', dom,
0, CONFIG['client.limit'], None, context)
except TrytonServerError, exception:
common.process_exception(exception, self.window)
common.process_exception(exception)
return False
if len(ids) != 1:
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
context=context, domain=domain, parent=self.window,
views_preload=self.attrs.get('views', {}))
ids = win.run()
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
self.wid_text.set_text('')
def callback(ids):
res_id = None
if ids:
res_id = ids[0]
self.screen.load(ids, modified=True)
self.screen.display(res_id=res_id)
if self.screen.current_view:
self.screen.current_view.set_cursor()
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', {}))
else:
callback(ids)
def _sig_label(self, screen, signal_data):
name = '_'
@@ -289,30 +288,30 @@ class WinForm(object):
line = '(%s/%s)' % (name, signal_data[1])
self.label.set_text(line)
def run(self):
def response(self, win, response_id):
validate = False
cancel_responses = (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT)
while not validate:
response = self.win.run()
self.screen.current_view.set_value()
if (response in cancel_responses
or self.screen.current_record is None):
break
self.screen.current_view.set_value()
if (response_id not in cancel_responses
and self.screen.current_record is not None):
validate = self.screen.current_record.validate(
self.screen.current_view.get_fields())
if not validate:
self.screen.current_view.set_cursor()
self.screen.display()
continue
if response == gtk.RESPONSE_ACCEPT:
return
if response_id == gtk.RESPONSE_ACCEPT:
self.new()
validate = False
return
if (self.but_cancel
and self.screen.current_record
and response in cancel_responses):
and response_id in cancel_responses):
self.screen.group.remove(self.screen.current_record, remove=True)
return False
return response not in cancel_responses
result = False
else:
result = response_id not in cancel_responses
self.destroy()
self.callback(result)
def new(self):
self.screen.new(context=self.context)
@@ -326,6 +325,12 @@ class WinForm(object):
viewport.remove(viewport.get_child())
self.screen.switch_view(view_type=self.prev_view.view_type)
self.screen.signal_unconnect(self)
self.screen.window = self.prev_window
self.win.destroy()
self.parent.present()
NoModal.destroy(self)
def show(self):
self.win.show()
common.center_window(self.win, self.parent, self.sensible_widget)
def hide(self):
self.win.hide()
+6 -8
View File
@@ -15,9 +15,10 @@ _ = gettext.gettext
class WinImport(object):
"Window import"
def __init__(self, model, parent):
def __init__(self, model):
self.parent = common.get_toplevel_window()
self.dialog = gtk.Dialog(
title=_("Import from CSV"), parent=parent,
title=_("Import from 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)
@@ -170,7 +171,6 @@ class WinImport(object):
self.model = model
self.fields_data = {}
self.parent = parent
self.dialog.show_all()
self.import_csv_file.set_current_folder(CONFIG['client.default_path'])
@@ -360,16 +360,14 @@ class WinImport(object):
return False
if res[0] >= 0:
if res[0] == 1:
common.message(_('%d record imported!') % (res[0],),
self.parent)
common.message(_('%d record imported!') % res[0])
else:
common.message(_('%d records imported!') % (res[0],),
self.parent)
common.message(_('%d records imported!') % res[0])
else:
buf = ''
for key, val in res[1].items():
buf += ('\t%s: %s\n' % (str(key), str(val)))
common.error(_('Importation Error!'), self.parent,
common.error(_('Importation Error!'),
_('Error trying to import this record:\n' \
'%s\nError Message:\n%s\n\n%s') % (buf, res[2], res[3]))
return True
+39 -33
View File
@@ -6,28 +6,30 @@ import tryton.rpc as rpc
from tryton.gui.window.view_form.screen import Screen
import tryton.gui.window.view_form.widget_search as widget_search
from tryton.config import TRYTON_ICON
import tryton.common as common
from tryton.gui.window.win_form import WinForm
from tryton.gui.window.nomodal import NoModal
_ = gettext.gettext
class WinSearch(object):
class WinSearch(NoModal):
def __init__(self, model, sel_multi=True, ids=None, context=None,
domain=None, parent=None, views_preload=None):
def __init__(self, model, callback, sel_multi=True, ids=None, context=None,
domain=None, views_preload=None):
NoModal.__init__(self)
if views_preload is None:
views_preload = {}
self.domain = domain or []
self.context = context or {}
self.sel_multi = sel_multi
self.parent = parent
self.callback = callback
self.win = gtk.Dialog(_('Search'), self.parent,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
gtk.DIALOG_DESTROY_WITH_PARENT)
self.win.set_icon(TRYTON_ICON)
self.win.set_has_separator(True)
self.win.set_default_response(gtk.RESPONSE_APPLY)
self.win.connect('response', self.response)
self.accel_group = gtk.AccelGroup()
self.win.add_accel_group(self.accel_group)
@@ -47,9 +49,9 @@ class WinSearch(object):
scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.win.vbox.pack_start(scrollwindow, expand=True, fill=True)
self.screen = Screen(model, self.win, domain=domain,
mode=['tree'], context=context,
views_preload=views_preload, row_activate=self.sig_activate)
self.screen = Screen(model, domain=domain, mode=['tree'],
context=context, views_preload=views_preload,
row_activate=self.sig_activate)
self.view = self.screen.current_view
self.view.unset_editable()
sel = self.view.widget_tree.get_selection()
@@ -74,6 +76,9 @@ class WinSearch(object):
self.win.set_size_request(700, 500)
self.register()
self.win.show()
def sig_activate(self, *args):
self.view.widget_tree.emit_stop_by_name('row_activated')
if not self.sel_multi:
@@ -86,33 +91,34 @@ class WinSearch(object):
return False
def destroy(self):
self.parent.present()
self.screen.destroy()
self.win.destroy()
NoModal.destroy(self)
def run(self):
end = False
while not end:
button = self.win.run()
if button == gtk.RESPONSE_OK:
def show(self):
self.win.show()
def hide(self):
self.win.hide()
def response(self, win, response_id):
res = None
if response_id == gtk.RESPONSE_OK:
res = self.screen.sel_ids_get()
elif response_id == gtk.RESPONSE_APPLY:
if not self.screen.search_filter():
res = self.screen.sel_ids_get()
end = True
elif button == gtk.RESPONSE_APPLY:
end = not self.screen.search_filter()
if end:
res = self.screen.sel_ids_get()
elif button == gtk.RESPONSE_ACCEPT:
res = None
screen = Screen(self.model_name, self.win, domain=self.domain,
context=self.context, mode=['form'])
win = WinForm(screen, self.win, new=True)
if win.run():
if screen.save_current():
res = [screen.current_record.id]
win.destroy()
end = True
else:
res = None
end = True
return
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]
self.destroy()
self.callback(res)
WinForm(screen, callback, new=True)
return
self.destroy()
return res
return self.callback(res)
+18 -15
View File
@@ -21,7 +21,7 @@ class Window(object):
Window.allow_similar = True
@staticmethod
def create(view_ids, model, res_id=False, domain=None, window=None,
def create(view_ids, model, res_id=False, domain=None,
context=None, mode=None, name=False, limit=None,
auto_refresh=False, search_value=None, icon=None):
from tryton.gui import Main
@@ -30,26 +30,29 @@ class Window(object):
if model:
from form import Form
win = Form(model, window, res_id, domain, mode=mode,
view_ids=(view_ids or []), context=context, name=name,
limit=limit, auto_refresh=auto_refresh,
search_value=search_value)
win = Form(model, res_id, domain, mode=mode,
view_ids=(view_ids or []), context=context, name=name,
limit=limit, auto_refresh=auto_refresh,
search_value=search_value)
else:
from board import Board
win = Board(model, window, view_ids and view_ids[0] or None,
context=context, name=name, auto_refresh=auto_refresh)
win = Board(model, view_ids and view_ids[0] or None,
context=context, name=name, auto_refresh=auto_refresh)
win.icon = icon
Main.get_main().win_add(win, hide_current=Window.hide_current,
allow_similar=Window.allow_similar)
@staticmethod
def create_wizard(action, datas, parent, state='init', direct_print=False,
email_print=False, email=None, name=False, context=None,
icon=None):
def create_wizard(action, data, state='init', direct_print=False,
email_print=False, email=None, name=False, context=None, icon=None,
window=False):
from tryton.gui import Main
from wizard import Wizard
win = Wizard(parent, name=name)
win.icon = icon
Main.get_main().win_add(win, Window.hide_current)
win.run(action, datas, state=state, direct_print=direct_print,
from wizard import WizardForm, WizardDialog
if window:
win = WizardForm(name=name)
win.icon = icon
Main.get_main().win_add(win, Window.hide_current)
else:
win = WizardDialog(name=name)
win.run(action, data, state=state, direct_print=direct_print,
email_print=email_print, email=email, context=context)
+223 -95
View File
@@ -2,23 +2,24 @@
#this repository contains the full copyright notices and license terms.
import gtk
import pango
import gettext
from tryton.signal_event import SignalEvent
import tryton.rpc as rpc
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
_ = gettext.gettext
class Wizard(SignalEvent):
"Wizard"
class Wizard(object):
def __init__(self, window, name=False):
def __init__(self, name=False):
super(Wizard, self).__init__()
self.window = window
self.widget = gtk.VBox(spacing=3)
self.toolbar_box = gtk.HBox()
self.widget.pack_start(self.toolbar_box, False, True)
self.toolbar_box = None
self.widget.show()
self.name = name or ''
self.model = ''
@@ -30,15 +31,8 @@ class Wizard(SignalEvent):
self.email = False
self.context = None
self.states = {}
self.handlers = {
'but_close': self.sig_close
}
def sig_close(self):
if 'end' in self.states:
self.states['end'].clicked()
return self.state == 'end'
self.response2state = {}
self.__processing = False
def run(self, action, datas, state='init', direct_print=False,
email_print=False, email=None, context=None):
@@ -55,7 +49,7 @@ class Wizard(SignalEvent):
try:
self.wiz_id = rpc.execute(*args)
except TrytonServerError, exception:
self.wiz_id = common.process_exception(exception, self.window, *args)
self.wiz_id = common.process_exception(exception, *args)
if not self.wiz_id:
return
self.process()
@@ -63,66 +57,72 @@ class Wizard(SignalEvent):
def process(self):
from tryton.action import Action
res = {}
while self.state != 'end':
ctx = self.context.copy()
ctx.update(rpc.CONTEXT)
ctx['active_id'] = self.datas.get('id')
ctx['active_ids'] = self.datas.get('ids')
rpcprogress = common.RPCProgress('execute', ('wizard',
self.action, 'execute', self.wiz_id, self.datas, self.state, ctx),
self.window)
try:
res = rpcprogress.run()
except TrytonServerError, exception:
common.process_exception(exception, self.window)
break
if not res:
self.end()
return
self.clean()
if 'datas' in res:
self.datas['form'] = res['datas']
elif res['type'] == 'form':
self.datas['form'] = {}
if res['type'] == 'form':
self.update(res, res['state'], res['object'], context=ctx)
self.screen.current_record.set_default(self.datas['form'])
break
elif res['type'] == 'action':
self.state = res['state']
if self.state == 'end':
if self.__processing:
return
try:
self.__processing = True
while self.state != 'end':
ctx = self.context.copy()
ctx.update(rpc.CONTEXT)
ctx['active_id'] = self.datas.get('id')
ctx['active_ids'] = self.datas.get('ids')
rpcprogress = common.RPCProgress('execute', ('wizard',
self.action, 'execute', self.wiz_id, self.datas,
self.state, ctx))
try:
res = rpcprogress.run()
except TrytonServerError, exception:
common.process_exception(exception)
self.end()
break
if not res:
self.end()
Action._exec_action(res['action'], self.window, self.datas,
context=ctx)
if self.state == 'end':
return
elif res['type'] == 'print':
self.datas['report_id'] = res.get('report_id', False)
if res.get('get_id_from_action', False):
backup_ids = datas['ids']
self.datas['ids'] = self.datas['form']['ids']
Action.exec_report(res['report'], self.datas, self.window,
direct_print=self.direct_print,
email_print=self.email_print, email=self.email,
context=ctx)
self.datas['ids'] = backup_ids
else:
Action.exec_report(res['report'], self.datas, self.window,
direct_print=self.direct_print,
email_print=self.email_print, email=self.email,
context=ctx)
self.state = res['state']
elif res['type'] == 'state':
self.state = res['state']
if self.state == 'end':
self.end()
if 'datas' in res:
self.datas['form'] = res['datas']
elif res['type'] == 'form':
self.datas['form'] = {}
if res['type'] == 'form':
self.clean()
self.update(res, res['state'], res['object'], context=ctx)
self.screen.current_record.set_default(self.datas['form'])
break
elif res['type'] == 'action':
self.state = res['state']
sensitive_widget = self.widget.get_toplevel()
if self.state == 'end':
self.end()
Action._exec_action(res['action'], self.datas, context=ctx)
if self.state == 'end' or (
res['action']['type'] == 'ir.action.wizard'
and not sensitive_widget.props.sensitive):
return
elif res['type'] == 'print':
self.datas['report_id'] = res.get('report_id', False)
if res.get('get_id_from_action', False):
backup_ids = datas['ids']
self.datas['ids'] = self.datas['form']['ids']
Action.exec_report(res['report'], self.datas,
direct_print=self.direct_print,
email_print=self.email_print, email=self.email,
context=ctx)
self.datas['ids'] = backup_ids
else:
Action.exec_report(res['report'], self.datas,
direct_print=self.direct_print,
email_print=self.email_print, email=self.email,
context=ctx)
self.state = res['state']
elif res['type'] == 'state':
self.state = res['state']
if self.state == 'end':
self.end()
finally:
self.__processing = False
def destroy(self):
if self.toolbar_box.get_children():
toolbar = self.toolbar_box.get_children()[0]
self.toolbar_box.remove(toolbar)
if hasattr(self, 'screen'):
self.screen.signal_unconnect(self)
self.screen.destroy()
@@ -137,14 +137,14 @@ class Wizard(SignalEvent):
rpc.context_reload()
except TrytonServerError:
pass
Main.get_main()._win_del(self.widget)
def clean(self):
for widget in self.widget.get_children():
self.widget.remove(widget)
self.states = {}
def sig_clicked(self, widget, state):
def response(self, widget, response):
state = self.response2state.get(response, 'end')
self.screen.current_view.set_value()
if not self.screen.current_record.validate() \
and state != 'end':
@@ -154,26 +154,26 @@ class Wizard(SignalEvent):
self.state = state
self.process()
def update(self, view, state, obj_name, context=None):
def _get_button(self, state):
button = gtk.Button()
button.set_use_underline(True)
button.set_label('_' + state[1])
if len(state) >= 3:
common.ICONFACTORY.register_icon(state[2])
icon = gtk.Image()
icon.set_from_stock(state[2], gtk.ICON_SIZE_BUTTON)
button.set_image(icon)
self.states[state[0]] = button
response = len(self.states)
self.response2state[response] = state[0]
button.show()
return button
def update(self, view, states, obj_name, context=None):
self.model = obj_name
hbuttonbox = gtk.HButtonBox()
hbuttonbox.set_spacing(5)
hbuttonbox.set_layout(gtk.BUTTONBOX_END)
hbuttonbox.show()
for i in state:
but = gtk.Button()
but.set_use_underline(True)
but.set_label('_' + i[1])
but.show()
but.connect('clicked', self.sig_clicked, i[0])
self.states[i[0]] = but
if len(i) >= 3:
common.ICONFACTORY.register_icon(i[2])
icon = gtk.Image()
icon.set_from_stock(i[2], gtk.ICON_SIZE_BUTTON)
but.set_image(icon)
hbuttonbox.pack_start(but)
for state in states:
self._get_button(state)
val = {}
fields = view['fields']
@@ -181,7 +181,7 @@ class Wizard(SignalEvent):
if 'value' in fields[i]:
val[i] = fields[i]['value']
self.screen = Screen(obj_name, self.window, mode=[], context=context)
self.screen = Screen(obj_name, mode=[], context=context)
self.screen.add_view(view, display=True)
self.screen.widget.show()
@@ -224,7 +224,8 @@ class Wizard(SignalEvent):
self.widget.pack_start(eb, expand=False, fill=True, padding=3)
self.widget.pack_start(self.toolbar_box, False, True)
if self.toolbar_box:
self.widget.pack_start(self.toolbar_box, False, True)
viewport = gtk.Viewport()
viewport.set_shadow_type(gtk.SHADOW_NONE)
@@ -239,8 +240,135 @@ class Wizard(SignalEvent):
self.widget.pack_start(self.scrolledwindow)
self.widget.pack_start(hbuttonbox, expand=False, fill=True)
self.screen.new(default=False)
self.screen.current_record.set_default(val)
self.screen.current_view.set_cursor()
class WizardForm(Wizard,SignalEvent):
"Wizard"
def __init__(self, name=False):
super(WizardForm, self).__init__(name=name)
self.toolbar_box = gtk.HBox()
self.hbuttonbox = gtk.HButtonBox()
self.hbuttonbox.set_spacing(5)
self.hbuttonbox.set_layout(gtk.BUTTONBOX_END)
self.hbuttonbox.show()
self.widget.pack_start(self.toolbar_box, False, True)
self.dialogs = []
self.handlers = {
'but_close': self.sig_close
}
def clean(self):
super(WizardForm, self).clean()
for button in self.hbuttonbox.get_children():
self.hbuttonbox.remove(button)
def _get_button(self, state):
button = super(WizardForm, self)._get_button(state)
button.connect('clicked', self.response, state[0])
self.hbuttonbox.pack_start(button)
return button
def update(self, view, states, obj_name, context=None):
super(WizardForm, self).update(view, states, obj_name, context=context)
self.widget.pack_start(self.hbuttonbox, expand=False, fill=True)
def sig_close(self):
if 'end' in self.states:
self.states['end'].clicked()
return self.state == 'end'
def destroy(self):
if self.toolbar_box.get_children():
toolbar = self.toolbar_box.get_children()[0]
self.toolbar_box.remove(toolbar)
super(WizardForm, self).destroy()
def end(self):
super(WizardForm, self).end()
Main.get_main()._win_del(self.widget)
class WizardDialog(Wizard, NoModal):
def __init__(self, name=False):
if not name:
name = _('Wizard')
Wizard.__init__(self, name=name)
NoModal.__init__(self)
self.dia = gtk.Dialog(self.name, self.parent,
gtk.DIALOG_DESTROY_WITH_PARENT)
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
if hasattr(self.dia, 'set_deletable'):
self.dia.set_deletable(False)
self.dia.connect('close', self.close)
self.dia.connect('response', self.response)
self.dia.connect('state-changed', self.state_changed)
self.accel_group = gtk.AccelGroup()
self.dia.add_accel_group(self.accel_group)
self.dia.vbox.add(self.widget)
self.register()
def clean(self):
super(WizardDialog, self).clean()
hbuttonbox = self.dia.get_action_area()
for button in hbuttonbox.get_children():
hbuttonbox.remove(button)
def _get_button(self, state):
button = super(WizardDialog, self)._get_button(state)
response = len(self.states)
self.dia.add_action_widget(button, response)
if len(state) >= 4 and state[3]:
button.set_flags(gtk.CAN_DEFAULT)
button.add_accelerator('clicked', self.accel_group,
gtk.keysyms.Return, gtk.gdk.CONTROL_MASK,
gtk.ACCEL_VISIBLE)
self.dia.set_default_response(response)
return button
def update(self, view, states, obj_name, context=None):
super(WizardDialog, self).update(view, states, obj_name, context=context)
sensible_allocation = self.sensible_widget.get_allocation()
self.dia.set_default_size(int(sensible_allocation.width * 0.9),
int(sensible_allocation.height * 0.9))
self.dia.show()
common.center_window(self.dia, self.parent, self.sensible_widget)
def destroy(self):
self.dia.destroy()
NoModal.destroy(self)
main = Main.get_main()
if self.parent == main.window:
current_form = main.get_page()
if current_form:
for dialog in current_form.dialogs:
dialog.show()
if hasattr(self.page, 'screen'):
self.page.screen.reload(written=True)
super(WizardDialog, self).destroy()
def end(self):
super(WizardDialog, self).end()
self.destroy()
def close(self, widget, event=None):
widget.emit_stop_by_name('close')
return True
def show(self):
self.dia.show()
def hide(self):
self.dia.hide()
def state_changed(self, widget, state):
if self.dia.props.sensitive and state == gtk.STATE_INSENSITIVE:
self.process()
+4 -4
View File
@@ -26,16 +26,16 @@ if os.path.isdir(PLUGINS_PATH):
except ImportError, exception:
continue
def execute(datas, parent):
def execute(datas):
result = {}
for module in MODULES:
for name, func in module.get_plugins(datas['model']):
result[name] = func
if not result:
common.message(_('No available plugin for this resource!'), parent)
common.message(_('No available plugin for this resource!'))
return False
res = common.selection(_('Choose a Plugin'), result, parent, alwaysask=True)
res = common.selection(_('Choose a Plugin'), result, alwaysask=True)
if res:
res[1](datas, parent)
res[1](datas)
return True
+2 -2
View File
@@ -5,11 +5,11 @@ import gettext
_ = gettext.gettext
def translate_view(datas, parent):
def translate_view(datas):
model = datas['model']
Window.create(False, 'ir.translation', res_id=False,
domain=[('model', '=', model)],
mode=['tree', 'form'], window=parent)
mode=['tree', 'form'])
def get_plugins(model):
return [
+4 -4
View File
@@ -5,16 +5,16 @@ import gettext
_ = gettext.gettext
def workflow_print(datas, parent):
def workflow_print(datas):
datas = datas.copy()
datas['nested'] = False
Action.exec_report('workflow.instance.graph', datas, parent)
Action.exec_report('workflow.instance.graph', datas)
return True
def workflow_print_complex(datas, parent):
def workflow_print_complex(datas):
datas = datas.copy()
datas['nested'] = True
Action.exec_report('workflow.instance.graph', datas, parent)
Action.exec_report('workflow.instance.graph', datas)
return True
def get_plugins(model):
-3
View File
@@ -1,3 +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.
from main import *
-262
View File
@@ -1,262 +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.
import gtk
import gettext
import tryton.rpc as rpc
import tryton.common as common
import thread, time
from tryton.gui.window.view_form.screen import Screen
import os
import pango
from tryton.config import CONFIG
from tryton.exceptions import TrytonServerError
_ = gettext.gettext
class Dialog(object):
"Dialog for wizard"
def __init__(self, view, state, obj_name, parent,
action='', size=(0, 0), context=None):
self.parent = parent
self.action = action
self.states = []
default = -1
self.dia = gtk.Dialog(_('Wizard'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
if hasattr(self.dia, 'set_deletable'):
self.dia.set_deletable(False)
self.dia.connect('close', self.close)
self.accel_group = gtk.AccelGroup()
self.dia.add_accel_group(self.accel_group)
for i in state:
but = gtk.Button(i[1])
but.show()
if len(i) >= 3:
common.ICONFACTORY.register_icon(i[2])
icon = gtk.Image()
icon.set_from_stock(i[2], gtk.ICON_SIZE_BUTTON)
but.set_image(icon)
self.dia.add_action_widget(but, len(self.states))
if len(i) >= 4 and i[3]:
if default < 0:
default = len(self.states)
but.set_flags(gtk.CAN_DEFAULT)
but.add_accelerator('clicked', self.accel_group,
gtk.keysyms.Return, gtk.gdk.CONTROL_MASK,
gtk.ACCEL_VISIBLE)
self.dia.set_default_response(default)
self.states.append(i[0])
val = {}
fields = view['fields']
for i in fields:
if 'value' in fields[i]:
val[i] = fields[i]['value']
self.screen = Screen(obj_name, self.dia, mode=[], context=context)
self.screen.add_view(view, display=True)
title = gtk.Label()
title.set_use_markup(True)
title.modify_font(pango.FontDescription("14"))
title.set_label('<b>' + self.screen.current_view.title + '</b>')
title.set_padding(20, 3)
title.set_alignment(0.0, 0.5)
title.show()
self.info_label = gtk.Label()
self.info_label.set_padding(3, 3)
self.info_label.set_alignment(1.0, 0.5)
self.eb_info = gtk.EventBox()
self.eb_info.add(self.info_label)
self.eb_info.connect('button-release-event',
lambda *a: self.message_info(''))
vbox = gtk.VBox()
vbox.pack_start(self.eb_info, expand=True, fill=True, padding=5)
vbox.show()
hbox = gtk.HBox()
hbox.pack_start(title, expand=True, fill=True)
hbox.pack_start(vbox, expand=False, fill=True, padding=20)
hbox.show()
frame = gtk.Frame()
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
frame.add(hbox)
frame.show()
eb = gtk.EventBox()
eb.add(frame)
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))
eb.show()
self.dia.vbox.pack_start(eb, expand=False, fill=True, padding=3)
self.dia.vbox.pack_start(self.screen.widget, True, True)
width, height = self.screen.screen_container.size_get()
parent_width, parent_height = parent.get_size()
dia_width, dia_height = self.dia.get_size()
self.widget_width = min(parent_width - 20,
max(dia_width, width + 20, size[0]))
self.widget_height = min(parent_height - 60,
max(height + dia_height + 20, size[1]))
self.dia.set_default_size(self.widget_width,
self.widget_height)
self.screen.widget.show()
self.dia.set_title(self.screen.current_view.title)
self.dia.show()
self.screen.new(default=False)
self.screen.current_record.set_default(val)
self.screen.current_view.set_cursor()
def run(self, datas=None):
if datas is None:
datas = {}
while True:
res = self.dia.run()
self.screen.current_view.set_value()
if self.screen.current_record.validate() \
or (res<0) or (self.states[res]=='end'):
break
self.screen.display()
if CONFIG['client.save_width_height']:
width, height = self.dia.get_size()
if (width, height) != (self.widget_width, self.widget_height):
try:
rpc.execute('model', 'ir.action.wizard_size', 'set_size',
self.action, self.screen.model_name, width, height,
rpc.CONTEXT)
except TrytonServerError:
pass
if res < len(self.states) and res >= 0:
datas.update(self.screen.get())
self.dia.hide()
self.parent.present()
return self.states[res], datas
else:
self.dia.hide()
self.parent.present()
return False
def close(self, widget, event=None):
widget.emit_stop_by_name('close')
return True
def destroy(self):
self.dia.destroy()
def message_info(self, message, color='red'):
if message:
self.info_label.set_label(message)
self.eb_info.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(
COLOR_SCHEMES.get(color, 'white')))
self.eb_info.show_all()
else:
self.info_label.set_label('')
self.eb_info.hide()
class Wizard(object):
@staticmethod
def execute(action, datas, parent, state='init',
direct_print=False, email_print=False, email=None,
context=None):
from tryton.action import Action
if not 'form' in datas:
datas['form'] = {}
args = ('wizard', action, 'create', rpc.CONTEXT)
try:
wiz_id = rpc.execute(*args)
except TrytonServerError, exception:
wiz_id = common.process_exception(exception, parent, *args)
if not wiz_id:
return
dia = None
res = {}
while state != 'end':
ctx = context.copy()
ctx.update(rpc.CONTEXT)
ctx['active_id'] = datas.get('id')
ctx['active_ids'] = datas.get('ids')
rpcprogress = common.RPCProgress('execute', ('wizard',
action, 'execute', wiz_id, datas, state, ctx), parent)
try:
res = rpcprogress.run()
exception = None
except TrytonServerError, exception:
if common.process_exception(exception, parent):
continue
else:
# Continue by running previous result except if access to
# wizard is denied
if exception.args[0] == 'AccessDenied':
break
if not res:
if dia:
res = {'type': 'form'}
else:
break
else:
if dia and not exception:
dia.destroy()
dia = None
if 'datas' in res:
datas['form'] = res['datas']
elif res['type'] == 'form':
datas['form'] = {}
if res['type'] == 'form':
if not dia:
dia = Dialog(res, res['state'], res['object'], parent,
action=action, size=res['size'], context=ctx)
dia.screen.current_record.set_default(datas['form'])
res2 = dia.run(datas['form'])
if not res2:
break
state, new_data = res2
for data in new_data:
if new_data[data] is None:
del new_data[data]
datas['form'].update(new_data)
del new_data
elif res['type'] == 'action':
Action._exec_action(res['action'], dia or parent, datas,
context=ctx)
state = res['state']
elif res['type'] == 'print':
datas['report_id'] = res.get('report_id', False)
if res.get('get_id_from_action', False):
backup_ids = datas['ids']
datas['ids'] = datas['form']['ids']
Action.exec_report(res['report'], datas, dia or parent,
direct_print=direct_print, email_print=email_print,
email=email, context=ctx)
datas['ids'] = backup_ids
else:
Action.exec_report(res['report'], datas, dia or parent,
direct_print=direct_print, email_print=email_print,
email=email, context=ctx)
state = res['state']
elif res['type'] == 'state':
state = res['state']
if dia:
dia.destroy()
dia = None
try:
rpc.execute('wizard', action, 'delete', wiz_id, rpc.CONTEXT)
#XXX to remove when company displayed in status bar
rpc.context_reload()
except TrytonServerError:
pass