QListView item with checkbox selection behavior

馋奶兔 提交于 2019-12-04 20:16:58

Solved this issue by connection two signals

  1. Registered model item changed signal for handling the checkbox indicator change.
  2. Registered view item activated signal for changing the checkbox indicator state

Here's my code:

void MyClass:Init() 
{
    m_poListView = new QListView(this);

    // Set single selection mode
    m_poListView->setSelectionMode(
               QAbstractItemView::SingleSelection);

    // Create list view item model
    QStandardItemModel*  poModel =
              new QStandardItemModel(m_poListView);

    QStandardItem * poListItem =
              new QStandardItem;

    // Checkable item
    poListItem->setCheckable( true );

    // Save checke state
    poListItem->setData(Qt::Unchecked, Qt::CheckStateRole);

    poModel->setItem(0, poListItem);

    m_poListView->setModel(poModel);

     // Register model item  changed signal
       connect(poModel, SIGNAL(itemChanged(QStandardItem*)),
       this,            SLOT  (SlotItemChanged(QStandardItem*)));

    // Resister view item acticated
     connect( m_poListView , SIGNAL(activated(const QModelIndex & )),
                 this,       SLOT(SlotListItemActivated(const QModelIndex & )))

}

Slots implemntation :

void MyClass::SlotItemChanged(QStandardItem *poItem)
{
    // Get current index from item
    const QModelIndex oCurrentIndex =
            poItemChanged->model()->indexFromItem(poItem);

    // Get list selection model
    QItemSelectionModel *poSelModel =
            m_poListView->selectionModel();

    // Set selection
    poSelModel->select(
                QItemSelection(oCurrentIndex, oCurrentIndex),
                QItemSelectionModel::Select | QItemSelectionModel::Current);
}

void MyClass::SlotListItemActivated(const QModelIndex &oIndex)
{
    Qt::CheckState eCheckState = Qt::Unchecked;

    // Get item's check state
    bool bChecked =
            oIndex.data(Qt::CheckStateRole).toBool();

    // Item checked ?
    if (bChecked == false) 
        eCheckState = Qt::Checked;
    else 
        eCheckState = Qt::Unchecked;

    // Get index model
      //    Note: I used QSortFilterProxyModel in the original code
    QSortFilterProxyModel *poModel = 
        (QSortFilterProxyModel *)oIndex.model();

    // Update model data
    poModel->setData(oIndex, eCheckState, Qt::CheckStateRole);
}

You have to connect itemChanged signal of QStandardItemModel and select items manually there.

If you want the checkbox to be checked on selection, you'll also have to connect selectionChanged signal of QListView::selectionModel() and check/uncheck items there.

Also, you don't need to manually set Qt::CheckStageRole.

Using C++11 and lambdas that would look like this:

connect(poModel, &QStandardItemModel::itemChanged, [poListView, poModel](QStandardItem * item) {
    const QModelIndex index = poModel->indexFromItem(item);
    QItemSelectionModel *selModel = poListView->selectionModel();
    selModel->select(QItemSelection(index, index), item->checkState() == Qt::Checked ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
});

connect(poListView->selectionModel(), &QItemSelectionModel::selectionChanged, [poModel](const QItemSelection &selected, const QItemSelection &deselected) {
    for (const QModelIndex &index : selected.indexes()) {
        poModel->itemFromIndex(index)->setCheckState(Qt::Checked);
    }
    for (const QModelIndex &index : deselected.indexes()) {
        poModel->itemFromIndex(index)->setCheckState(Qt::Unchecked);
    }
});

Or with old connect syntax:

void MyClass::handleCheckedChanged(QStandardItem *item) {
    const QModelIndex index = item->model()->indexFromItem(item);
    QItemSelectionModel *selModel = poListView->selectionModel();
    selModel->select(QItemSelection(index, index), item->checkState() == Qt::Checked ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
}

void MyClass::handleSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {
    foreach (const QModelIndex &index, selected.indexes()) {
        index.model()->itemFromIndex(index)->setCheckState(Qt::Checked);
    }
    foreach (const QModelIndex &index, deselected.indexes()) {
        index.model()->itemFromIndex(index)->setCheckState(Qt::Unchecked);
    }
}

...

connect(poModel, SIGNAL(itemChanged(QStandardItem *)), this, SLOT(handleCheckedChanged(QStandardItem *)));

connect(poListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged(QItemSelection, QItemSelection)));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!