Unsolved Subclassing QComboBox to have Checkboxes
-
As the title states I'd like to have the items in my QComboBox to have check boxes. I've subclassed QStandardItemModel in order to do so, but it isn't working. I get the items, but no checkboxes. Normally when I want checkboxes in a QTableView I reimplement the flags function. I've seen where individuals override the addItem function of QCombox and then set the QComboBox to be editable, but that isn't desired as I don't want to give the user the ability to add items into the combo box and I would think, as with other Qt Model/View classes, this would work similarly.
Header:
#ifndef CHECKABLECOMBOBOX_HPP #define CHECKABLECOMBOBOX_HPP #include <QStandardItemModel> #include <QComboBox> class CCheckableComboBoxModel : public QStandardItemModel { Q_OBJECT public : CCheckableComboBoxModel( QObject * parent = nullptr ) ; ~CCheckableComboBoxModel() ; protected : virtual QVariant data( const QModelIndex &index, int role ) const ; virtual Qt::ItemFlags flags( const QModelIndex & index ) const ; virtual bool setData( const QModelIndex & index, const QVariant & value, int role ) ; signals : void CheckStateChanged( bool checked, const QString & item ) ; } ; class CCheckableComboBox : public QComboBox { Q_OBJECT public : CCheckableComboBox( QWidget * parent = nullptr ) ; ~CCheckableComboBox() ; protected : CCheckableComboBoxModel * m_model ; } ; #endif // CHECKABLECOMBOBOX_HPP
Source
#include "CheckableComboBox.hpp" CCheckableComboBoxModel::CCheckableComboBoxModel( QObject * parent ) : QStandardItemModel( parent ) { } CCheckableComboBoxModel::~CCheckableComboBoxModel() { } QVariant CCheckableComboBoxModel::data( const QModelIndex & index, int role ) const { QVariant retval ; if( !index.isValid() ) { return retval ; } QStandardItem * standardItem = item( index.row(), index.column() ) ; printf( "Item is checkable %d!\n", standardItem->isCheckable() ) ; if( standardItem != nullptr ) { switch( role ) { case Qt::CheckStateRole : return standardItem->checkState() ; case Qt::DisplayRole : return standardItem->text() ; default : break ; } } return retval ; } Qt::ItemFlags CCheckableComboBoxModel::flags( const QModelIndex & index ) const { Q_UNUSED( index ) ; return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ; } bool CCheckableComboBoxModel::setData( const QModelIndex & index, const QVariant & value, int role ) { bool retval = false ; if( index.isValid() && role == Qt::CheckStateRole ) { //get the item QStandardItem * standardItem = item( index.row(), index.column() ) ; Qt::CheckState checkState = ( Qt::CheckState ) value.toInt() ; standardItem->setCheckState( checkState ) ; emit CheckStateChanged( ( checkState == Qt::Checked ), standardItem->text() ) ; retval = true ; } return retval ; } CCheckableComboBox::CCheckableComboBox( QWidget * parent ) : QComboBox( parent ) { m_model = new CCheckableComboBoxModel( this ) ; setModel( m_model ) ; addItem( "Hello" ) ; addItem( "Bob" ) ; } CCheckableComboBox::~CCheckableComboBox() { }
-
Hi
For the items, do you set
item->setData(Qt::Unchecked, Qt::CheckStateRole);
as else the state is undefined and it it might not render the checkbox or
something like that. -
@mrjj hmmm so that would require me to overload the addItem function in QComboBox I don't think that's the ideal solution as the model should tell the view all of that information. In the past when I've added items to a QTableView/QListView, I've never had to do that for checkboxes. Since I've reimplemented the flags function it automatically sets all items added to have a CheckStateRole ( in the aforementioned views ) - or at least I thought it worked that way.
-
@HunterMetcalfe
hi
Hmm i must agree since i used a QStandardItemModel
but you do have the flag function/custom model so
I would also assume that should be enough.Is the code complete enough to run ?
-
Please see also https://bugreports.qt.io/browse/QTBUG-60310