user6205205
user6205205

Reputation:

Edit table in PyQt QAbstractTableModel without deletion of content

What I have done so far:

I'm implementing an custom QAbstractTableModel (used in a QTableView-Widget) that contains editable cells. The properties of these cells are specified in my flags() method that looks like this:

def flags(self, index):  # Qt was imported from PyQt4.QtCore
    if index.column() < 2:
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | \
               Qt.ItemIsSelectable
    else:
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable

Cells in the first two columns are marked as editable just like I want.

What I want to do:

However when double clicking the cell to trigger the editing the contained text is deleted and an empty field is shown.

Example of editing a cell

But I don't want to delete & replace the contained text because the contained text could be very long and shouldn't be retyped. I just want to edit what is already contained. When double-clicked the cell should be editable with the previously contained text inside (maybe already selected).

The Question:

How can I achieve this behavior? Do I need to edit my flags method and specify different properties for these cells?

Upvotes: 4

Views: 7858

Answers (2)

Claude C
Claude C

Reputation: 51

As Brendan Abel said,

No data is appearing in the cells during editing because you likely haven't set any data on the Qt.EditRole for each item in your model

In this case, to show previous data in the edit box after you double click the cell, it requires to access data() as EditRole, so you should implement the data() method in the inherited model class as something like this:

def data(self, index, role=None):
    ...
    if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
        item = index.internalPointer()
        return item.data[index.column()]
    ...

It is also mentioned in the official document of model view programming

Upvotes: 4

Brendan Abel
Brendan Abel

Reputation: 37559

You have a few options.

No data is appearing in the cells during editing because you likely haven't set any data on the Qt.EditRole for each item in your model. The QTableWidget's do this be default.

Another way of doing this is by using a QItemDelegate. This will allow you to manually create the editor widget and initialize it before it appears in the QTableView. You can use the display role text if the edit text hasn't been populated.

class MyDelegate(QtGui.QItemDelegate):

    def createEditor(self, parent, option, index):
        if index.column() == 2:
            return super(MyDelegate, self).createEditor(parent, option, index)
        return None

    def setEditorData(self, editor, index):
        if index.column() == 2:
            # Gets display text if edit data hasn't been set.
            text = index.data(Qt.EditRole) or index.data(Qt.DisplayRole)
            editor.setText(text)         

delegate = MyDelegate()
tableview.setItemDelegate(delegate)

Upvotes: 4

Related Questions