Base mock:
Hello,
What I have:
- QAbstractListModel that contains my items.
- QListView that will contain individual widgets or delegates.
- Each individual item in the QListView needs to have 3 editable areas in the widget.
Preface:
I am having trouble figuring out how to get a proper layered widget system working. If you look at the attached image, each box in green represents an 'item' in my model, as well as an invidual item to the user in my view, while the data on the 'widgets' inside of each green box is data from and relating to that item in the model.
So if somebody edits QLineEdit1 in Widget 1, I expect that the data will be updated in the model for the item that Widget1 relates to.
Problem:
I can't figure out how to have multiple editors working inside the same delegate. If I click on the item (the QLineEdit), the index is of course going to relate to the main widget item (the green box) - I can't find anything to tell me that I've clicked on the painted QLineEdit, so if I just return an editable QLineEdit inside of createEditor, it's just going to be a generic one, placed wherever, and I need to figure out which widget it relates to so I can update the model correct, and can also make the editor draw in the position of where I clicked on the painted QLineEdit.
I can't figure out how to get a good system working. I understand delegates, I understand MVC, all of that is fine. I just don't know if what I'm trying to do is possible or I need to switch it up and do something else. If I do need to try something else, I'd appreciate some suggestions.
Thanks.
Here's some basic code (this doesn't have individual items painting inside the widgets right now, but has the base set up):
import sys
from PySide import QtCore, QtGui
DELEGATE_DATA_ROLE = 37
DELEGATE_INDEX = 0
class ItemWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(ItemWidget, self).__init__(parent=parent)
self.main_layout = QtGui.QVBoxLayout()
self.setLayout(self.main_layout)
class ItemDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(ItemDelegate, self).__init__(parent=parent)
def sizeHint(self, option, index):
return QtCore.QSize(80, 80)
def createEditor(self, parent, option, index):
editor = QtGui.QLineEdit(parent)
editor.setFixedWidth(200)
editor.setFixedHeight(50)
return editor
def setEditorData(self, editor, index):
item_str = index.data(QtCore.Qt.DisplayRole)
description = item_str['description']
editor.setValue(description)
def setEditorData(self, editor, index):
print 'running setEditorData'
if index.column() == DELEGATE_INDEX:
print 'delegate'
else:
QtGui.QStyledItemDelegate(self, editor, index)
class ItemModel(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(ItemModel, self).__init__(parent=parent)
self.items = [
{'one': '1', 'name': 'one', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
{'two': '2', 'name': 'two', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
{'three': '3', 'name': 'three', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
{'four': '4', 'name': 'four', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
{'five': '5', 'name': 'five', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
{'six': '6', 'name': 'six', 'thumbnail': 'charlie.jpg', 'description': 'aabb'}
]
def rowCount(self, index):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
if role == QtCore.Qt.DisplayRole:
if 0 <= index.row() < self.rowCount(index):
return self.items[index.row()]
if role == DELEGATE_DATA_ROLE:
item = self.items[index.row()]
return item, item.get('name'), item.get('description'), item.get('thumbnail')
if role == QtCore.Qt.EditRole:
return self.items[index.row()]
def setData(self, index, value, role=QtCore.Qt.EditRole):
if role == QtCore.Qt.EditRole:
self.items[index.row()] = value
self.dataChanged.emit(index, index)
return True
return False
def flags(self, index):
flag = super(ItemModel, self).flags(index)
return flag | QtCore.Qt.ItemIsEditable
class ListView(QtGui.QListView):
def __init__(self, parent=None):
super(ListView, self).__init__(parent=parent)
class TestUI(QtGui.QDialog):
def __init__(self, parent=None):
super(TestUI, self).__init__(parent)
self.main_layout = QtGui.QVBoxLayout()
self.resize(700, 500)
self.view = ListView()
self.item_delegate = ItemDelegate()
self.view.setItemDelegate(self.item_delegate)
self.model = ItemModel()
self.view.setModel(self.model)
self.item_widget = ItemWidget()
self.setLayout(self.main_layout)
self.main_layout.addWidget(self.view)
self.main_layout.addWidget(self.item_widget)
def start():
app = QtGui.QApplication(sys.argv)
ui = TestUI()
ui.show()
ui.setWindowState(QtCore.Qt.WindowActive)
ui.raise_()
app.exec_()
if __name__ == '__main__':
start()