class DictMultiSelectionEntry(DictEntry): expand = False def create_widget(self): widget = Gtk.ScrolledWindow() widget.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) widget.set_shadow_type(Gtk.ShadowType.ETCHED_IN) widget.set_size_request(100, 100) model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.tree = TreeViewControl() self.tree.set_model(model) self.tree.set_search_column(1) self.tree.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) self.tree.set_headers_visible(False) selection = self.tree.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect('changed', self._changed) widget.add(self.tree) self.selection = self.definition['selection'] if self.definition.get('sort', True): self.selection.sort(key=operator.itemgetter(1)) for value, name in self.selection: name = str(name) model.append((value, name)) name_column = Gtk.TreeViewColumn() name_cell = Gtk.CellRendererText() name_column.pack_start(name_cell, expand=True) name_column.add_attribute(name_cell, 'text', 1) self.tree.append_column(name_column) return widget def get_value(self): model, paths = self.tree.get_selection().get_selected_rows() return [model[path][0] for path in paths] def set_value(self, value): value2path = {v: idx for idx, (v, _) in enumerate(self.selection)} selection = self.tree.get_selection() selection.handler_block_by_func(self._changed) try: selection.unselect_all() for v in value: if v in value2path: selection.select_path(value2path[v]) finally: selection.handler_unblock_by_func(self._changed) def _changed(self, selection): GLib.idle_add(self.parent_widget._focus_out) def set_readonly(self, readonly): selection = self.tree.get_selection() selection.set_select_function(lambda *a: not readonly)
class MultiSelection(Widget, SelectionMixin): expand = True def __init__(self, view, attrs): super(MultiSelection, self).__init__(view, attrs) if int(attrs.get('yexpand', self.expand)): self.widget = gtk.ScrolledWindow() self.widget.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.widget.set_shadow_type(gtk.SHADOW_ETCHED_IN) else: self.widget = gtk.VBox() self.widget.get_accessible().set_name(attrs.get('string', '')) self.model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING) self.tree = TreeViewControl() self.tree.set_model(self.model) self.tree.set_search_column(1) self.tree.connect('focus-out-event', lambda *a: self._focus_out()) self.tree.set_headers_visible(False) selection = self.tree.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) selection.connect('changed', self.changed) self.widget.add(self.tree) name_column = gtk.TreeViewColumn() name_cell = gtk.CellRendererText() name_column.pack_start(name_cell) name_column.add_attribute(name_cell, 'text', 1) self.tree.append_column(name_column) self.nullable_widget = False self.init_selection() self.id2path = {} def _color_widget(self): return self.tree def _readonly_set(self, readonly): super(MultiSelection, self)._readonly_set(readonly) set_widget_style(self.tree, not readonly) selection = self.tree.get_selection() selection.set_select_function(lambda *a: not readonly) @property def modified(self): if self.record and self.field: group = set(r.id for r in self.field.get_client(self.record)) value = set(self.get_value()) return value != group return False def changed(self, selection): def focus_out(): if self.widget.props.window: self._focus_out() # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) def get_value(self): model, paths = self.tree.get_selection().get_selected_rows() return [model[path][0] for path in paths] def set_value(self, record, field): field.set_client(record, self.get_value()) def display(self, record, field): selection = self.tree.get_selection() selection.handler_block_by_func(self.changed) try: # Remove select_function to allow update, # it will be set back in the super call selection.set_select_function(lambda *a: True) self.update_selection(record, field) self.model.clear() if field is None: return id2path = {} for idx, (value, name) in enumerate(self.selection): self.model.append((value, name)) id2path[value] = idx selection.unselect_all() group = field.get_client(record) for element in group: if (element not in group.record_removed and element not in group.record_deleted and element.id in id2path): selection.select_path(id2path[element.id]) super(MultiSelection, self).display(record, field) finally: selection.handler_unblock_by_func(self.changed)
class MultiSelection(Widget, SelectionMixin): expand = True def __init__(self, view, attrs): super(MultiSelection, self).__init__(view, attrs) self.widget = gtk.ScrolledWindow() self.widget.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.widget.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.widget.get_accessible().set_name(attrs.get('string', '')) self.model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING) self.tree = TreeViewControl() self.tree.set_model(self.model) self.tree.set_search_column(1) self.tree.connect('focus-out-event', lambda *a: self._focus_out()) self.tree.set_headers_visible(False) selection = self.tree.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) selection.connect('changed', self.changed) self.widget.add(self.tree) name_column = gtk.TreeViewColumn() name_cell = gtk.CellRendererText() name_column.pack_start(name_cell) name_column.add_attribute(name_cell, 'text', 1) self.tree.append_column(name_column) self.nullable_widget = False self.init_selection() self.id2path = {} @property def modified(self): if self.record and self.field: group = set(r.id for r in self.field.get_client(self.record)) value = set(self.get_value()) return value != group return False def changed(self, selection): def focus_out(): if self.widget.props.window: self._focus_out() # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) def get_value(self): model, paths = self.tree.get_selection().get_selected_rows() return [model[path][0] for path in paths] def set_value(self, record, field): field.set_client(record, self.get_value()) def display(self, record, field): selection = self.tree.get_selection() selection.handler_block_by_func(self.changed) try: self.update_selection(record, field) super(MultiSelection, self).display(record, field) self.model.clear() if field is None: return id2path = {} for idx, (value, name) in enumerate(self.selection): self.model.append((value, name)) id2path[value] = idx selection.unselect_all() group = field.get_client(record) for element in group: if (element not in group.record_removed and element not in group.record_deleted and element.id in id2path): selection.select_path(id2path[element.id]) finally: selection.handler_unblock_by_func(self.changed)