Making a checkbox in a QTableView useable?



  • I am creating my own custom model that has a boolean value. the boolean value needs to be checkable in the QTableView. The QTableView is displaying the checkbox, it is checkable, after the user clicks in the cell, to the right of the checkbox to put the whole cell into edit mode. then the checkbox can be checked. Is there any way to allow the user to simply click on time to toggle the checkbox? Below is my model, the view has no special code:

    NameManglorModel.h
    @class NameManglorData : public QObject
    {
    Q_OBJECT
    public:
    NameManglorData(const QString& srcFilename, const QString& dstFilename)
    {
    _srcFilename = srcFilename;
    _dstFilename = dstFilename;

    _process = !_dstFilename.isEmpty();
    }

    QString srcFilename() const { return _srcFilename;}
    void setSrcFilename(const QString& value) { _srcFilename = value; }

    QString dstFilename() const { return _dstFilename;}
    void setDstFilename(const QString& value) { _dstFilename = value; _process = !_dstFilename.isEmpty(); }

    bool process() const { return !_dstFilename.isEmpty() && _process;}
    void setProcess(const bool& value) { _process = value; }

    bool error() const { return _error;}
    void setError(const bool& value) { _error = value; }

    private:
    QString _srcFilename;
    QString _dstFilename;
    bool _process;
    bool _error;
    };

    class NameManglorModel : public QAbstractTableModel
    {
    Q_OBJECT

    public:
    NameManglorModel(QObject *parent);
    ~NameManglorModel();

    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const ;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
    Qt::ItemFlags flags(const QModelIndex & index) const;

    void add( const QString& srcFilename, const QString& dstFilename);
    void clear();

    private:
    QList<NameManglorData*> _coll;
    };
    @

    NameManglorModel.cpp
    @NameManglorModel::NameManglorModel(QObject *parent)
    : QAbstractTableModel(parent)
    {
    }

    NameManglorModel::~NameManglorModel()
    {
    qDeleteAll(_coll.begin(), _coll.end());
    _coll.clear();
    }

    void NameManglorModel::add( const QString& srcFilename, const QString& dstFilename)
    {
    _coll.append( new NameManglorData(srcFilename, dstFilename));
    }

    void NameManglorModel::clear()
    {
    qDeleteAll(_coll.begin(), _coll.end());
    _coll.clear();
    }

    QVariant NameManglorModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
    if (role == Qt::DisplayRole)
    {
    if (orientation == Qt::Horizontal)
    {
    switch (section)
    {
    case 0: return QString("Process");
    case 1: return QString("Source");
    case 2: return QString("Destination");
    case 3: return QString("Error");
    }
    }
    }
    return QVariant();
    }

    int NameManglorModel::rowCount(const QModelIndex & /parent/) const
    {
    return _coll.count();
    }

    int NameManglorModel::columnCount(const QModelIndex & /parent/) const
    {
    return 4;
    }

    QVariant NameManglorModel::data(const QModelIndex &index, int role) const
    {
    if( index.row() < _coll.count())
    {
    if( index.column() == 0)
    {
    if (role == Qt::CheckStateRole)
    {
    NameManglorData* p = _coll[index.row()];
    return p->process() ? Qt::Checked : Qt::Unchecked;
    }
    }
    else if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
    NameManglorData* p = _coll[index.row()];

    switch(index.column())
    {
    case 0: break;
    case 1: return p->srcFilename();
    case 2: return p->dstFilename();
    case 3: return p->error();
    }
    }
    }
    return QVariant();
    }

    bool NameManglorModel::setData(const QModelIndex & index, const QVariant & value, int role /= Qt::EditRole/)
    {
    if (role == Qt::EditRole)
    {
    //save value from editor to member m_gridData
    NameManglorData* p = _coll[index.row()];

    switch(index.column())
    {
    case 0:
    p->setProcess(value.toBool());
    break;
    case 2:
    p->setDstFilename(value.toString());
    break;
    }
    }
    return true;
    }

    Qt::ItemFlags NameManglorModel::flags(const QModelIndex & index) const
    {
    Qt::ItemFlags flags = QAbstractTableModel::flags(index);

    if( index.column() == 0)
    flags |= Qt::ItemIsEditable | Qt::ItemIsUserCheckable;
    else if( index.column() == 2)
    flags |= Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ;

    return flags;
    }
    @



  • If you want the whole cell to act as the toggle for the checkbox, I think you'd probably need a delegate. If you subclass QStyledItemDelegate, you can reimplement editorEvent(). In there, you could translate the coordinates of mousepress (and/or -release) events on the cell to lie in the area of the checkbox. You can then pass on the call to the base class. That should, I think, be a simple way to do this.



  • Andre,

    I understand the basic concept, do you know if thre are ny examples out there anywhere?

    Sam



  • Not that I am aware of. It should just take a few lines of code, however.



  • Thank you for pointing me in the correct direction, once I know the solution was found within the editorEvent(), I found this article that solves both my problem along with centering the checkbox. Very nice!

    "How can I align the checkboxes in a view?":http://developer.qt.nokia.com/faq/answer/how_can_i_align_the_checkboxes_in_a_view


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.