Example #1
0
    def display(self):
        super(DictWidget, self).display()

        if not self.field:
            return

        record_id = self.record.id if self.record else None
        if record_id != self._record_id:
            for key in list(self.fields.keys()):
                self._sig_remove(None, key, modified=False)
            self._record_id = record_id

        value = self.field.get_client(self.record) if self.field else {}
        new_key_names = set(value.keys()) - set(self.field.keys)
        if new_key_names:
            self.field.add_keys(list(new_key_names), self.record)
        decoder = PYSONDecoder()
        for key, val in sorted(value.items()):
            if key not in self.field.keys:
                continue
            if key not in self.fields:
                self.add_line(key)
            widget = self.fields[key]
            widget.set_value(val)
            widget.set_readonly(self._readonly)
            key_domain = decoder.decode(self.field.keys[key].get('domain')
                                        or '[]')
            widget_class(widget.widget, 'invalid',
                         not eval_domain(key_domain, value))
        for key in set(self.fields.keys()) - set(value.keys()):
            self._sig_remove(None, key, modified=False)

        self._set_button_sensitive()
Example #2
0
 def domain(self):
     group_domain = self.__domain
     if group_domain and isinstance(group_domain, str):
         decoder = PYSONDecoder(self.context)
         group_domain = decoder.decode(group_domain)
     if self.parent and self.child_name:
         field = self.parent.group.fields[self.child_name]
         return [group_domain, field.domain_get(self.parent)]
     return group_domain
Example #3
0
 def domain(self):
     group_domain = self.__domain
     if group_domain and isinstance(group_domain, str):
         decoder = PYSONDecoder(self.context)
         group_domain = decoder.decode(group_domain)
     if self.parent and self.child_name:
         field = self.parent.group.fields[self.child_name]
         return [group_domain, field.domain_get(self.parent)]
     return group_domain
Example #4
0
 def get_tab_domain(self):
     if not self.notebook:
         return []
     idx = self.notebook.get_current_page()
     if idx < 0:
         return []
     ctx, domain = self.tab_domain[idx][1]
     decoder = PYSONDecoder(ctx)
     return decoder.decode(domain)
Example #5
0
 def get_tab_domain(self):
     if not self.notebook:
         return []
     idx = self.notebook.get_current_page()
     if idx < 0:
         return []
     ctx, domain = self.tab_domain[idx][1]
     decoder = PYSONDecoder(ctx)
     return decoder.decode(domain)
Example #6
0
    def search_filter(self, search_string=None, only_ids=False):
        if self.context_screen:
            context_record = self.context_screen.current_record
            if not context_record.validate():
                self.clear()
                self.context_screen.display(set_cursor=True)
                return False
            context = self.context
            context.update(self.context_screen.get_on_change_value())
            self.new_group(context)

        domain = self.search_domain(search_string, True)
        if self.context_domain:
            decoder = PYSONDecoder(self.context)
            domain = ['AND', domain, decoder.decode(self.context_domain)]
        tab_domain = self.screen_container.get_tab_domain()
        if tab_domain:
            domain = ['AND', domain, tab_domain]

        context = self.context
        if self.screen_container.but_active.get_active():
            context['active_test'] = False
        try:
            ids = RPCExecute('model',
                             self.model_name,
                             'search',
                             domain,
                             self.offset,
                             self.limit,
                             self.order,
                             context=context)
        except RPCException:
            ids = []
        if not only_ids:
            if self.limit is not None and len(ids) == self.limit:
                try:
                    self.search_count = RPCExecute('model',
                                                   self.model_name,
                                                   'search_count',
                                                   domain,
                                                   context=context)
                except RPCException:
                    self.search_count = 0
            else:
                self.search_count = len(ids)
        self.screen_container.but_prev.set_sensitive(bool(self.offset))
        if (self.limit is not None and len(ids) == self.limit
                and self.search_count > self.limit + self.offset):
            self.screen_container.but_next.set_sensitive(True)
        else:
            self.screen_container.but_next.set_sensitive(False)
        if only_ids:
            return ids
        self.clear()
        self.load(ids)
        self.count_tab_domain()
        return bool(ids)
Example #7
0
    def display(self):
        super(DictWidget, self).display()

        if not self.field:
            return

        record_id = self.record.id if self.record else None
        if record_id != self._record_id:
            for key in list(self.fields.keys()):
                self._sig_remove(None, key, modified=False)
            self._record_id = record_id

        value = self.field.get_client(self.record) if self.field else {}
        new_key_names = set(value.keys()) - set(self.field.keys)
        if new_key_names:
            self.field.add_keys(list(new_key_names), self.record)
        decoder = PYSONDecoder()

        # ABDC: Allow dictschema to be ordered by a sequence
        value_ordered = OrderedDict()
        use_sequence = any(
            x[1].get('sequence_order', None) for x in self.field.keys.items())
        if use_sequence:
            for skey, svalues in sorted(self.field.keys.items(),
                    key=lambda x: x[1]['sequence_order']):
                if skey not in value:
                    continue
                value_ordered[skey] = value[skey]

        def _loop_order_hook():
            if use_sequence:
                return value_ordered.items()
            else:
                return ((key, val) for key, val in sorted(value.items()))

        for key, val in _loop_order_hook():
            if key not in self.field.keys:
                continue
            if key not in self.fields:
                self.add_line(key)
            widget = self.fields[key]
            widget.set_value(val)
            widget.set_readonly(self._readonly)
            key_domain = decoder.decode(
                self.field.keys[key].get('domain') or '[]')
            widget_class(
                widget.widget, 'invalid', not eval_domain(key_domain, value))
        for key in set(self.fields.keys()) - set(value.keys()):
            self._sig_remove(None, key, modified=False)

        self._set_button_sensitive()
Example #8
0
    def display(self, force=False):
        self.treeview.display_counter += 1
        current_record = self.record
        if (force or not self.treeview.get_model()
                or self.group != self.treeview.get_model().group):
            model = AdaptModelGroup(self.group, self.children_field,
                                    self.children_definitions)
            self.treeview.set_model(model)
            # __select_changed resets current_record to None
            self.record = current_record
            if current_record:
                selection = self.treeview.get_selection()
                path = current_record.get_index_path(model.group)
                # JCA : Check selection is not empty before updateing path
                if selection:
                    selection.select_path(path)
        if not current_record:
            selection = self.treeview.get_selection()
            selection.unselect_all()
        self.treeview.queue_draw()
        if self.editable:
            self.set_state()
        self.update_arrow()
        self.update_sum()

        # Set column visibility depending on attributes and domain
        domain = []
        if self.screen.domain:
            domain.append(self.screen.get_domain())
        tab_domain = self.screen.screen_container.get_tab_domain()
        if tab_domain:
            domain.append(tab_domain)
        domain = simplify(domain)
        decoder = PYSONDecoder(self.screen.context)
        for column in self.treeview.get_columns():
            name = column.name
            if not name:
                continue
            widget = self.get_column_widget(column)
            if current_record and widget.editable:
                widget.set_editable(current_record)
            if decoder.decode(widget.attrs.get('tree_invisible', '0')):
                column.set_visible(False)
            elif name == self.screen.exclude_field:
                column.set_visible(False)
            else:
                inv_domain = domain_inversion(domain, name)
                if not isinstance(inv_domain, bool):
                    inv_domain = simplify(inv_domain)
                unique, _, _ = unique_value(inv_domain)
                column.set_visible(not unique or bool(self.children_field))
Example #9
0
File: pyson.py Project: fabyc/nodux
class PYSON(Char):
    def __init__(self, view, attrs):
        super(PYSON, self).__init__(view, attrs)
        self.encoder = PYSONEncoder()
        self.decoder = PYSONDecoder(noeval=True)
        self.entry.connect('key-release-event', self.validate_pyson)

    def get_encoded_value(self):
        value = self.get_value()
        if not value:
            return value
        try:
            return self.encoder.encode(eval(value, CONTEXT))
        except (ValueError, TypeError, NameError, SyntaxError):
            return None

    def set_value(self, record, field):
        field.set_client(record, self.get_encoded_value())

    def get_client_value(self, record, field):
        value = super(PYSON, self).get_client_value(record, field)
        if value:
            value = repr(self.decoder.decode(value))
        return value

    def validate_pyson(self, *args):
        icon = gtk.STOCK_OK
        if self.get_encoded_value() is None:
            icon = gtk.STOCK_CANCEL
        self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, icon)

    def _focus_out(self):
        self.validate_pyson()
        super(PYSON, self)._focus_out()
Example #10
0
 def updateDatas(self, group):
     self.datas = {}
     self.labels = {}
     self.ids = {}
     self.group = group
     minx = None
     maxx = None
     for model in group:
         x = model[self.xfield['name']].get(model)
         if not minx:
             minx = x
         if not maxx:
             maxx = x
         minx = min(minx, x)
         maxx = max(maxx, x)
         self.labels[x] = model[self.xfield['name']].get_client(model)
         self.ids.setdefault(x, [])
         self.ids[x].append(model.id)
         self.datas.setdefault(x, {})
         for yfield in self.yfields:
             key = yfield.get('key', yfield['name'])
             self.datas[x].setdefault(key, 0.0)
             if yfield.get('domain'):
                 context = rpc.CONTEXT.copy()
                 context['context'] = context.copy()
                 context['_user'] = rpc._USER
                 for field in model.group.fields:
                     context[field] = model[field].get(model)
                 if not PYSONDecoder(context).decode(yfield['domain']):
                     continue
             if yfield['name'] == '#':
                 self.datas[x][key] += 1
             else:
                 value = model[yfield['name']].get(model)
                 if isinstance(value, datetime.timedelta):
                     value = value.total_seconds()
                 self.datas[x][key] += float(value or 0)
     date_format = self.view.screen.context.get('date_format', '%x')
     datetime_format = date_format + ' %X'
     if isinstance(minx, datetime.datetime):
         date = minx
         while date <= maxx:
             self.labels[date] = datetime_strftime(date, datetime_format)
             self.datas.setdefault(date, {})
             for yfield in self.yfields:
                 self.datas[date].setdefault(
                     yfield.get('key', yfield['name']), 0.0)
             date += relativedelta(days=1)
     elif isinstance(minx, datetime.date):
         date = minx
         while date <= maxx:
             self.labels[date] = datetime_strftime(date, date_format)
             self.datas.setdefault(date, {})
             for yfield in self.yfields:
                 self.datas[date].setdefault(
                     yfield.get('key', yfield['name']), 0.0)
             date += relativedelta(days=1)
Example #11
0
 def count_tab_domain(self):
     def set_tab_counter(count, idx):
         try:
             count = count()
         except RPCException:
             count = None
         self.screen_container.set_tab_counter(count, idx)
     screen_domain = self.search_domain(self.screen_container.get_text())
     for idx, (name, (ctx, domain), count) in enumerate(
             self.screen_container.tab_domain):
         if not count:
             continue
         decoder = PYSONDecoder(ctx)
         domain = ['AND', decoder.decode(domain), screen_domain]
         set_tab_counter(lambda: None, idx)
         RPCExecute('model', self.model_name,
             'search_count', domain, context=self.context,
             callback=functools.partial(set_tab_counter, idx=idx))
Example #12
0
    def _parse_button(self, node, attributes):
        button = Button(self.view, attributes)
        self.view.state_widgets.append(button)

        column = Gtk.TreeViewColumn(
            attributes.get('string', ''), button.renderer)
        column._type = 'button'
        column.name = None
        column.set_cell_data_func(button.renderer, button.setter)

        self._set_column_widget(column, attributes, arrow=False)
        self._set_column_width(column, attributes)

        decoder = PYSONDecoder(self.view.screen.context)
        column.set_visible(
            not decoder.decode(attributes.get('tree_invisible', '0')))

        self.view.treeview.append_column(column)
Example #13
0
class PYSON(Char):

    def __init__(self, view, attrs):
        super(PYSON, self).__init__(view, attrs)
        self.encoder = PYSONEncoder()
        self.decoder = PYSONDecoder(noeval=True)
        self.entry.connect('key-release-event', self.validate_pyson)

    def get_encoded_value(self):
        value = self.get_value()
        if not value:
            return value
        try:
            return self.encoder.encode(eval(value, CONTEXT))
        except Exception:
            return None

    def set_value(self):
        # avoid modification because different encoding
        value = self.get_encoded_value()
        previous = self.field.get_client(self.record)
        if (previous
                and value == self.encoder.encode(
                    self.decoder.decode(previous))):
            value = previous
        self.field.set_client(self.record, value)

    def get_client_value(self):
        value = super(PYSON, self).get_client_value()
        if value:
            value = repr(self.decoder.decode(value))
        return value

    def validate_pyson(self, *args):
        icon = 'tryton-ok'
        if self.get_encoded_value() is None:
            icon = 'tryton-error'
        pixbuf = IconFactory.get_pixbuf(icon, Gtk.IconSize.MENU)
        self.entry.set_icon_from_pixbuf(
            Gtk.EntryIconPosition.SECONDARY, pixbuf)

    def _focus_out(self):
        self.validate_pyson()
        super(PYSON, self)._focus_out()
Example #14
0
    def _parse_button(self, node):
        node_attrs = node_attributes(node)
        widget = Button(self, node_attrs)
        self.state_widgets.append(widget)

        column = gtk.TreeViewColumn(node_attrs.get('string', ''),
            widget.renderer)
        column._type = 'button'
        column.name = None
        column.set_cell_data_func(widget.renderer, widget.setter)

        self.set_column_widget(column, None, node_attrs, arrow=False)
        self.set_column_width(column, None, node_attrs)

        decoder = PYSONDecoder(self.screen.context)
        column.set_visible(
            not decoder.decode(node_attrs.get('tree_invisible', '0')))

        self.treeview.append_column(column)
Example #15
0
 def expr_eval(self, expr):
     if not isinstance(expr, str):
         return expr
     ctx = self.get_eval()
     ctx['context'] = self.get_context()
     ctx['active_model'] = self.model_name
     ctx['active_id'] = self.id
     if self.parent and self.parent_name:
         ctx['_parent_' + self.parent_name] = \
             common.EvalEnvironment(self.parent)
     val = PYSONDecoder(ctx).decode(expr)
     return val
Example #16
0
class PYSON(Char):
    def __init__(self, view, attrs):
        super(PYSON, self).__init__(view, attrs)
        self.encoder = PYSONEncoder()
        self.decoder = PYSONDecoder(noeval=True)
        self.entry.connect('key-release-event', self.validate_pyson)

    def get_encoded_value(self):
        value = self.get_value()
        if not value:
            return value
        try:
            return self.encoder.encode(eval(value, CONTEXT))
        except Exception:
            return None

    def set_value(self, record, field):
        # avoid modification because different encoding
        value = self.get_encoded_value()
        previous = field.get_client(record)
        if (previous and value == self.encoder.encode(
                self.decoder.decode(previous))):
            value = previous
        field.set_client(record, value)

    def get_client_value(self, record, field):
        value = super(PYSON, self).get_client_value(record, field)
        if value:
            value = repr(self.decoder.decode(value))
        return value

    def validate_pyson(self, *args):
        icon = gtk.STOCK_OK
        if self.get_encoded_value() is None:
            icon = gtk.STOCK_CANCEL
        self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, icon)

    def _focus_out(self):
        self.validate_pyson()
        super(PYSON, self)._focus_out()
Example #17
0
    def validate(self, record, softvalidation=False, pre_validate=None):
        valid = super(DictField, self).validate(record, softvalidation,
                                                pre_validate)

        if self.attrs.get('readonly'):
            return valid

        decoder = PYSONDecoder()
        field_value = self.get_eval(record)
        domain = []
        for key in field_value:
            if key not in self.keys:
                continue
            key_domain = self.keys[key].get('domain')
            if key_domain:
                domain.append(decoder.decode(key_domain))

        valid_value = eval_domain(domain, field_value)
        if not valid_value:
            self.get_state_attrs(record)['invalid'] = 'domain'

        return valid and valid_value
Example #18
0
 def update_domain(self, actions):
     domain_ctx = self.context.copy()
     domain_ctx['context'] = domain_ctx
     domain_ctx['_user'] = rpc._USER
     for action in actions:
         if action.active:
             domain_ctx[action.name] = 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 hasattr(self, 'screen'):  # Catch early update
         # Using idle_add to prevent corruption of the event who triggered
         # the update.
         gtk.idle_add(self.display)
Example #19
0
 def update_domain(self, actions):
     domain_ctx = self.context.copy()
     domain_ctx['_actions'] = {}
     for action in actions:
         domain_ctx['_actions'][action.name] = 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 hasattr(self, 'screen'):  # Catch early update
         # Using idle_add to prevent corruption of the event who triggered
         # the update.
         def display():
             if self.screen.widget.props.window:
                 self.display()
         GLib.idle_add(display)
Example #20
0
File: pyson.py Project: fabyc/nodux
 def __init__(self, view, attrs):
     super(PYSON, self).__init__(view, attrs)
     self.encoder = PYSONEncoder()
     self.decoder = PYSONDecoder(noeval=True)
     self.entry.connect('key-release-event', self.validate_pyson)
Example #21
0
    def __init__(self, attrs=None, context=None):
        super(Action, self).__init__()
        self.name = attrs['name']
        self.context = context or {}

        try:
            self.action = RPCExecute('model', 'ir.action.act_window', 'get',
                                     self.name)
        except RPCException:
            raise

        view_ids = None
        self.action['view_mode'] = None
        if self.action.get('views', []):
            view_ids = [x[0] for x in self.action['views']]
            self.action['view_mode'] = [x[1] for x in self.action['views']]
        elif self.action.get('view_id', False):
            view_ids = [self.action['view_id'][0]]

        if 'view_mode' in attrs:
            self.action['view_mode'] = attrs['view_mode']

        self.action.setdefault('pyson_domain', '[]')
        self.context.update(rpc.CONTEXT)
        self.context['_user'] = rpc._USER
        self.context.update(
            PYSONDecoder(self.context).decode(
                self.action.get('pyson_context', '{}')))

        eval_ctx = self.context.copy()
        self.context.update(
            PYSONDecoder(eval_ctx).decode(
                self.action.get('pyson_context', '{}')))

        self.domain = []
        self.update_domain([])

        search_context = self.context.copy()
        search_context['context'] = self.context
        search_context['_user'] = rpc._USER
        search_value = PYSONDecoder(search_context).decode(
            self.action['pyson_search_value'] or '{}')

        self.widget = gtk.Frame()
        self.widget.set_border_width(0)

        vbox = gtk.VBox(homogeneous=False, spacing=3)
        self.widget.add(vbox)

        self.title = gtk.Label()
        self.widget.set_label_widget(self.title)
        self.widget.set_label_align(0.0, 0.5)
        self.widget.show_all()

        self.screen = Screen(self.action['res_model'],
                             mode=self.action['view_mode'],
                             context=self.context,
                             view_ids=view_ids,
                             domain=self.domain,
                             search_value=search_value,
                             row_activate=self.row_activate)
        vbox.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.signal_connect(self, 'record-message',
                                   self._active_changed)

        if attrs.get('string'):
            self.title.set_text(attrs['string'])
        else:
            self.title.set_text(self.action['name'])

        self.widget.set_size_request(int(attrs.get('width', -1)),
                                     int(attrs.get('height', -1)))

        self.screen.search_filter()
Example #22
0
    def state_set(self, record):
        super().state_set(record)
        if not self.get_visible():
            return
        if CONFIG['client.modepda']:
            self.hide()
            return
        if record:
            data = {
                'model': record.model_name,
                'id': record.id,
                'ids': [record.id],
            }
            context = record.get_context()
            pyson_ctx = {
                'active_model': record.model_name,
                'active_id': record.id,
                'active_ids': [record.id],
            }
            self._current = record.id
        else:
            data = {}
            context = {}
            pyson_ctx = {}
            self._current = None
        pyson_ctx['context'] = context
        try:
            self.disconnect_by_func(self.__class__.clicked)
        except TypeError:
            pass
        self.connect('clicked', self.__class__.clicked, [data, context])
        action = common.RPCExecute('model',
                                   'ir.action',
                                   'get_action_value',
                                   self.action_id,
                                   context=context)
        self.set_label(action['rec_name'])

        decoder = PYSONDecoder(pyson_ctx)
        domain = decoder.decode(action['pyson_domain'])
        if action.get('pyson_search_value'):
            domain = [domain, decoder.decode(action['pyson_search_value'])]
        tab_domains = [(n, decoder.decode(d)) for n, d, c in action['domains']
                       if c]
        if tab_domains:
            label = ('%s\n' % action['rec_name']) + '\n'.join(
                '%s (%%d)' % n for n, _ in tab_domains)
        else:
            label = '%s (%%d)' % action['rec_name']
        if record and self.action_id in record.links_counts:
            counter = record.links_counts[self.action_id]
            self._set_label_counter(label, counter)
        else:
            counter = [0] * (len(tab_domains) or 1)
            if record:
                record.links_counts[self.action_id] = counter
            if tab_domains:
                for i, (_, tab_domain) in enumerate(tab_domains):
                    common.RPCExecute(
                        'model',
                        action['res_model'],
                        'search_count', ['AND', domain, tab_domain],
                        context=context,
                        callback=functools.partial(self._set_count,
                                                   idx=i,
                                                   current=self._current,
                                                   counter=counter,
                                                   label=label))
            else:
                common.RPCExecute('model',
                                  action['res_model'],
                                  'search_count',
                                  domain,
                                  context=context,
                                  callback=functools.partial(
                                      self._set_count,
                                      current=self._current,
                                      counter=counter,
                                      label=label))
Example #23
0
    def _exec_action(action, data=None, context=None):
        if context is None:
            context = {}
        if data is None:
            data = {}
        else:
            data = data.copy()
        if 'type' not in (action or {}):
            return

        if action['type'] == 'ir.action.act_window':
            view_ids = False
            view_mode = None
            if action.get('views', []):
                view_ids = [x[0] 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_model': data.get('res_model'),
                'active_id': data.get('id', False),
                'active_ids': data.get('ids', []),
            }
            ctx.update(rpc.CONTEXT)
            eval_ctx = ctx.copy()
            eval_ctx['_user'] = rpc._USER
            action_ctx = PYSONDecoder(eval_ctx).decode(
                    action.get('pyson_context') or '{}')
            ctx.update(action_ctx)
            ctx.update(context)

            domain_context = ctx.copy()
            domain_context['context'] = ctx
            domain_context['_user'] = rpc._USER
            domain = PYSONDecoder(domain_context).decode(
                action['pyson_domain'])

            search_context = ctx.copy()
            search_context['context'] = ctx
            search_context['_user'] = rpc._USER
            search_value = PYSONDecoder(search_context).decode(
                    action['pyson_search_value'] or '[]')

            tab_domain_context = ctx.copy()
            tab_domain_context['context'] = ctx
            tab_domain_context['_user'] = rpc._USER
            decoder = PYSONDecoder(tab_domain_context)
            tab_domain = [(n, decoder.decode(d)) for n, d in action['domains']]

            name = False
            if action.get('window_name', True):
                name = action.get('name', False)

            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_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 ''),
                    tab_domain=tab_domain)
        elif action['type'] == 'ir.action.wizard':
            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,
                    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.url':
            if action['url']:
                webbrowser.open(action['url'], new=2)
Example #24
0
    def _exec_action(action, data=None, context=None):
        if context is None:
            context = {}
        else:
            context = context.copy()
        if 'date_format' not in context:
            context['date_format'] = rpc.CONTEXT.get(
                'locale', {}).get('date', '%x')
        if data is None:
            data = {}
        else:
            data = data.copy()
        if 'type' not in (action or {}):
            return

        data['action_id'] = action['id']
        if action['type'] == 'ir.action.act_window':
            view_ids = False
            view_mode = None
            if action.get('views', []):
                view_ids = [x[0] 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_model': data.get('model'),
                'active_id': data.get('id'),
                'active_ids': data.get('ids', []),
            }
            ctx.update(rpc.CONTEXT)
            ctx['_user'] = rpc._USER
            decoder = PYSONDecoder(ctx)
            action_ctx = decoder.decode(action.get('pyson_context') or '{}')
            action_ctx.update(context)
            action_ctx.update(ctx)
            action_ctx.update(data.get('extra_context', {}))
            action_ctx['context'] = ctx

            decoder = PYSONDecoder(action_ctx)
            domain = action['pyson_domain']
            order = decoder.decode(action['pyson_order'])
            search_value = decoder.decode(action['pyson_search_value'] or '[]')
            tab_domain = [(n, (action_ctx, d)) for n, d in action['domains']]

            name = False
            if action.get('window_name', True):
                name = action.get('name', False)

            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_ctx, order, view_mode, name=name,
                    limit=action.get('limit'),
                    search_value=search_value,
                    icon=(action.get('icon.rec_name') or ''),
                    tab_domain=tab_domain,
                    context_model=action['context_model'])
        elif action['type'] == 'ir.action.wizard':
            context = copy.deepcopy(context)
            context.update(data.get('extra_context', {}))
            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,
                    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.url':
            if action['url']:
                webbrowser.open(action['url'], new=2)
Example #25
0
    def _exec_action(action, data=None, context=None):
        from tryton.gui.window import Window
        if context is None:
            context = {}
        else:
            context = context.copy()
        if data is None:
            data = {}
        else:
            data = data.copy()
        if 'type' not in (action or {}):
            return

        context.pop('active_id', None)
        context.pop('active_ids', None)
        context.pop('active_model', None)

        def add_name_suffix(name, context=None):
            if not data.get('ids') or not data.get('model'):
                return name
            max_records = 5
            ids = list(filter(lambda id: id >= 0, data['ids']))[:max_records]
            if not ids:
                return name
            rec_names = RPCExecute('model',
                                   data['model'],
                                   'read',
                                   ids, ['rec_name'],
                                   context=context)
            name_suffix = _(', ').join([x['rec_name'] for x in rec_names])
            if len(data['ids']) > len(ids):
                name_suffix += _(',...')
            if name_suffix:
                return _('%s (%s)') % (name, name_suffix)
            else:
                return name

        data['action_id'] = action['id']
        if action['type'] == 'ir.action.act_window':
            view_ids = []
            view_mode = None
            if action.get('views', []):
                view_ids = [x[0] 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_model': data.get('model'),
                'active_id': data.get('id'),
                'active_ids': data.get('ids') or [],
            }
            ctx.update(rpc.CONTEXT)
            ctx['_user'] = rpc._USER
            decoder = PYSONDecoder(ctx)
            action_ctx = context.copy()
            action_ctx.update(
                decoder.decode(action.get('pyson_context') or '{}'))
            ctx.update(action_ctx)

            ctx['context'] = ctx
            decoder = PYSONDecoder(ctx)
            domain = decoder.decode(action['pyson_domain'])
            order = decoder.decode(action['pyson_order'])
            search_value = decoder.decode(action['pyson_search_value'] or '[]')
            tab_domain = [(n, decoder.decode(d), c)
                          for n, d, c in action['domains']]

            name = action.get('name', '')
            if action.get('keyword', ''):
                name = add_name_suffix(name, action_ctx)

            res_model = action.get('res_model', data.get('res_model'))
            res_id = action.get('res_id', data.get('res_id'))
            limit = action.get('limit')
            if limit is None:
                limit = CONFIG['client.limit']

            Window.create(res_model,
                          view_ids=view_ids,
                          res_id=res_id,
                          domain=domain,
                          context=action_ctx,
                          order=order,
                          mode=view_mode,
                          name=name,
                          limit=limit,
                          search_value=search_value,
                          icon=(action.get('icon.rec_name') or ''),
                          tab_domain=tab_domain,
                          context_model=action['context_model'],
                          context_domain=action['context_domain'])
        elif action['type'] == 'ir.action.wizard':
            name = action.get('name', '')
            if action.get('keyword', 'form_action') == 'form_action':
                name = add_name_suffix(name, context)
            Window.create_wizard(action['wiz_name'],
                                 data,
                                 direct_print=action.get(
                                     'direct_print', False),
                                 name=name,
                                 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,
                               direct_print=action.get('direct_print', False),
                               context=context)

        elif action['type'] == 'ir.action.url':
            if action['url']:
                webbrowser.open(action['url'], new=2)
Example #26
0
 def get_domain(self):
     if not self.domain or not isinstance(self.domain, basestring):
         return self.domain
     decoder = PYSONDecoder(self.context)
     return decoder.decode(self.domain)
Example #27
0
    def __init__(self, attrs=None, context=None):
        if context is None:
            context = {}
        super(Action, self).__init__()
        self.name = attrs['name']

        try:
            self.action = RPCExecute('model', 'ir.action.act_window', 'get',
                                     self.name)
        except RPCException:
            raise

        view_ids = []
        view_mode = None
        if self.action.get('views', []):
            view_ids = [x[0] for x in self.action['views']]
            view_mode = [x[1] for x in self.action['views']]
        elif self.action.get('view_id', False):
            view_ids = [self.action['view_id'][0]]

        self.action.setdefault('pyson_domain', '[]')
        ctx = {}
        ctx.update(rpc.CONTEXT)
        ctx['_user'] = rpc._USER
        decoder = PYSONDecoder(ctx)
        action_ctx = context.copy()
        action_ctx.update(
            decoder.decode(self.action.get('pyson_context') or '{}'))
        ctx.update(action_ctx)

        ctx['context'] = ctx
        decoder = PYSONDecoder(ctx)
        self.domain = decoder.decode(self.action['pyson_domain'])
        order = decoder.decode(self.action['pyson_order'])
        search_value = decoder.decode(self.action['pyson_search_value']
                                      or '[]')
        tab_domain = [(n, decoder.decode(d), c)
                      for n, d, c in self.action['domains']]

        limit = self.action.get('limit')
        if limit is None:
            limit = CONFIG['client.limit']

        self.context = ctx
        self.domain = []
        self.update_domain([])

        self.widget = Gtk.Frame()
        self.widget.set_border_width(0)

        vbox = Gtk.VBox(homogeneous=False, spacing=3)
        self.widget.add(vbox)

        self.title = Gtk.Label()
        self.widget.set_label_widget(self.title)
        self.widget.set_label_align(0.0, 0.5)
        self.widget.show_all()

        self.screen = Screen(self.action['res_model'],
                             view_ids=view_ids,
                             domain=self.domain,
                             context=action_ctx,
                             order=order,
                             mode=view_mode,
                             limit=limit,
                             search_value=search_value,
                             tab_domain=tab_domain,
                             context_model=self.action['context_model'],
                             context_domain=self.action['context_domain'],
                             row_activate=self.row_activate)
        vbox.pack_start(self.screen.widget, expand=True, fill=True, padding=0)
        self.screen.signal_connect(self, 'record-message',
                                   self._active_changed)

        if attrs.get('string'):
            self.title.set_text(attrs['string'])
        else:
            self.title.set_text(self.action['name'])

        self.widget.set_size_request(int(attrs.get('width', -1)),
                                     int(attrs.get('height', -1)))

        self.screen.search_filter()
Example #28
0
    def _exec_action(action, data=None, context=None):
        if context is None:
            context = {}
        else:
            context = context.copy()
        if 'date_format' not in context:
            context['date_format'] = rpc.CONTEXT.get('locale',
                                                     {}).get('date', '%x')
        if data is None:
            data = {}
        else:
            data = data.copy()
        if 'type' not in (action or {}):
            return

        data['action_id'] = action['id']
        if action['type'] == 'ir.action.act_window':
            view_ids = False
            view_mode = None
            if action.get('views', []):
                view_ids = [x[0] 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_model': data.get('model'),
                'active_id': data.get('id'),
                'active_ids': data.get('ids', []),
            }
            ctx.update(rpc.CONTEXT)
            ctx['_user'] = rpc._USER
            decoder = PYSONDecoder(ctx)
            action_ctx = decoder.decode(action.get('pyson_context') or '{}')
            action_ctx.update(context)
            action_ctx.update(ctx)
            action_ctx.update(data.get('extra_context', {}))
            action_ctx['context'] = ctx

            decoder = PYSONDecoder(action_ctx)
            domain = action['pyson_domain']
            order = decoder.decode(action['pyson_order'])
            search_value = decoder.decode(action['pyson_search_value'] or '[]')
            tab_domain = [(n, (action_ctx, d)) for n, d in action['domains']]

            name = False
            if action.get('window_name', True):
                name = action.get('name', False)

            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_ctx,
                          order,
                          view_mode,
                          name=name,
                          limit=action.get('limit'),
                          search_value=search_value,
                          icon=(action.get('icon.rec_name') or ''),
                          tab_domain=tab_domain,
                          context_model=action['context_model'])
        elif action['type'] == 'ir.action.wizard':
            context = copy.deepcopy(context)
            context.update(data.get('extra_context', {}))
            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,
                               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.url':
            if action['url']:
                webbrowser.open(action['url'], new=2)
Example #29
0
    def display(self, force=False):
        self.treeview.display_counter += 1
        current_record = self.record
        if (force or not self.treeview.get_model()
                or self.group != self.treeview.get_model().group):
            model = AdaptModelGroup(self.group, self.children_field)
            self.treeview.set_model(model)
            # __select_changed resets current_record to None
            self.record = current_record
            if current_record:
                selection = self.treeview.get_selection()
                path = current_record.get_index_path(model.group)
                selection.select_path(path)
            # The search column must be set each time the model is changed
            self.treeview.set_search_column(0)
        if not current_record:
            selection = self.treeview.get_selection()
            selection.unselect_all()
        self.treeview.queue_draw()
        if self.editable:
            self.set_state()
        self.update_arrow()
        self.update_sum()

        # Set column visibility depending on attributes and domain
        domain = []
        if self.screen.domain:
            domain.append(self.screen.domain)
        tab_domain = self.screen.screen_container.get_tab_domain()
        if tab_domain:
            domain.append(tab_domain)
        domain = simplify(domain)
        decoder = PYSONDecoder(self.screen.context)
        tree_column_optional = self.screen.tree_column_optional.get(
            self.view_id, {})
        for column in self.treeview.get_columns():
            name = column.name
            if not name:
                continue
            widget = self.get_column_widget(column)
            widget.set_editable()
            if column.name in tree_column_optional:
                optional = tree_column_optional[column.name]
            else:
                optional = bool(int(widget.attrs.get('optional', '0')))
            invisible = decoder.decode(widget.attrs.get('tree_invisible', '0'))
            if invisible or optional:
                column.set_visible(False)
            elif name == self.screen.exclude_field:
                column.set_visible(False)
            else:
                inv_domain = domain_inversion(domain, name)
                if not isinstance(inv_domain, bool):
                    inv_domain = simplify(inv_domain)
                unique, _, _ = unique_value(inv_domain)
                column.set_visible(not unique or bool(self.children_field))
        if self.children_field:
            for i, column in enumerate(self.treeview.get_columns()):
                if self.draggable and not i:
                    continue
                if column.get_visible():
                    self.treeview.set_expander_column(column)
                    break
Example #30
0
    def sig_win_menu(self, prefs=None):
        from tryton.gui.window.view_form.screen import Screen

        if not prefs:
            try:
                prefs = RPCExecute('model', 'res.user', 'get_preferences',
                                   False)
            except RPCException:
                return False

        if self.menu_screen:
            self.menu_screen.save_tree_state()
        for child in self.menu.get_children():
            self.menu.remove(child)

        action = PYSONDecoder().decode(prefs['pyson_menu'])
        view_ids = []
        if action.get('views', []):
            view_ids = [x[0] for x in action['views']]
        elif action.get('view_id', False):
            view_ids = [action['view_id'][0]]
        ctx = rpc.CONTEXT.copy()
        decoder = PYSONDecoder(ctx)
        action_ctx = decoder.decode(action.get('pyson_context') or '{}')
        domain = decoder.decode(action['pyson_domain'])
        screen = Screen(action['res_model'],
                        mode=['tree'],
                        view_ids=view_ids,
                        domain=domain,
                        context=action_ctx,
                        readonly=True,
                        limit=None,
                        row_activate=self.menu_row_activate)
        # Use alternate view to not show search box
        screen.screen_container.alternate_view = True
        screen.switch_view(view_type=screen.current_view.view_type)

        self.menu.pack_start(screen.screen_container.alternate_viewport, True,
                             True)
        treeview = screen.current_view.treeview
        treeview.set_headers_visible(False)

        # Favorite column
        column = gtk.TreeViewColumn()
        column.name = None
        column._type = None
        favorite_renderer = CellRendererClickablePixbuf()
        column.pack_start(favorite_renderer, expand=False)

        def favorite_setter(column, cell, store, iter_):
            menu = store.get_value(iter_, 0)
            favorite = menu.value.get('favorite')
            if favorite:
                stock_id = 'tryton-star'
            elif favorite is False:
                stock_id = 'tryton-unstar'
            else:
                stock_id = ''
            pixbuf = treeview.render_icon(stock_id=stock_id,
                                          size=gtk.ICON_SIZE_MENU,
                                          detail=None)
            cell.set_property('pixbuf', pixbuf)

        column.set_cell_data_func(favorite_renderer, favorite_setter)

        def toggle_favorite(renderer, path, treeview):
            if treeview.props.window:
                self.toggle_favorite(renderer, path, treeview)

        favorite_renderer.connect(
            'clicked', lambda *a: gobject.idle_add(toggle_favorite, *a),
            treeview)
        # Unset fixed height mode to add column
        treeview.set_fixed_height_mode(False)
        treeview.set_property('enable-grid-lines',
                              gtk.TREE_VIEW_GRID_LINES_NONE)
        treeview.append_column(column)

        screen.search_filter()
        screen.display(set_cursor=True)
        self.menu_screen = screen
Example #31
0
def time_format(field):
    return PYSONDecoder({}).decode(field['format'])
Example #32
0
    def search_box(self, widget):
        def window_hide(window, *args):
            window.hide()
            self.search_entry.grab_focus()

        def key_press(widget, event):
            if event.keyval == gtk.keysyms.Escape:
                window_hide(widget)
                return True
            return False

        def search():
            self.search_window.hide()
            text = ''
            for label, entry in self.search_table.fields:
                if isinstance(entry, gtk.ComboBox):
                    value = quote(entry.get_active_text()) or None
                elif isinstance(entry, (Dates, Selection)):
                    value = entry.get_value()
                else:
                    value = quote(entry.get_text()) or None
                if value is not None:
                    text += quote(label) + ': ' + value + ' '
            self.set_text(text)
            self.do_search()
            # Store text after doing the search
            # because domain parser could simplify the text
            self.last_search_text = self.get_text()

        if not self.search_window:
            self.search_window = gtk.Window()
            self.search_window.set_transient_for(widget.get_toplevel())
            self.search_window.set_type_hint(
                gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU)
            self.search_window.set_destroy_with_parent(True)
            self.search_window.set_decorated(False)
            self.search_window.set_deletable(False)
            self.search_window.connect('delete-event', window_hide)
            self.search_window.connect('key-press-event', key_press)
            self.search_window.connect('focus-out-event', window_hide)

            def toggle_window_hide(combobox, shown):
                if combobox.props.popup_shown:
                    self.search_window.handler_block_by_func(window_hide)
                else:
                    self.search_window.handler_unblock_by_func(window_hide)

            vbox = gtk.VBox()
            fields = [
                f for f in self.screen.domain_parser.fields.itervalues()
                if f.get('searchable', True)
            ]
            self.search_table = gtk.Table(rows=len(fields), columns=2)
            self.search_table.set_homogeneous(False)
            self.search_table.set_border_width(5)
            self.search_table.set_row_spacings(2)
            self.search_table.set_col_spacings(2)

            # Fill table with fields
            self.search_table.fields = []
            for i, field in enumerate(fields):
                label = gtk.Label(field['string'])
                label.set_alignment(0.0, 0.0)
                self.search_table.attach(label,
                                         0,
                                         1,
                                         i,
                                         i + 1,
                                         yoptions=gtk.FILL)
                yoptions = False
                if field['type'] == 'boolean':
                    if hasattr(gtk, 'ComboBoxText'):
                        entry = gtk.ComboBoxText()
                    else:
                        entry = gtk.combo_box_new_text()
                    entry.connect('notify::popup-shown', toggle_window_hide)
                    entry.append_text('')
                    selections = (_('True'), _('False'))
                    for selection in selections:
                        entry.append_text(selection)
                elif field['type'] == 'selection':
                    selections = tuple(x[1] for x in field['selection'])
                    entry = Selection(selections)
                    yoptions = gtk.FILL | gtk.EXPAND
                elif field['type'] in ('date', 'datetime', 'time'):
                    date_format = self.screen.context.get('date_format', '%x')
                    if field['type'] == 'date':
                        entry = Dates(date_format)
                    elif field['type'] in ('datetime', 'time'):
                        time_format = PYSONDecoder({}).decode(field['format'])
                        if field['type'] == 'time':
                            entry = Times(time_format)
                        elif field['type'] == 'datetime':
                            entry = DateTimes(date_format, time_format)
                    entry.connect_activate(lambda *a: search())
                else:
                    entry = gtk.Entry()
                    entry.connect('activate', lambda *a: search())
                label.set_mnemonic_widget(entry)
                self.search_table.attach(entry,
                                         1,
                                         2,
                                         i,
                                         i + 1,
                                         yoptions=yoptions)
                self.search_table.fields.append((field['string'], entry))

            scrolled = gtk.ScrolledWindow()
            scrolled.add_with_viewport(self.search_table)
            scrolled.set_shadow_type(gtk.SHADOW_NONE)
            scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
            vbox.pack_start(scrolled, expand=True, fill=True)
            find_button = gtk.Button(_('Find'))
            find_button.connect('clicked', lambda *a: search())
            find_img = gtk.Image()
            find_img.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR)
            find_button.set_image(find_img)
            hbuttonbox = gtk.HButtonBox()
            hbuttonbox.set_spacing(5)
            hbuttonbox.pack_start(find_button)
            hbuttonbox.set_layout(gtk.BUTTONBOX_END)
            vbox.pack_start(hbuttonbox, expand=False, fill=True)
            self.search_window.add(vbox)
            vbox.show_all()

            new_size = map(
                sum,
                zip(self.search_table.size_request(), scrolled.size_request()))
            self.search_window.set_default_size(*new_size)

        parent = widget.get_toplevel()
        widget_x, widget_y = widget.translate_coordinates(parent, 0, 0)
        widget_allocation = widget.get_allocation()

        # Resize the window to not be out of the parent
        width, height = self.search_window.get_default_size()
        allocation = parent.get_allocation()
        delta_width = allocation.width - (widget_x + width)
        delta_height = allocation.height - (widget_y +
                                            widget_allocation.height + height)
        if delta_width < 0:
            width += delta_width
        if delta_height < 0:
            height += delta_height
        self.search_window.resize(width, height)

        # Move the window under the button
        if hasattr(widget.window, 'get_root_coords'):
            x, y = widget.window.get_root_coords(widget_allocation.x,
                                                 widget_allocation.y)
        else:
            x, y = widget.window.get_origin()
        self.search_window.move(x, y + widget_allocation.height)
        self.search_window.show()
        self.search_window.grab_focus()

        if self.last_search_text.strip() != self.get_text().strip():
            for label, entry in self.search_table.fields:
                if isinstance(entry, gtk.ComboBox):
                    entry.set_active(-1)
                elif isinstance(entry, Dates):
                    entry.set_values(None, None)
                elif isinstance(entry, Selection):
                    entry.treeview.get_selection().unselect_all()
                else:
                    entry.set_text('')
            if self.search_table.fields:
                self.search_table.fields[0][1].grab_focus()
Example #33
0
 def get_domain(self):
     if not self.domain or not isinstance(self.domain, basestring):
         return self.domain
     decoder = PYSONDecoder(self.context)
     return decoder.decode(self.domain)
Example #34
0
    def _exec_action(action, data=None, context=None):
        if context is None:
            context = {}
        if data is None:
            data = {}
        else:
            data = data.copy()
        if 'type' not in (action or {}):
            return

        def add_name_suffix(name):
            if not data.get('ids') or not data.get('model'):
                return name
            max_records = 5
            rec_names = RPCExecute('model', data['model'],
                'read', data['ids'][:max_records], ['rec_name'])
            name_suffix = _(', ').join([x['rec_name'] for x in rec_names])
            if len(data['ids']) > max_records:
                name_suffix += _(u',\u2026')
            return _('%s (%s)') % (name, name_suffix)

        data['action_id'] = action['id']
        if action['type'] == 'ir.action.act_window':
            view_ids = []
            view_mode = None
            if action.get('views', []):
                view_ids = [x[0] 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_model': data.get('model'),
                'active_id': data.get('id'),
                'active_ids': data.get('ids', []),
            }
            ctx.update(rpc.CONTEXT)
            ctx['_user'] = rpc._USER
            decoder = PYSONDecoder(ctx)
            # TODO: comment changes
            action_ctx = context.copy()
            action_ctx.update(decoder.decode(
                    action.get('pyson_context') or '{}'))
            action_ctx.update(ctx)
            action_ctx.update(data.get('extra_context', {}))
            action_ctx['context'] = ctx

            decoder = PYSONDecoder(action_ctx)
            domain = action['pyson_domain']
            order = decoder.decode(action['pyson_order'])
            search_value = decoder.decode(action['pyson_search_value'] or '[]')
            tab_domain = [(n, (action_ctx, d), c)
                for n, d, c in action['domains']]

            name = action.get('name', '')
            if action.get('keyword', '') == 'form_relate':
                name = add_name_suffix(name)

            res_model = action.get('res_model', data.get('res_model'))
            res_id = action.get('res_id', data.get('res_id'))
            limit = action.get('limit')
            if limit is None:
                limit = CONFIG['client.limit']

            Window.create(res_model,
                view_ids=view_ids,
                res_id=res_id,
                domain=domain,
                context=action_ctx,
                order=order,
                mode=view_mode,
                name=name,
                limit=limit,
                search_value=search_value,
                icon=(action.get('icon.rec_name') or ''),
                tab_domain=tab_domain,
                context_model=action['context_model'],
                context_domain=action.get('context_domain', None))
        elif action['type'] == 'ir.action.wizard':
            name = action.get('name', '')
            if action.get('keyword', 'form_action') == 'form_action':
                name = add_name_suffix(name)
            context = copy.deepcopy(context)
            context.update(data.get('extra_context', {}))
            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=name,
                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,
                    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.url':
            if action['url']:
                webbrowser.open(action['url'], new=2)
Example #35
0
    def search_box(self, widget):
        def window_hide(window, *args):
            window.hide()
            self.search_entry.grab_focus()

        def search():
            self.search_popover.popdown()
            text = ''
            for label, entry in self.search_grid.fields:
                if isinstance(entry, Gtk.ComboBoxText):
                    value = quote(entry.get_active_text()) or None
                elif isinstance(entry, (Between, Selection)):
                    value = entry.get_value()
                else:
                    value = quote(entry.get_text()) or None
                if value is not None:
                    text += quote(label) + ': ' + value + ' '
            self.set_text(text)
            self.do_search()
            # Store text after doing the search
            # because domain parser could simplify the text
            self.last_search_text = self.get_text()

        if not self.search_popover:
            self.search_popover = Gtk.Popover()
            self.search_popover.set_relative_to(widget)

            vbox = Gtk.VBox()
            fields = [
                f for f in self.screen.domain_parser.fields.values()
                if f.get('searchable', True) and '.' not in f['name']
            ]
            self.search_grid = Gtk.Grid(column_spacing=3, row_spacing=3)

            # Fill table with fields
            self.search_grid.fields = []
            for i, field in enumerate(fields):
                label = Gtk.Label(label=field['string'],
                                  halign=Gtk.Align.START,
                                  valign=Gtk.Align.START)
                self.search_grid.attach(label, 0, i, 1, 1)
                if field['type'] == 'boolean':
                    entry = Gtk.ComboBoxText()
                    entry.append_text('')
                    selections = (_('True'), _('False'))
                    for selection in selections:
                        entry.append_text(selection)
                elif field['type'] in ['selection', 'multiselection']:
                    selections = tuple(x[1] for x in field['selection'])
                    entry = Selection(selections)
                    entry.set_vexpand(True)
                elif field['type'] in ('date', 'datetime', 'time'):
                    date_format = common.date_format(
                        self.screen.context.get('date_format'))
                    if field['type'] == 'date':
                        entry = Dates(date_format)
                    elif field['type'] in ('datetime', 'time'):
                        time_format = PYSONDecoder({}).decode(field['format'])
                        if field['type'] == 'time':
                            entry = Times(time_format)
                        elif field['type'] == 'datetime':
                            entry = DateTimes(date_format, time_format)
                    entry.connect('activate', lambda *a: search())
                elif field['type'] in ['integer', 'float', 'numeric']:
                    entry = Numbers()
                    entry.connect('activate', lambda *a: search())
                else:
                    entry = Gtk.Entry()
                    entry.connect('activate', lambda *a: search())
                label.set_mnemonic_widget(entry)
                self.search_grid.attach(entry, 1, i, 1, 1)
                self.search_grid.fields.append((field['string'], entry))

            scrolled = Gtk.ScrolledWindow()
            scrolled.add(self.search_grid)
            scrolled.set_shadow_type(Gtk.ShadowType.NONE)
            scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
            vbox.pack_start(scrolled, expand=True, fill=True, padding=0)
            find_button = Gtk.Button(label=_('Find'))
            find_button.connect('clicked', lambda *a: search())
            find_button.set_image(
                common.IconFactory.get_image('tryton-search',
                                             Gtk.IconSize.SMALL_TOOLBAR))
            find_button.set_can_default(True)
            self.search_popover.set_default_widget(find_button)
            hbuttonbox = Gtk.HButtonBox()
            hbuttonbox.pack_start(find_button,
                                  expand=False,
                                  fill=False,
                                  padding=0)
            hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END)
            vbox.pack_start(hbuttonbox, expand=False, fill=True, padding=0)
            self.search_popover.add(vbox)
            vbox.show_all()
            scrolled.set_size_request(
                -1, min(self.search_grid.get_preferred_height()[1], 400))

        self.search_popover.set_pointing_to(
            widget.get_icon_area(Gtk.EntryIconPosition.PRIMARY))
        self.search_popover.popup()
        if self.search_grid.fields:
            self.search_grid.fields[0][1].grab_focus()

        if self.last_search_text.strip() != self.get_text().strip():
            for label, entry in self.search_grid.fields:
                if isinstance(entry, Gtk.ComboBoxText):
                    entry.set_active(-1)
                elif isinstance(entry, Between):
                    entry.set_value(None, None)
                elif isinstance(entry, Selection):
                    entry.treeview.get_selection().unselect_all()
                else:
                    entry.set_text('')