import re from nmreval.lib.colors import BaseColor, Colors from nmreval.lib.lines import LineStyle from nmreval.lib.symbols import SymbolStyle, make_symbol_pixmap from ..Qt import QtWidgets, QtGui, QtCore class PropertyDelegate(QtWidgets.QStyledItemDelegate): def paint(self, painter: QtGui.QPainter, options: QtWidgets.QStyleOptionViewItem, idx: QtCore.QModelIndex): r = idx.data(QtCore.Qt.DisplayRole) if r is not None: if isinstance(r, BaseColor): painter.save() c = QtGui.QColor(*r.value) rect = options.rect painter.fillRect(rect, QtGui.QBrush(c)) painter.restore() elif isinstance(r, LineStyle): painter.save() pen = QtGui.QPen() pal = QtGui.QGuiApplication.palette() pen.setColor(pal.color(QtGui.QPalette.Text)) pen.setWidth(2) pen.setStyle(r.value) pen.setCapStyle(QtCore.Qt.RoundCap) painter.setPen(pen) rect = options.rect rect.adjust(5, 0, -5, 0) mid = (rect.bottom()+rect.top()) / 2 painter.drawLine(rect.left(), mid, rect.right(), mid) painter.restore() elif isinstance(r, SymbolStyle): painter.save() pen = QtGui.QPen() pal = QtGui.QGuiApplication.palette() pen.setColor(pal.color(QtGui.QPalette.Text)) painter.setPen(pen) pm = make_symbol_pixmap(r) painter.drawPixmap(options.rect.topLeft()+QtCore.QPoint(3, (options.rect.height()-pm.height())/2), pm) style = QtWidgets.QApplication.style() text_rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options, None) text_rect.adjust(5+pm.width(), 0, 0, 0) painter.drawText(text_rect, options.displayAlignment, r.name) painter.restore() else: super().paint(painter, options, idx) def createEditor(self, parent: QtWidgets.QWidget, options: QtWidgets.QStyleOptionViewItem, idx: QtCore.QModelIndex) -> QtWidgets.QWidget: data = idx.data() if isinstance(data, BaseColor): editor = ColorListEditor(parent) elif isinstance(data, LineStyle): editor = LineStyleEditor(parent) elif isinstance(data, SymbolStyle): editor = SymbolStyleEditor(parent) elif isinstance(data, float): editor = SpinBoxEditor(parent) else: editor = super().createEditor(parent, options, idx) return editor def setEditorData(self, editor: QtWidgets.QWidget, idx: QtCore.QModelIndex): data = idx.data() if isinstance(data, (BaseColor, LineStyle, SymbolStyle)): editor.value = data else: super().setEditorData(editor, idx) def setModelData(self, editor: QtWidgets.QWidget, model: QtCore.QAbstractItemModel, idx: QtCore.QModelIndex): data = idx.data() if isinstance(data, (BaseColor, LineStyle, SymbolStyle)): model.setData(idx, editor.value) else: super().setModelData(editor, model, idx) class ColorListEditor(QtWidgets.QComboBox): def __init__(self, parent=None): super().__init__(parent) self.populateList() @QtCore.pyqtProperty(BaseColor, user=True) def value(self): return self.itemData(self.currentIndex()) @value.setter def value(self, val): for i in range(self.count()): if val.name == self.itemData(i).name: self.setCurrentIndex(i) break def populateList(self): for i, colorName in enumerate(Colors): color = QtGui.QColor(*colorName.value) self.insertItem(i, colorName.name) self.setItemData(i, colorName) px = QtGui.QPixmap(self.iconSize()) px.fill(color) self.setItemData(i, QtGui.QIcon(px), QtCore.Qt.DecorationRole) class SpinBoxEditor(QtWidgets.QDoubleSpinBox): def __init__(self, parent=None): super().__init__(parent) self.setValue(1.0) self.setSingleStep(0.1) self.setDecimals(1) @QtCore.pyqtProperty(float, user=True) def value(self): return super().value() @value.setter def value(self, val): super().setValue(val) class LineStyleEditor(QtWidgets.QComboBox): def __init__(self, parent=None): super().__init__(parent=parent) self.setItemDelegate(LineStyleDelegate()) self.populate() @QtCore.pyqtProperty(int, user=True) def value(self): return self.itemData(self.currentIndex()) @value.setter def value(self, val): for i in range(self.count()): if val == self.itemData(i): self.setCurrentIndex(i) break def populate(self): for i, style in enumerate(LineStyle): self.insertItem(i, re.sub(r'([A-Z])', r' \g<1>', style.name)) self.setItemData(i, style) def paintEvent(self, evt: QtGui.QPaintEvent): if self.currentData() is not None: painter = QtWidgets.QStylePainter(self) opt = QtWidgets.QStyleOptionComboBox() self.initStyleOption(opt) painter.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt) pen = QtGui.QPen() pal = QtGui.QGuiApplication.palette() pen.setColor(pal.color(QtGui.QPalette.Text)) pen.setWidth(2) pen.setStyle(self.currentData().value) pen.setCapStyle(QtCore.Qt.RoundCap) painter.setPen(pen) rect = painter.style().subControlRect(QtWidgets.QStyle.CC_ComboBox, opt, QtWidgets.QStyle.SC_ComboBoxEditField, None) rect.adjust(+10, 0, -10, 0) mid = (rect.bottom() + rect.top()) / 2 painter.drawLine(rect.left(), mid, rect.right(), mid) painter.end() else: super().paintEvent(evt) class LineStyleDelegate(QtWidgets.QStyledItemDelegate): def paint(self, painter, option, index): data = index.data(QtCore.Qt.UserRole) if data is not None: pen = QtGui.QPen() pal = QtGui.QGuiApplication.palette() pen.setColor(pal.color(QtGui.QPalette.Text)) pen.setWidth(2) pen.setStyle(data.value) pen.setCapStyle(QtCore.Qt.RoundCap) painter.setPen(pen) rect = option.rect rect.adjust(+10, 0, -10, 0) mid = (rect.bottom()+rect.top()) / 2 painter.drawLine(rect.left(), mid, rect.right(), mid) else: QtWidgets.QStyledItemDelegate.paint(self, painter, option, index) class SymbolStyleEditor(QtWidgets.QComboBox): def __init__(self, parent=None): super().__init__(parent=parent) self.populate() @QtCore.pyqtProperty(SymbolStyle, user=True) def value(self): return self.itemData(self.currentIndex()) @value.setter def value(self, val): for i in range(self.count()): if val == self.itemData(i): self.setCurrentIndex(i) break def populate(self): for i, s in enumerate(SymbolStyle): self.insertItem(i, re.sub(r'([A-Z])', r' \g<1>', s.name)) self.setItemData(i, s) self.setItemData(i, make_symbol_pixmap(s), QtCore.Qt.DecorationRole) class HeaderDelegate(QtWidgets.QStyledItemDelegate): def paint(self, painter: QtGui.QPainter, option: QtWidgets.QStyleOptionViewItem, index: QtCore.QModelIndex): header_option = QtWidgets.QStyleOptionHeader() header_option.rect = option.rect style = QtWidgets.QApplication.style() style.drawControl(QtWidgets.QStyle.CE_HeaderSection, header_option, painter) text_rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, option, None) text_rect.adjust(2, 0, 0, 0) if option.state & QtWidgets.QStyle.State_Selected: painter.fillRect(option.rect, option.palette.highlight()) painter.drawText(text_rect, option.displayAlignment, index.data(QtCore.Qt.DisplayRole))