class VariableEditor(QWidget): """An editor widget for a variable. Can edit the variable name, and its attributes dictionary. """ variable_changed = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.var = None self.setup_gui() def setup_gui(self): layout = QVBoxLayout() self.setLayout(layout) self.main_form = QFormLayout() self.main_form.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) layout.addLayout(self.main_form) self._setup_gui_name() self._setup_gui_labels() def _setup_gui_name(self): self.name_edit = QLineEdit() self.main_form.addRow("Name:", self.name_edit) self.name_edit.editingFinished.connect(self.on_name_changed) def _setup_gui_labels(self): vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(1) self.labels_edit = QTreeView() self.labels_edit.setEditTriggers(QTreeView.CurrentChanged) self.labels_edit.setRootIsDecorated(False) self.labels_model = DictItemsModel() self.labels_edit.setModel(self.labels_model) self.labels_edit.selectionModel().selectionChanged.connect( self.on_label_selection_changed) # Necessary signals to know when the labels change self.labels_model.dataChanged.connect(self.on_labels_changed) self.labels_model.rowsInserted.connect(self.on_labels_changed) self.labels_model.rowsRemoved.connect(self.on_labels_changed) vlayout.addWidget(self.labels_edit) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) hlayout.setSpacing(1) self.add_label_action = QAction( "+", self, toolTip="Add a new label.", triggered=self.on_add_label, enabled=False, shortcut=QKeySequence(QKeySequence.New)) self.remove_label_action = QAction( unicodedata.lookup("MINUS SIGN"), self, toolTip="Remove selected label.", triggered=self.on_remove_label, enabled=False, shortcut=QKeySequence(QKeySequence.Delete)) button_size = gui.toolButtonSizeHint() button_size = QSize(button_size, button_size) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.add_label_action) hlayout.addWidget(button) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.remove_label_action) hlayout.addWidget(button) hlayout.addStretch(10) vlayout.addLayout(hlayout) self.main_form.addRow("Labels:", vlayout) def set_data(self, var): """Set the variable to edit. """ self.clear() self.var = var if var is not None: self.name_edit.setText(var.name) self.labels_model.set_dict(dict(var.attributes)) self.add_label_action.setEnabled(True) else: self.add_label_action.setEnabled(False) self.remove_label_action.setEnabled(False) def get_data(self): """Retrieve the modified variable. """ name = str(self.name_edit.text()) labels = self.labels_model.get_dict() # Is the variable actually changed. if self.var is not None and not self.is_same(): var = type(self.var)(name) var.attributes.update(labels) self.var = var else: var = self.var return var def is_same(self): """Is the current model state the same as the input. """ name = str(self.name_edit.text()) labels = self.labels_model.get_dict() return (self.var is not None and name == self.var.name and labels == self.var.attributes) def clear(self): """Clear the editor state. """ self.var = None self.name_edit.setText("") self.labels_model.set_dict({}) def maybe_commit(self): if not self.is_same(): self.commit() def commit(self): """Emit a ``variable_changed()`` signal. """ self.variable_changed.emit() @Slot() def on_name_changed(self): self.maybe_commit() @Slot() def on_labels_changed(self, *args): self.maybe_commit() @Slot() def on_add_label(self): self.labels_model.appendRow([QStandardItem(""), QStandardItem("")]) row = self.labels_model.rowCount() - 1 index = self.labels_model.index(row, 0) self.labels_edit.edit(index) @Slot() def on_remove_label(self): rows = self.labels_edit.selectionModel().selectedRows() if rows: row = rows[0] self.labels_model.removeRow(row.row()) @Slot() def on_label_selection_changed(self): selected = self.labels_edit.selectionModel().selectedRows() self.remove_label_action.setEnabled(bool(len(selected)))
class VariableEditor(QWidget): """An editor widget for a variable. Can edit the variable name, and its attributes dictionary. """ variable_changed = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.var = None self.setup_gui() def setup_gui(self): layout = QVBoxLayout() self.setLayout(layout) self.main_form = QFormLayout() self.main_form.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) layout.addLayout(self.main_form) self._setup_gui_name() self._setup_gui_labels() def _setup_gui_name(self): class OrangeLineEdit(QLineEdit): def keyPressEvent(self, event): if event.key() in [Qt.Key_Return, Qt.Key_Enter]: self.parent().on_name_changed() else: super().keyPressEvent(event) self.name_edit = OrangeLineEdit() self.main_form.addRow("Name:", self.name_edit) self.name_edit.editingFinished.connect(self.on_name_changed) def _setup_gui_labels(self): vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(1) self.labels_edit = QTreeView() self.labels_edit.setEditTriggers(QTreeView.CurrentChanged) self.labels_edit.setRootIsDecorated(False) self.labels_model = DictItemsModel() self.labels_edit.setModel(self.labels_model) self.labels_edit.selectionModel().selectionChanged.connect( self.on_label_selection_changed) # Necessary signals to know when the labels change self.labels_model.dataChanged.connect(self.on_labels_changed) self.labels_model.rowsInserted.connect(self.on_labels_changed) self.labels_model.rowsRemoved.connect(self.on_labels_changed) vlayout.addWidget(self.labels_edit) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) hlayout.setSpacing(1) self.add_label_action = QAction( "+", self, toolTip="Add a new label.", triggered=self.on_add_label, enabled=False, shortcut=QKeySequence(QKeySequence.New), ) self.remove_label_action = QAction( unicodedata.lookup("MINUS SIGN"), self, toolTip="Remove selected label.", triggered=self.on_remove_label, enabled=False, shortcut=QKeySequence(QKeySequence.Delete), ) button_size = gui.toolButtonSizeHint() button_size = QSize(button_size, button_size) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.add_label_action) hlayout.addWidget(button) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.remove_label_action) hlayout.addWidget(button) hlayout.addStretch(10) vlayout.addLayout(hlayout) self.main_form.addRow("Labels:", vlayout) def set_data(self, var): """Set the variable to edit. """ self.clear() self.var = var if var is not None: self.name_edit.setText(var.name) self.labels_model.set_dict(dict(var.attributes)) self.add_label_action.setEnabled(True) else: self.add_label_action.setEnabled(False) self.remove_label_action.setEnabled(False) def get_data(self): """Retrieve the modified variable. """ name = str(self.name_edit.text()).strip() labels = self.labels_model.get_dict() # Is the variable actually changed. if self.var is not None and not self.is_same(): var = type(self.var)(name) var.attributes.update(labels) self.var = var else: var = self.var return var def is_legal(self): name = str(self.name_edit.text()).strip() return not len(name) == 0 def is_same(self): """Is the current model state the same as the input. """ name = str(self.name_edit.text()).strip() labels = self.labels_model.get_dict() return (self.var is not None and name == self.var.name and labels == self.var.attributes) def clear(self): """Clear the editor state. """ self.var = None self.name_edit.setText("") self.labels_model.set_dict({}) def maybe_commit(self): if not self.is_same() and self.is_legal(): self.commit() def commit(self): """Emit a ``variable_changed()`` signal. """ self.variable_changed.emit() @Slot() def on_name_changed(self): self.maybe_commit() @Slot() def on_labels_changed(self, *args): self.maybe_commit() @Slot() def on_add_label(self): self.labels_model.appendRow([QStandardItem(""), QStandardItem("")]) row = self.labels_model.rowCount() - 1 index = self.labels_model.index(row, 0) self.labels_edit.edit(index) @Slot() def on_remove_label(self): rows = self.labels_edit.selectionModel().selectedRows() if rows: row = rows[0] self.labels_model.removeRow(row.row()) @Slot() def on_label_selection_changed(self): selected = self.labels_edit.selectionModel().selectedRows() self.remove_label_action.setEnabled(bool(len(selected)))