0

I'm working on a dialog class with a QListView and a customized model inheriting QAbstractListModel. Items on my list are custom widgets with several labels.

I managed to make a checkbox displayed for each item by reimplementing data(), setData() and flags() methods of my model, but when I run my code and click on a checkbox associated to one of the item, the checkbox doesn't appear as checked (remains unchecked).

Here's my code:

mymodel.h

class MyModel : public QAbstractListModel
{
    Q_OBJECT

public:
    MyModel(QObject *parent);
    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE ;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
    bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
    Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE ;

    QSet<QPersistentModelIndex> checkedItems;
};

mymodel.cpp

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if(role == Qt::CheckStateRole)
    {
        if(checkedItems.contains(index))
            return Qt::Checked;
        else
            return Qt::Unchecked;
    }

    return QVariant();
}


bool MyModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if(role == Qt::CheckStateRole)
    {
        if(value == Qt::Checked)
            checkedItems.insert(index);
        else
            checkedItems.remove(index);

        emit dataChanged(index, index);
    }

    return true;
}


Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
    return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable;
}

mydelegate.h

class MyDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {}
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

mydelegate.cpp

QSize MyDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    return QSize(400, 120);
}

In the constructor of mydialog.cpp

model = new MyModel(this);
ui->list->setModel(model);
ui->list->setItemDelegate(new MyDelegate(this));

I've tried adding flags Qt::ItemIsEnabled and Qt::ItemIsEditable but it didn't change anything.

I'm not very familiar with view/model implementation so far, although I've read Qt docs.

Thx for the help !

nmud
  • 175
  • 14
  • Try if it works without the delegate. If it works, state that in your question. If it doesn't remove it from the question. – SteakOverflow Mar 09 '18 at 13:22
  • Removing the delegate didn't solve the issue. I added it in the first place to resize the items of the listview, because without it their height was shrinked. – nmud Mar 09 '18 at 13:48
  • Just debug the application to see whether `checkedItems.contains(index)` returns true for desired items. – vahancho Mar 09 '18 at 13:57
  • This statement is always false – nmud Mar 09 '18 at 14:18
  • I think you are missing `checkBoxItem.setChecked(True)` in your setData function or maybe you do that in another part of your code ? – PBareil Mar 09 '18 at 15:03
  • How do I access this checkBoxItem ? Because the checkbox behavior is fine as long as I work with a simple model of QString, but when I use my custom widget it no longer works. – nmud Mar 09 '18 at 15:10
  • Display size is not relevant to your problem. Always try to formulate a minimal problem if you want help. Also forget about the checkBoxItem, that is a different API. My guess is that you cannot store QModelIndexes in whatever container you are using. Try storing the row instead. For a less random guess, provide a [mcve](https://stackoverflow.com/help/mcve). – SteakOverflow Mar 09 '18 at 15:33
  • I never said the display size was relevant here, just that I added the delegate so the items were correctly sized that's all. – nmud Mar 09 '18 at 15:39
  • @nmud How do you fill in the model? – eyllanesc Mar 09 '18 at 16:31
  • @eyllanesc : the model is filled with a for loop. I've a QList of struct as member of MyModel and I do calls to push_back() method to populate this list. Let me know if you want me to add more code samples about this in the question. – nmud Mar 10 '18 at 16:48
  • @nmud If you want someone to help you, you must provide a [mcve] – eyllanesc Mar 10 '18 at 16:50

1 Answers1

0

To be more precise about my comment, here is what I had in mind

    bool MyModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if(role == Qt::CheckStateRole)
    {
        if(value == Qt::Checked)
            checkedItems.insert(index);
            self.checkBoxList[index.row()][index.column()].setChecked(True)
        else
            checkedItems.remove(index);
            self.checkBoxList[index.row()][index.column()].setChecked(False)

        emit dataChanged(index, index);
    }

    return true;
}

I just do not have all of your code so I do not know how your self.checkBoxList is done. Are the checkBox child of the table?

PBareil
  • 157
  • 6
  • I think the checkboxes are added just because the flags method was reimpleted and the flag Qt:: ItemIsUserCheckable was added. So if there's a way to access the checkboxes variables I don't know about it. Also it's c++ and not python :) – nmud Mar 10 '18 at 16:45
  • Then I would suggest that you add a checkbox to this column instead – PBareil Mar 12 '18 at 13:17