merge
This commit is contained in:
commit
27aecb30b3
15 files changed
+128
-73
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Add communication between boards
|
||||
* Added domain inversion feature
|
||||
* Handle loading attribute on fields
|
||||
* Use default format for value in wizard form
|
||||
|
||||
+27
-35
@@ -25,13 +25,13 @@ class Action(object):
|
||||
context = {}
|
||||
if email is None:
|
||||
email = {}
|
||||
datas = data.copy()
|
||||
ids = datas['ids']
|
||||
del datas['ids']
|
||||
data = data.copy()
|
||||
ids = data['ids']
|
||||
del data['ids']
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(context)
|
||||
if not ids:
|
||||
args = ('model', datas['model'], 'search', [], 0, None, None, ctx)
|
||||
args = ('model', data['model'], 'search', [], 0, None, None, ctx)
|
||||
try:
|
||||
ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
@@ -41,8 +41,8 @@ class Action(object):
|
||||
if ids == []:
|
||||
message(_('Nothing to print!'), window)
|
||||
return False
|
||||
datas['id'] = ids[0]
|
||||
args = ('report', name, 'execute', ids, datas, ctx)
|
||||
data['id'] = ids[0]
|
||||
args = ('report', name, 'execute', ids, data, ctx)
|
||||
rpcprogress = common.RPCProgress('execute', args, window)
|
||||
try:
|
||||
res = rpcprogress.run()
|
||||
@@ -70,7 +70,7 @@ class Action(object):
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def execute(act_id, datas, window, action_type=None, context=None):
|
||||
def execute(act_id, data, window, action_type=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
@@ -92,40 +92,32 @@ class Action(object):
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, window)
|
||||
return
|
||||
Action._exec_action(res, window, datas)
|
||||
Action._exec_action(res, window, data)
|
||||
|
||||
@staticmethod
|
||||
def _exec_action(action, window, datas=None, context=None):
|
||||
def _exec_action(action, window, data=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if datas is None:
|
||||
datas = {}
|
||||
if data is None:
|
||||
data = {}
|
||||
else:
|
||||
data = data.copy()
|
||||
if 'type' not in (action or {}):
|
||||
return
|
||||
|
||||
if action['type'] == 'ir.action.act_window':
|
||||
for key in (
|
||||
'res_id',
|
||||
'res_model',
|
||||
'view_type',
|
||||
'limit',
|
||||
'auto_refresh',
|
||||
'search_value',
|
||||
):
|
||||
datas[key] = action.get(key, datas.get(key, None))
|
||||
|
||||
view_ids = False
|
||||
datas['view_mode'] = None
|
||||
view_mode = None
|
||||
if action.get('views', []):
|
||||
view_ids = [x[0] for x in action['views']]
|
||||
datas['view_mode'] = [x[1] for x in action['views']]
|
||||
view_mode = [x[1] for x in action['views']]
|
||||
elif action.get('view_id', False):
|
||||
view_ids = [action['view_id'][0]]
|
||||
|
||||
action.setdefault('pyson_domain', '[]')
|
||||
ctx = {
|
||||
'active_id': datas.get('id',False),
|
||||
'active_ids': datas.get('ids',[]),
|
||||
'active_id': data.get('id', False),
|
||||
'active_ids': data.get('ids', []),
|
||||
}
|
||||
ctx.update(rpc.CONTEXT)
|
||||
eval_ctx = ctx.copy()
|
||||
@@ -138,9 +130,6 @@ class Action(object):
|
||||
domain_context['context'] = ctx
|
||||
domain = PYSONDecoder(domain_context).decode(action['pyson_domain'])
|
||||
|
||||
if datas.get('domain', False):
|
||||
domain.append(datas['domain'])
|
||||
|
||||
search_context = ctx.copy()
|
||||
search_context['context'] = ctx
|
||||
search_value = PYSONDecoder(search_context).decode(
|
||||
@@ -150,26 +139,29 @@ class Action(object):
|
||||
if action.get('window_name', True):
|
||||
name = action.get('name', False)
|
||||
|
||||
Window.create(view_ids, datas['res_model'], datas['res_id'], domain,
|
||||
action['view_type'], window, action_ctx,
|
||||
datas['view_mode'], name=name,
|
||||
limit=datas['limit'], auto_refresh=datas['auto_refresh'],
|
||||
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,
|
||||
action['view_type'], window, action_ctx, view_mode,
|
||||
name=name, limit=action.get('limit'),
|
||||
auto_refresh=action.get('auto_refresh'),
|
||||
search_value=search_value)
|
||||
elif action['type'] == 'ir.action.wizard':
|
||||
if action.get('window', False):
|
||||
Window.create_wizard(action['wiz_name'], datas, window,
|
||||
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)
|
||||
else:
|
||||
Wizard.execute(action['wiz_name'], datas, window,
|
||||
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)
|
||||
|
||||
elif action['type'] == 'ir.action.report':
|
||||
Action.exec_report(action['report_name'], datas, window,
|
||||
Action.exec_report(action['report_name'], data, window,
|
||||
direct_print=action.get('direct_print', False),
|
||||
email_print=action.get('email_print', False),
|
||||
email=action.get('email'), context=context)
|
||||
|
||||
@@ -357,8 +357,13 @@ class DBCreate(object):
|
||||
and langreal \
|
||||
and passwd \
|
||||
and admin_passwd.get_text():
|
||||
if rpc.db_exec(url_m.group(1), int(url_m.group(2)),
|
||||
'db_exist', dbname):
|
||||
try:
|
||||
exist = rpc.db_exec(url_m.group(1),
|
||||
int(url_m.group(2)), 'db_exist', dbname)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.dialog)
|
||||
continue
|
||||
if exist:
|
||||
common.warning(_("A database with the same name " \
|
||||
"already exists.\n" \
|
||||
"Try another database name."), self.dialog,
|
||||
|
||||
@@ -192,9 +192,10 @@ class Form(SignalEvent):
|
||||
win.show_all()
|
||||
|
||||
response = win.run()
|
||||
win.destroy()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.screen.display(locale.atoi(entry.get_text()), set_cursor=True)
|
||||
win.destroy()
|
||||
self.window.present()
|
||||
|
||||
def destroy(self):
|
||||
self.screen.signal_unconnect(self)
|
||||
|
||||
@@ -190,20 +190,8 @@ class Tree(SignalEvent):
|
||||
ids.index(y['id'])))
|
||||
radiotb = None
|
||||
for res in results:
|
||||
radiotb = gtk.RadioToolButton(group=radiotb)
|
||||
radiotb.set_label_widget(gtk.Label(res['name']))
|
||||
|
||||
icon = gtk.Image()
|
||||
try:
|
||||
icon.set_from_stock(res[icon_name],
|
||||
gtk.ICON_SIZE_BUTTON)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
hbox = gtk.HBox(spacing=6)
|
||||
hbox.pack_start(icon)
|
||||
hbox.pack_start(gtk.Label(res['name']))
|
||||
radiotb.set_icon_widget(hbox)
|
||||
radiotb = gtk.RadioToolButton(radiotb, res[icon_name])
|
||||
radiotb.set_label(res['name'])
|
||||
radiotb.show_all()
|
||||
radiotb.set_data('id', res['id'])
|
||||
radiotb.connect('clicked', self.menu_main_clicked)
|
||||
|
||||
@@ -13,12 +13,14 @@ import tryton.common as common
|
||||
from tryton.pyson import PYSONDecoder
|
||||
import gettext
|
||||
from tryton.config import CONFIG
|
||||
from tryton.signal_event import SignalEvent
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class Action(object):
|
||||
class Action(SignalEvent):
|
||||
|
||||
def __init__(self, window, attrs=None):
|
||||
super(Action, self).__init__()
|
||||
self.act_id = int(attrs['name'])
|
||||
self._window = window
|
||||
self.screen = None
|
||||
@@ -51,10 +53,8 @@ class Action(object):
|
||||
self.context.update(PYSONDecoder(eval_ctx).decode(
|
||||
self.action.get('pyson_context', '{}')))
|
||||
|
||||
domain_ctx = self.context.copy()
|
||||
self.domain = PYSONDecoder(domain_ctx).decode(
|
||||
self.action['pyson_domain'])
|
||||
|
||||
self.domain = []
|
||||
self.update_domain([])
|
||||
|
||||
self.widget = gtk.Frame()
|
||||
self.widget.set_border_width(0)
|
||||
@@ -151,6 +151,8 @@ class Action(object):
|
||||
alignment.add(self.screen.screen_container.alternate_viewport)
|
||||
name = self.screen.current_view.title
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
self.screen.signal_connect(self, 'record-message',
|
||||
self._active_changed)
|
||||
elif self.action['view_type'] == 'tree':
|
||||
ctx = {}
|
||||
ctx.update(rpc.CONTEXT)
|
||||
@@ -172,6 +174,8 @@ class Action(object):
|
||||
alignment.add(self.tree.widget_get())
|
||||
name = self.tree.name
|
||||
self.tree.view.connect('key_press_event', self.sig_key_press)
|
||||
self.tree.signal_connect(self, 'select-changed',
|
||||
self._active_changed)
|
||||
|
||||
if attrs.get('string'):
|
||||
self.title.set_text(attrs['string'])
|
||||
@@ -251,3 +255,28 @@ class Action(object):
|
||||
.get_selected_rows()
|
||||
for path in paths:
|
||||
self.tree.view.expand_row(path, False)
|
||||
|
||||
def _active_changed(self, *args):
|
||||
self.signal('active-changed')
|
||||
|
||||
def _get_active(self):
|
||||
if self.screen:
|
||||
return common.EvalEnvironment(self.screen.current_record, False)
|
||||
elif self.tree:
|
||||
return {'id': self.tree.sel_id_get()}
|
||||
|
||||
active = property(_get_active)
|
||||
|
||||
def update_domain(self, actions):
|
||||
domain_ctx = self.context.copy()
|
||||
for action in actions:
|
||||
if action.active:
|
||||
domain_ctx['_active_%s' % action.act_id] = action.active
|
||||
new_domain = PYSONDecoder(domain_ctx).decode(
|
||||
self.action['pyson_domain'])
|
||||
if self.domain == new_domain:
|
||||
return
|
||||
del self.domain[:]
|
||||
self.domain.extend(new_domain)
|
||||
if self.screen:
|
||||
self.screen.search_filter()
|
||||
@@ -2,8 +2,9 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
'View board'
|
||||
|
||||
from parser import ParserBoard
|
||||
import xml.dom.minidom
|
||||
from parser import ParserBoard
|
||||
from tryton.gui.window.view_board.action import Action
|
||||
|
||||
class ViewBoard(object):
|
||||
'View board'
|
||||
@@ -18,7 +19,12 @@ class ViewBoard(object):
|
||||
continue
|
||||
self.widget, self.widgets = parser.parse(node)
|
||||
break
|
||||
self.actions = [x for x in self.widgets if isinstance(x, Action)]
|
||||
for action in self.actions:
|
||||
action.signal_connect(self, 'active-changed',
|
||||
self._active_changed)
|
||||
self.widget.show_all()
|
||||
self._active_changed(None)
|
||||
|
||||
def widget_get(self):
|
||||
return self.widget
|
||||
@@ -26,3 +32,9 @@ class ViewBoard(object):
|
||||
def reload(self):
|
||||
for widget in self.widgets:
|
||||
widget.display()
|
||||
|
||||
def _active_changed(self, event_action, *args):
|
||||
for action in self.actions:
|
||||
if action == event_action:
|
||||
continue
|
||||
action.update_domain(self.actions)
|
||||
@@ -80,9 +80,13 @@ class Group(SignalEvent, list):
|
||||
self.signal('group-list-changed', ('record-removed', idx))
|
||||
|
||||
def clear(self):
|
||||
if not self.lock_signal:
|
||||
for record in self:
|
||||
self.signal('group-list-changed', ('record-removed', 0))
|
||||
del self[:]
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('group-cleared',))
|
||||
self.__id2record = {}
|
||||
self.record_removed = []
|
||||
self.record_deleted = []
|
||||
|
||||
|
||||
@@ -39,12 +39,12 @@ class Record(SignalEvent):
|
||||
def __getitem__(self, name):
|
||||
if name not in self._loaded and self.id > 0:
|
||||
ids = [self.id]
|
||||
import traceback
|
||||
if name == '*':
|
||||
loading = reduce(
|
||||
lambda x, y: 'eager' if x == y == 'eager' else 'lazy',
|
||||
(field.attrs.get('loading', 'eager')
|
||||
for field in self.group.fields.itervalues()))
|
||||
for field in self.group.fields.itervalues()),
|
||||
'eager')
|
||||
else:
|
||||
loading = self.group.fields[name].attrs.get('loading', 'eager')
|
||||
if self in self.group and loading == 'eager':
|
||||
|
||||
@@ -35,13 +35,16 @@ class ViewForm(ParserView):
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.add(vp)
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.viewport = gtk.Viewport()
|
||||
self.viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
self.viewport.add(scroll)
|
||||
scroll.set_placement(gtk.CORNER_TOP_LEFT)
|
||||
viewport = gtk.Viewport()
|
||||
viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
viewport.add(scroll)
|
||||
width, height = self.widget.size_request()
|
||||
if isinstance(self.screen.window, gtk.Dialog):
|
||||
vbox.set_size_request(width or -1, height or -1)
|
||||
vbox.pack_start(viewport, expand=True, fill=True)
|
||||
|
||||
self.widget = vbox
|
||||
self.widget.set_size_request(width, height)
|
||||
self.widget.pack_start(self.viewport, expand=True, fill=True)
|
||||
|
||||
if toolbar and not CONFIG['client.modepda']:
|
||||
hbox = gtk.HBox(homogeneous=False)
|
||||
|
||||
@@ -64,6 +64,8 @@ class Many2Many(WidgetInterface):
|
||||
view_type=['tree'], views_preload=attrs.get('views', {}),
|
||||
row_activate=self._on_activate)
|
||||
|
||||
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)
|
||||
|
||||
@@ -166,6 +166,8 @@ class One2Many(WidgetInterface):
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
menuitem_title.get_child().set_text(attrs.get('string', ''))
|
||||
|
||||
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)
|
||||
|
||||
@@ -150,16 +150,25 @@ class ViewList(ParserView):
|
||||
buttons, toolbar, notebooks, cursor_widget)
|
||||
self.store = None
|
||||
self.view_type = 'tree'
|
||||
self.widget = gtk.VBox()
|
||||
self.widget_tree = widget
|
||||
|
||||
vbox = gtk.VBox()
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.add(self.widget_tree)
|
||||
scroll.add(self.widget)
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_placement(gtk.CORNER_TOP_LEFT)
|
||||
viewport = gtk.Viewport()
|
||||
viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
viewport.add(scroll)
|
||||
self.widget.pack_start(viewport, expand=True, fill=True)
|
||||
width, height = self.widget.size_request()
|
||||
self.widget_tree = self.widget
|
||||
|
||||
if isinstance(self.screen.window, gtk.Dialog):
|
||||
vbox.set_size_request(width or -1, height or -1)
|
||||
vbox.pack_start(viewport, expand=True, fill=True)
|
||||
|
||||
self.widget_tree.screen = screen
|
||||
|
||||
self.widget = vbox
|
||||
self.reload = False
|
||||
self.children = children
|
||||
|
||||
|
||||
@@ -827,7 +827,7 @@ class ProgressBar(object):
|
||||
|
||||
class Button(object):
|
||||
|
||||
def __init__(self, treeview, windown, screen, attrs=None):
|
||||
def __init__(self, treeview, window, screen, attrs=None):
|
||||
super(Button, self).__init__()
|
||||
self.attrs = attrs or {}
|
||||
self.renderer = CellRendererButton(attrs.get('string', _('Unknown')))
|
||||
|
||||
@@ -13,6 +13,7 @@ from tryton.common import HM_FORMAT
|
||||
import tryton.common as common
|
||||
from tryton.translate import date_format
|
||||
from tryton.pyson import PYSONDecoder
|
||||
from tryton.signal_event import SignalEvent
|
||||
|
||||
FIELDS_LIST_TYPE = {
|
||||
'boolean': gobject.TYPE_BOOLEAN,
|
||||
@@ -323,11 +324,12 @@ class ViewTreeModel(gtk.GenericTreeModel, gtk.TreeSortable):
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
class ViewTree(object):
|
||||
class ViewTree(SignalEvent):
|
||||
"View tree"
|
||||
|
||||
def __init__(self, view_info, ids, window, sel_multi=False,
|
||||
context=None):
|
||||
super(ViewTree, self).__init__()
|
||||
self.window = window
|
||||
self.view = gtk.TreeView()
|
||||
self.view.set_headers_visible(not CONFIG['client.modepda'])
|
||||
@@ -342,10 +344,12 @@ class ViewTree(object):
|
||||
self.name = parse.title
|
||||
self.sel_multi = sel_multi
|
||||
|
||||
selection = self.view.get_selection()
|
||||
if sel_multi:
|
||||
self.view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||
selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
else:
|
||||
self.view.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
||||
selection.self.view.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
||||
selection.connect('changed', self.__select_changed)
|
||||
self.view.set_expander_column(self.view.get_column(1))
|
||||
self.view.set_enable_search(False)
|
||||
self.view.get_column(0).set_visible(False)
|
||||
@@ -413,3 +417,6 @@ class ViewTree(object):
|
||||
if not i:
|
||||
return None
|
||||
return model.get_value(i, col)
|
||||
|
||||
def __select_changed(self, tree_sel):
|
||||
self.signal('select-changed')
|
||||
Reference in new issue
Block a user