Last active
February 11, 2016 20:49
-
-
Save estan/c051d1f798c4c46caa7d to your computer and use it in GitHub Desktop.
Fixed experimentation with custom delegate + editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from functools import partial | |
from sys import argv, exit | |
from PyQt5.QtCore import (Qt, QAbstractTableModel, QModelIndex, pyqtProperty, | |
pyqtSignal, QVariant) | |
from PyQt5.QtWidgets import (QApplication, QFrame, QStyledItemDelegate, QTableView, | |
QFormLayout, QSlider) | |
class MyAbstractItem(object): | |
def data(self, role): | |
raise NotImplementedError | |
def setData(self, value, role): | |
raise NotImplementedError | |
class MyTextItem(MyAbstractItem): | |
def __init__(self, text): | |
self._text = text | |
def data(self, role): | |
if role != Qt.DisplayRole and role != Qt.EditRole: | |
return None | |
return self._text | |
def setData(self, text, role): | |
if role != Qt.EditRole: | |
return False | |
self._text = text | |
return True | |
class MyCoolItem(MyAbstractItem): | |
def __init__(self, values): | |
self._values = values #: dict: Maps names to values | |
def data(self, role): | |
if role == Qt.DisplayRole: | |
return str(self._values) # Just as string for now. | |
elif role == Qt.EditRole: | |
return self._values | |
return None | |
def setData(self, values, role): | |
if role != Qt.EditRole: | |
return False | |
self._values = values | |
return True | |
class MyCoolEditor(QFrame): | |
def __init__(self, parent=None): | |
super(MyCoolEditor, self).__init__(parent) | |
self._values = None | |
self.setAutoFillBackground(True) | |
self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) | |
self.setLayout(QFormLayout()) | |
@pyqtProperty(QVariant, user=True) | |
def values(self): | |
return self._values | |
@values.setter | |
def values(self, values): | |
self._values = values | |
while self.layout().count() > 0: | |
self.layout().takeAt(0) | |
for name, value in values.items(): | |
slider = QSlider(Qt.Horizontal) | |
slider.setMinimum(0) | |
slider.setMaximum(100) | |
slider.setValue(value) | |
slider.valueChanged.connect(partial(self._setValue, name)) | |
self.layout().addRow(name + ':', slider) | |
def _setValue(self, name, value): | |
self._values[name] = value | |
class MyCoolDelegate(QStyledItemDelegate): | |
def createEditor(self, parent, option, index): | |
values = index.data(Qt.EditRole) | |
if isinstance(values, dict): | |
return MyCoolEditor(parent) | |
return super(MyCoolDelegate, self).createEditor(parent, option, index) | |
def updateEditorGeometry(self, editor, option, index): | |
editor.setGeometry(option.rect.x(), | |
option.rect.y() + option.rect.height(), 200, 60) | |
class MyModel(QAbstractTableModel): | |
def __init__(self, headers, rows, parent=None): | |
super(MyModel, self).__init__(parent) | |
self._headers = headers | |
self._rows = rows | |
def rowCount(self, parent=QModelIndex()): | |
if parent.isValid(): | |
return 0 | |
return len(self._rows) | |
def columnCount(self, parent=QModelIndex()): | |
return len(self._headers) | |
def headerData(self, section, orientation, role=Qt.DisplayRole): | |
if orientation != Qt.Horizontal or role != Qt.DisplayRole: | |
return None | |
return self._headers[section] | |
def data(self, index, role=Qt.DisplayRole): | |
if not index.isValid(): | |
return None | |
# Delegate to the item at the given index. | |
return self._rows[index.row()][index.column()].data(role) | |
def setData(self, index, value, role=Qt.EditRole): | |
if not index.isValid(): | |
return False | |
# Delegate to the item at the given index. | |
if self._rows[index.row()][index.column()].setData(value, role): | |
self.dataChanged.emit(index, index) | |
return True | |
return False | |
def flags(self, index): | |
if not index.isValid(): | |
return Qt.NoItemFlags | |
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable | |
app = None | |
def main(): | |
global app | |
app = QApplication(argv) | |
model = MyModel( | |
headers=['Cool Column', 'Text Column', 'Text Column'], | |
rows=[ | |
[MyCoolItem({'a': 10, 'b': 20}), MyTextItem('c'), MyTextItem('c')], | |
[MyCoolItem({'d': 30, 'e': 50}), MyTextItem('f'), MyTextItem('c')], | |
[MyCoolItem({'d': 30, 'e': 50}), MyTextItem('f'), MyTextItem('c')], | |
[MyCoolItem({'d': 30, 'e': 50}), MyTextItem('f'), MyTextItem('c')], | |
[MyCoolItem({'d': 30, 'e': 50}), MyTextItem('f'), MyTextItem('c')] | |
], | |
parent=app | |
) | |
delegate = MyCoolDelegate(model) | |
view = QTableView() | |
view.setItemDelegateForColumn(0, delegate) | |
view.setModel(model) | |
view.show() | |
exit(app.exec_()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment