Beispiel #1
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)
Beispiel #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
Beispiel #3
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
Beispiel #4
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)
Beispiel #5
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)
Beispiel #6
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)
Beispiel #7
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()
Beispiel #8
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
Beispiel #9
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)
Beispiel #10
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)
Beispiel #11
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)
Beispiel #12
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))
Beispiel #13
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)
Beispiel #14
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