class CompositionElementalWidget(_CompositionWidget): class _CompositionModel(QAbstractTableModel): def __init__(self): QAbstractTableModel.__init__(self) self.composition = OrderedDict() def rowCount(self, *args, **kwargs): return len(self.composition) def columnCount(self, *args, **kwargs): return 2 def data(self, index, role): if not index.isValid() or \ not (0 <= index.row() < len(self.composition)): return None if role == Qt.TextAlignmentRole: return Qt.AlignCenter if role != Qt.DisplayRole: return None z, fraction = list(self.composition.items())[index.row()] column = index.column() if column == 0: if z is None: return 'none' else: return str(get_symbol(z)) elif column == 1: return str(fraction) def headerData(self, section , orientation, role): if role != Qt.DisplayRole: return None if orientation == Qt.Horizontal: if section == 0: return 'Element' elif section == 1: return 'Fraction' elif orientation == Qt.Vertical: return str(section + 1) def flags(self, index): if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index) | Qt.ItemIsEditable) def setData(self, index, value, role=Qt.EditRole): if not index.isValid() or \ not (0 <= index.row() < len(self.composition)): return False z = list(self.composition.keys())[index.row()] column = index.column() if column == 0: if value in self.composition: return False fraction = self.composition.pop(z) self.composition[value] = fraction elif column == 1: self.composition[z] = float(value) self.dataChanged.emit(index, index) return True def insertRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginInsertRows(parent, row, row + count - 1) if None in self.composition: return False self.composition[None] = 0.0 self.endInsertRows() return True def removeRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginRemoveRows(parent, row, count + row - 1) keys = list(self.composition.keys()) for key in keys[:row] + keys[row + count:]: self.composition.pop(key) self.endRemoveRows() return True class _CompositionDelegate(QItemDelegate): def __init__(self, parent=None): QItemDelegate.__init__(self, parent) def createEditor(self, parent, option, index): column = index.column() if column == 0: editor = PeriodicTableDialog(parent) editor.setMultipleSelection(False) editor.setRequiresSelection(True) return editor elif column == 1: editor = QLineEdit(parent) editor.setValidator(QDoubleValidator()) return editor else: return QItemDelegate.createEditor(self, parent, option, index) def setEditorData(self, editor, index): text = index.model().data(index, Qt.DisplayRole) column = index.column() if column == 0: if text != 'none': editor.setSelection(text) elif column == 1: editor.setText(text) else: QItemDelegate.setEditorData(self, editor, index) def setModelData(self, editor, model, index): column = index.column() if column == 0: model.setData(index, editor.selection()) elif column == 1: model.setData(index, editor.text()) else: return QItemDelegate.setModelData(self, editor, model, index) def __init__(self, parent=None): _CompositionWidget.__init__(self, CompositionElemental, parent) def _init_ui(self): # Widgets model = self._CompositionModel() self._table = QTableView() self._table.setModel(model) self._table.setItemDelegate(self._CompositionDelegate(self)) self._table.horizontalHeader().setStretchLastSection(True) self._toolbar = QToolBar() action_add = self._toolbar.addAction(getIcon("list-add"), "Add layer") action_remove = self._toolbar.addAction(getIcon("list-remove"), "Remove layer") # Layouts layout = _CompositionWidget._init_ui(self) layout.addRow(self._table) layout.addRow(self._toolbar) # Signals action_add.triggered.connect(self._on_add) action_remove.triggered.connect(self._on_remove) model.dataChanged.connect(self.edited) model.rowsInserted.connect(self.edited) model.rowsRemoved.connect(self.edited) return layout def _on_add(self): index = self._table.selectionModel().currentIndex() model = self._table.model() model.insertRows(index.row() + 1) def _on_remove(self): selection = self._table.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Window layer", "Select a layer") return model = self._table.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.removeRow(row) def _create_parameter(self): return self.CLASS('wt%') def parameter(self, parameter=None): parameter = _CompositionWidget.parameter(self, parameter) parameter.update(self._table.model().composition) return parameter def setParameter(self, condition): _CompositionWidget.setParameter(self, condition) self._table.model().composition.update(condition) self._table.model().reset() def setReadOnly(self, state): _CompositionWidget.setReadOnly(self, state) if state: trigger = QTableView.EditTrigger.NoEditTriggers else: trigger = QTableView.EditTrigger.AllEditTriggers self._table.setEditTriggers(trigger) self._toolbar.setEnabled(not state) def isReadOnly(self): return _CompositionWidget.isReadOnly(self) and \ self._table.editTriggers() == QTableView.EditTrigger.NoEditTriggers and \ not self._toolbar.isEnabled()
class SpecimenPositionListWidget(ParameterWidget): class _SpecimenPositionModel(QAbstractTableModel): def __init__(self): QAbstractTableModel.__init__(self) self.positions = [] def rowCount(self, *args, **kwargs): return len(self.positions) def columnCount(self, *args, **kwargs): return 5 def data(self, index, role): if not index.isValid() or not (0 <= index.row() < len(self.positions)): return None if role != Qt.DisplayRole: return None position = self.positions[index.row()] column = index.column() if column == 0: return str(position.x) if position.x is not None else '' elif column == 1: return str(position.y) if position.y is not None else '' elif column == 2: return str(position.z) if position.z is not None else '' elif column == 3: return str(position.r) if position.r is not None else '' elif column == 4: return str(position.t) if position.t is not None else '' def headerData(self, section , orientation, role): if role != Qt.DisplayRole: return None if orientation == Qt.Horizontal: if section == 0: return 'X' elif section == 1: return 'Y' elif section == 2: return 'Z' elif section == 3: return 'R' elif section == 4: return 'T' elif orientation == Qt.Vertical: return str(section + 1) def flags(self, index): if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index) | Qt.ItemIsEditable) def setData(self, index, value, role=Qt.EditRole): if not index.isValid() or \ not (0 <= index.row() < len(self.positions)): return False position = self.positions[index.row()] column = index.column() if column == 0: position.x = value elif column == 1: position.y = value elif column == 2: position.z = value elif column == 3: position.r = value elif column == 4: position.t = value return True def insertRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginInsertRows(parent, row, row + count - 1) for i in range(count): self.positions.insert(row + i, SpecimenPosition()) self.endInsertRows() return True def removeRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginRemoveRows(parent, row, row + count - 1) self.positions = self.positions[:row] + self.positions[row + count:] self.endRemoveRows() return True class _SpecimenPositionDelegate(QItemDelegate): def __init__(self, parent=None): QItemDelegate.__init__(self, parent) def createEditor(self, parent, option, index): column = index.column() if column == 0: return NumericalAttributeLineEdit(SpecimenPosition.x, parent) elif column == 1: return NumericalAttributeLineEdit(SpecimenPosition.y, parent) elif column == 2: return NumericalAttributeLineEdit(SpecimenPosition.y, parent) elif column == 3: return NumericalAttributeLineEdit(SpecimenPosition.y, parent) elif column == 4: return NumericalAttributeLineEdit(SpecimenPosition.y, parent) else: return QItemDelegate.createEditor(self, parent, option, index) def setEditorData(self, editor, index): text = index.model().data(index, Qt.DisplayRole) column = index.column() if column == 0: editor.setText(text) elif column == 1: editor.setText(text) elif column == 2: editor.setText(text) elif column == 3: editor.setText(text) elif column == 4: editor.setText(text) else: QItemDelegate.setEditorData(self, editor, index) def setModelData(self, editor, model, index): column = index.column() if column == 0: model.setData(index, editor.text()) elif column == 1: model.setData(index, editor.text()) elif column == 2: model.setData(index, editor.text()) elif column == 3: model.setData(index, editor.text()) elif column == 4: model.setData(index, editor.text()) else: return QItemDelegate.setModelData(self, editor, model, index) def __init__(self, parent=None): ParameterWidget.__init__(self, object, parent) def _init_ui(self): # Widgets self._table = QTableView() self._table.setModel(self._SpecimenPositionModel()) self._table.setItemDelegate(self._SpecimenPositionDelegate(self)) self._table.horizontalHeader().setStretchLastSection(True) self._toolbar = QToolBar() action_add = self._toolbar.addAction(getIcon("list-add"), "Add layer") action_remove = self._toolbar.addAction(getIcon("list-remove"), "Remove layer") # Layouts layout = ParameterWidget._init_ui(self) layout.addRow(self._table) layout.addRow(self._toolbar) # Signals action_add.triggered.connect(self._on_add) action_remove.triggered.connect(self._on_remove) return layout def _on_add(self): index = self._table.selectionModel().currentIndex() model = self._table.model() model.insertRows(index.row() + 1) def _on_remove(self): selection = self._table.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Specimen position", "Select a position") return model = self._table.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.removeRow(row) def parameter(self): positions = [] for position in self._table.model().positions: positions.append(SpecimenPosition(position.x, position.y, position.z, position.r, position.t)) return positions def setParameter(self, positions): model = self._table.model() model.positions = positions model.reset() def positions(self): return self.parameter() def setPositions(self, positions): self.setParameter(positions) def setReadOnly(self, state): ParameterWidget.setReadOnly(self, state) if state: trigger = QTableView.EditTrigger.NoEditTriggers else: trigger = QTableView.EditTrigger.AllEditTriggers self._table.setEditTriggers(trigger) self._toolbar.setEnabled(not state) def isReadOnly(self): return ParameterWidget.isReadOnly(self) and \ self._table.editTriggers() == QTableView.EditTrigger.NoEditTriggers and \ not self._toolbar.isEnabled()
class WindowWidget(ParameterWidget): class _WindowModel(QAbstractTableModel): def __init__(self): QAbstractTableModel.__init__(self) self.layers = [] def rowCount(self, *args, **kwargs): return len(self.layers) def columnCount(self, *args, **kwargs): return 2 def data(self, index, role): if not index.isValid() or not (0 <= index.row() < len(self.layers)): return None if role != Qt.DisplayRole: return None layer = self.layers[index.row()] column = index.column() if column == 0: return layer.material elif column == 1: return '%s' % layer.thickness def headerData(self, section , orientation, role): if role != Qt.DisplayRole: return None if orientation == Qt.Horizontal: if section == 0: return 'Material' elif section == 1: return 'Thickness' elif orientation == Qt.Vertical: return str(section + 1) def flags(self, index): if not index.isValid(): return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index) | Qt.ItemIsEditable) def setData(self, index, value, role=Qt.EditRole): if not index.isValid() or \ not (0 <= index.row() < len(self.layers)): return False layer = self.layers[index.row()] column = index.column() if column == 0: layer.material = value elif column == 1: layer.thickness = value self.dataChanged.emit(index, index) return True def insertRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginInsertRows(parent, row, row + count - 1) for i in range(count): self.layers.insert(row + i, WindowLayer("unknown", 0.0)) self.endInsertRows() return True def removeRows(self, row, count=1, parent=None): if count == 0: return False if parent is None: parent = QModelIndex() self.beginRemoveRows(parent, row, row + count - 1) self.layers = self.layers[:row] + self.layers[row + count:] self.endRemoveRows() return True class _WindowDelegate(QItemDelegate): def __init__(self, parent=None): QItemDelegate.__init__(self, parent) def createEditor(self, parent, option, index): column = index.column() if column == 0: return TextAttributeLineEdit(WindowLayer.material, parent) elif column == 1: return NumericalAttributeLineEdit(WindowLayer.thickness, parent) else: return QItemDelegate.createEditor(self, parent, option, index) def setEditorData(self, editor, index): text = index.model().data(index, Qt.DisplayRole) column = index.column() if column == 0: editor.setText(text) elif column == 1: editor.setText(text) else: QItemDelegate.setEditorData(self, editor, index) def setModelData(self, editor, model, index): column = index.column() if column == 0: model.setData(index, editor.text()) elif column == 1: model.setData(index, editor.text()) else: return QItemDelegate.setModelData(self, editor, model, index) def __init__(self, parent=None): ParameterWidget.__init__(self, Window, parent) def _init_ui(self): # Widgets model = self._WindowModel() self._table = QTableView() self._table.setModel(model) self._table.setItemDelegate(self._WindowDelegate(self)) self._table.horizontalHeader().setStretchLastSection(True) self._toolbar = QToolBar() action_add = self._toolbar.addAction(getIcon("list-add"), "Add layer") action_remove = self._toolbar.addAction(getIcon("list-remove"), "Remove layer") # Layouts layout = ParameterWidget._init_ui(self) layout.addRow(self._table) layout.addRow(self._toolbar) # Signals action_add.triggered.connect(self._on_add) action_remove.triggered.connect(self._on_remove) model.dataChanged.connect(self.edited) model.rowsInserted.connect(self.edited) model.rowsRemoved.connect(self.edited) return layout def _on_add(self): index = self._table.selectionModel().currentIndex() model = self._table.model() model.insertRows(index.row() + 1) def _on_remove(self): selection = self._table.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Window layer", "Select a layer") return model = self._table.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.removeRow(row) def parameter(self, parameter=None): parameter = ParameterWidget.parameter(self, parameter) parameter.layers.clear() for layer in self._table.model().layers: parameter.append_layer(layer.material, layer.thickness) # copy return parameter def setParameter(self, window): model = self._table.model() model.layers = window.layers model.reset() def window(self): return self.parameter() def setWindow(self, window): self.setParameter(window) def setReadOnly(self, state): ParameterWidget.setReadOnly(self, state) if state: trigger = QTableView.EditTrigger.NoEditTriggers else: trigger = QTableView.EditTrigger.AllEditTriggers self._table.setEditTriggers(trigger) self._toolbar.setEnabled(not state) def isReadOnly(self): return ParameterWidget.isReadOnly(self) and \ self._table.editTriggers() == QTableView.EditTrigger.NoEditTriggers and \ not self._toolbar.isEnabled()