Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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()
    {
    
    }
    

  • Lifetime Qt Champion

    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.


  • Lifetime Qt Champion

    @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 ?


  • Qt Champions 2019


Log in to reply