Heisenbug
Heisenbug

Reputation: 39164

PyQt: How to change currentIndex in QComboBox when custom QAbstractListModel data changed

I've read some examples on how to define a custom model for a QComboBox widget.

Here's how I defined my model:

class LevelListModel(QAbstractListModel):
    def __init__(self, parent=None, *args):
        """ datain: a list where each item is a row
        """
        QAbstractListModel.__init__(self, parent, *args)
        self.levelList = []
    def rowCount(self, parent=QModelIndex()):
        return len(self.levelList)

    def data(self, index, role):
        if index.isValid() and role == Qt.DisplayRole:
            return QVariant(index.row())
        else:
            return QVariant()
    def addLevel(self,level):
        self.beginResetModel()
        self.levelList.append(level)
        self.endResetModel()

I set the model to my QComboBox:

self.levelListModel = LevelListModel()
self.ui.levelComboBox.setModel(self.levelListModel)

I add a model to my list this way:

newLevel = Level (self.levelListModel.rowCount() + 1)
self.levelListModel.addLevel(newLevel)

The item is added correctly and I can see it inside the combobox, but I would like to change the currentIndex to be the new item's index.

I guess QAbstractListModel could raise some kind of events that QComboBox can listen to, but I haven't still found how to do that.

My questions are:

  1. How can I notify the QComboBox that model data changed, and listen to that event to modify currentIndex accordingly?
  2. I used [begin|end]ResetModel because my entry should be an ordered sequence of integer. So I need to rebuild the data list completely once an item in the middle of the list have been removed. I don't know if this is the right way to go. Any better solution?

Upvotes: 4

Views: 5522

Answers (1)

Avaris
Avaris

Reputation: 36715

1

How can I notify the QComboBox that model data changed, and listen to that event to modify currentIndex accordingly?

No need to listen an event from the way you do things. You know when the model data is changed, because you add things yourself. Just change the currentIndex after adding a data.

I'd probably modify the addLevel method to return the QModelIndex of the added item and then use it to set the currentIndex of the QComboBox:

class LevelListModel(QAbstractListModel):
    # [skipped]
    def addLevel(self,level):
        self.beginInsertRows(QModelIndex(), len(self.levelList), len(self.levelList))
        self.levelList.append(level)
        self.endInsertRows()
        return self.index(len(self.levelList)-1)

and

newLevel = Level (self.levelListModel.rowCount() + 1)
newIndex = self.levelListModel.addLevel(newLevel)
self.ui.levelComboBox.setCurrentIndex(newIndex)

2

I used [begin|end]ResetModel because my entry should be an ordered sequence of integer. So I need to rebuild the data list completely once an item in the middle of the list have been removed. I don't know if this is the right way to go. Any better solution?

That depends. [begin|end]ResetModel is for really drastic changes. I don't see how keeping an ordered list of integers would lead to such changes for single item addition/removal. From what you describe, you should be using [begin|end]InsertRows and [begin|end]RemoveRows.

Upvotes: 3

Related Questions