Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QItemDelegate for editing questions



  • I have written my first QItemDelegate subclass to allow editing of a certain kind of data in a QTableView. My code works fine, but I'm a touch uneasy about a couple of issues. I'd appreciate any comments.

    Code is Python/PyQt, but don't let that put you C++ers off reading! It's really simple and close to C++.

    I need to allow user to edit dates in a column. I have already rolled my own QWidget for that, JDateEdit, used elsewhere in my app. Before anyone asks, can't use Qt's QDateEdit for that as it does not allow the date to be left empty --- I asked here about that a long time ago. Not relevant to the issues anyway. Also, I looked into QItemEditFactory and the example using that: decided not to go down that route, it uses Qt properties and C++ macros to accomplish and those are just a pain from Python/PyQt. So I am just doing it via subclassing QItemDelegate. With this said, onto the code:

    Caller:

    self.tableView.setModel(self.model)
    self.tableView.setItemDelegateForColumn(col, JDateItemDelegate(self.tableView))
    
    

    Subclass definition:

    class JDateItemDelegate(QItemDelegate):
        # delegate to provide a JDateEdit for editing a date nicely when it's in e.g. a JTableView
        def __init__(self, parent=None):
            super().__init__(parent)
    
        def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex):
            return JDateEdit(parent)
    
        def setEditorData(self, dateEdit: JDateEdit, index: QModelIndex):
            date = index.model().data(index, Qt.EditRole)
            dateEdit.setDate(date)
    
        def setModelData(self, dateEdit: JDateEdit, model: QAbstractItemModel, index: QModelIndex):
            date = dateEdit.date()
            model.setData(index, date)
    

    That's it! I'd appreciate comments on:

    • Have I done anything wrong/missed anything?

    • Qt is usually very precise/consistent in the parameters etc. it uses. setModelData() has a model parameter which I use for model.setData() to store the data back. But setEditorData() does not have a model parameter: I still need to fetch the data to edit from model.data(), so I've had to get the model via index.model() (which could equally have been done in setModelData()). Why this inconsistency between the two methods --- am I missing something?

    • createEditor() is passed a QModelIndex parameter but I don't use it, perhaps because I know I've only set my delegate on an appropriate column so I don't need to check? I don't seem to need to fetch the value to edit from the model here, as setEditorData() will be called upon edit and that's where I will be doing it?

    • createEditor() is passed a QStyleOptionViewItem parameter. I don't use it because I don't know what to do with it. Now, very specifically, while I was Googling earlier to find about all of this, I came across a post which I cannot now find. It said/warned to the effect of: "if you are creating your own editor widget, you should set Qt hard focus on your widget, as otherwise some events intended for your editor may go to the table view, or vice versa". Where I have written Qt hard focus it was actually some Qt attribute, something about "hard" & "focus", perhaps some style for a QWidget? Can anyone figure what it was, because I cannot find the reference again for the life of me?

    Many thanks for any answers.


  • Qt Champions 2019

    First please derive from QStyledItemDelegate, QItemDelegate will hopefully go away with Qt6.

    • setEditorData()/setModelData() - you forgot QModelIndex::data() which can be used in setEditorData() as a shortcut.
    • createEdtior() - it's because you can create a different editor/widget for each index
    • QStyleOptionViewItem - just take a look at the parameters - it's used for drawing the item so you can use it too if you want/need it.

    The stuff with the hard focus I don't understand...



  • @Christian-Ehrlicher
    Thanks, that's perfect. I will change my derivation.

    you forgot QModelIndex::data() which can be used in setEditorData() as a shortcut.

    Funny you should say that! Earlier I was musing to myself: "If QModelIndex contains a reference to the model, then a convenience method to access the data would be possible...". :) That's good, but doesn't to me answer why Qt passes the model explicitly to setModelData() but not to setEditorData(). It's as though they expect you to need it in the former but not in the latter, so I wondered if I was missing something.

    I still wonder what that Qt hard focus thing I saw is about.... Does a widget have some "hard focus" property which affects how it receives events?


  • Qt Champions 2019

    Maybe they mean StrongFocus?



  • @Christian-Ehrlicher
    You're a hero :)
    Here we go https://doc.qt.io/qt-5/qabstractitemdelegate.html:

    The returned editor widget should have Qt::StrongFocus; otherwise, QMouseEvents received by the widget will propagate to the view.

    What do you think of that? Do I need to take any action on the QWidget I am returning?


  • Qt Champions 2019

    At least I did not yet had problems with the default behavior but it maybe depends on the type of the displayed widget - with QComboBoxes I don't have a problem here.



  • @Christian-Ehrlicher
    OK, mine too seems to be working without my doing anything about StrongFocus so I won't worry.



  • @JonB said in QItemDelegate for editing questions:

    but doesn't to me answer why Qt passes the model explicitly to setModelData() but not to setEditorData()

    index.model() returns a const QAbstractItemModel* you can read the data from the model and set it inside the editor but you can't performs actions that alter the model from it, that's why setModelData() needs to have another, non-const, model passed as argument



  • @VRonin
    Ahhhhh!!!!! Well, that makes sense. I wouldn't know that, because I'm Python/PyQt where we don't have any notion of const and we can change whatever we like when we like, regardless! :)


  • Moderators

    @JonB said in QItemDelegate for editing questions:

    Python/PyQt where we don't have any notion of const and we can change whatever we like when we like

    A truly frightening thought....



  • @J.Hilk Everything about Python is frightening.... :)


Log in to reply