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

QTableView displays boolean model as checkbox AND "true" or "false" text



  • Hi,

    I have a model and a tableview. Table displays all model data. Data consists of a QVector of a struct. One member in struct is boolean. I can display it as checkbox in the table but there is a "true" or "false" text close to checkbox. If I doble-click on text, it converts to combobox. I don't know why.
    What is the problem?

    Thanks.

    Combo

    #include "registermodel.h"
    #include <QFont>
    #include <QBrush>
    #include <QColor>
    
    #define DEB qDebug().noquote() <<
    
    RegisterModel::RegisterModel(QObject *parent) : QAbstractTableModel(parent)
    {
        headers = QStringList();
        headers << "Name" << "Page" << "Address" << "Current Value" << "Write Protect" << "Write Value";
    }
    
    int RegisterModel::rowCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent);
        return Registers.size();
    }
    
    int RegisterModel::columnCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent);
        return COLS;
    }
    
    QVariant RegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (role == Qt::DisplayRole)
        {
            if (orientation == Qt::Horizontal) {
                    return headers.at(section);
            }
    
            if (orientation == Qt::Vertical) {
                return section+1;
            }
        }
        return QVariant();
    }
    
    void RegisterModel::setElement(int row, int col, QVariant value)
    {
        switch (col) {
        case 0:
            Registers[row].name = value.toString();
            break;
        case 1:
            Registers[row].page = value.toUInt();
            break;
        case 2:
            Registers[row].address = value.toUInt();
            break;
        case 3:
            Registers[row].currValue = value.toUInt();
            break;
        case 4:
            Registers[row].wrProtect = value.toBool();
            break;
        case 5:
            Registers[row].wrValue = value.toUInt();
            break;
    
        default:
            break;
        }
    }
    
    
    QVariant RegisterModel::data(const QModelIndex &index, int role) const
    {
        int row = index.row();
        int col = index.column();
    
        switch (role) {
        case Qt::DisplayRole:
            return getData(col, row);
            break;
    
        case Qt::EditRole:
    
            return getData(col, row);
            break;
    
        case Qt::TextAlignmentRole:
            if(col == 0)
                return Qt::AlignLeft;
            else
                return Qt::AlignRight;
            break;
    
        case Qt::CheckStateRole:
    
            if(col == 4)
            {
    
                if(Registers[row].wrProtect == true)
                {
                    return Qt::Checked;
                }
                else
                {
                    return Qt::Unchecked;
                }
            }
    
            break;
    
        case Qt::FontRole:
            if(col != 0)
                return QFont("Courier New", 10, QFont::Normal);
            break;
    
        case Qt::BackgroundRole:
    
            if(row % 2 == 0)
            {
                QColor c;
                c.setNamedColor("#E2E2E2");
                QBrush bg(c);
                return bg;
            }
    
            break;
    
        default:
            return QVariant();
            break;
        }
    
        return QVariant();
    }
    
    bool RegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
    
        if(role == Qt::EditRole)
        {
            setElement(index.row(), index.column(), value);
        }
    
        else if (role == Qt::CheckStateRole)
        {
            bool check = false;
    
            if((Qt::CheckState)value.toInt() == Qt::Checked)
                check = true;
    
            setElement(index.row(), index.column(), check);
        }
    
        emit dataChanged(index, index);
    
        return true;
    
    }
    
    Qt::ItemFlags RegisterModel::flags(const QModelIndex &index) const
    {
        int col = index.column();
        if (col == 5)
            return Qt::ItemIsEnabled | Qt::ItemIsEditable | QAbstractTableModel::flags(index);
        else if (col == 4)
            return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | QAbstractTableModel::flags(index);
        else
            return QAbstractTableModel::flags(index);
    }
    
    
    void RegisterModel::changed(const int row)
    {
        emit dataChanged(index(row, 0), index(row, 5));
    }
    
    
    
    bool RegisterModel::fillData(QVector<QStringList> *data)
    {
       Register reg;
    
       bool ok;
    
       beginInsertRows(QModelIndex(), 0, data->size());
    
       for(int i = 0; i < data->size(); ++i)
       {
           reg.name = data->at(i).at(0);
           reg.address = data->at(i).at(2).toUInt(&ok, 16);
           reg.page = data->at(i).at(1).toUInt(&ok, 10);
           reg.currValue = 0;
           reg.wrProtect = true;
           reg.wrValue = 0;
    
           Registers.append(reg);
    
       }
    
       endInsertRows();
       return true;
    }
    
    
    
    QVariant RegisterModel::getData(int col, int row) const
    {
        switch (col) {
        case 0:
            return QVariant(Registers[row].name);      // QString
            break;
        case 1:
            return QVariant(Registers[row].page);      // quint16
            break;
        case 2:
            return QVariant(QString("%1").arg(Registers[row].address, 8, 16, QChar('0')).toUpper());   // quint32
            break;
        case 3:
            return QVariant(QString("%1").arg(Registers[row].currValue, 8, 16, QChar('0')).toUpper()); // quint32
            break;
        case 4:
            return QVariant(Registers[row].wrProtect); // bool
            break;
        case 5:
            return QVariant(QString("%1").arg(Registers[row].wrValue, 8, 16, QChar('0')).toUpper());   // quint32
            break;
        default:
            return QVariant();
            break;
        }
    }
    
    void RegisterModel::dumpRegisters()
    {
        DEB "+--------------------------------------------------------------------------------+";
        DEB QString("| %1%2%3: %4 %5    %6 |").arg("Name", -25). \
                                         arg("Page", 5).\
                                         arg("Address", 11).\
                                         arg("Curr Val.", 10).\
                                         arg("Wr Protect", 12). \
                                         arg("Wr Value", 8);
    
        foreach (Register reg, Registers) {
            QString name = reg.name.left(23) + ((reg.name.size() > 23) ? ".." : "");
            DEB QString("| %1%2   %3:   %4 %5    %6 |").arg(name, -25). \
                                             arg(reg.page, 5).\
                                             arg(reg.address, 8, 16, QChar('0')).\
                                             arg(reg.currValue, 8, 16, QChar('0')).\
                                             arg(reg.wrProtect, 12). \
                                             arg(reg.wrValue, 8, 16, QChar('0'));
        }
    
        DEB "+--------------------------------------------------------------------------------+";
    
    }
    
    

  • Qt Champions 2019

    You return a Qt::DisplayRole and EditRole for row 4 also - so the view displays this data.



  • Ok, I changed it but now it displays an editable field. When I double-click it opens a text field. When I leave the text field empty, checkbox gets false. Checkbox alone works correctly, it changes datamodel.

    registermodel.cpp:

    .....
        case Qt::DisplayRole:
            if(col != 4)
                return getData(col, row);
            break;
    
        case Qt::EditRole:
            if(col != 4)
                return getData(col, row);
            break;
    .....
    

    text field


  • Qt Champions 2019

    You have to return the correct flags for this column with http://doc.qt.io/qt-5/qabstractitemmodel.html#flags - Qt::ItemIsUserCheckable but not Qt::ItemIsEditable iirc



  • Ok, thanks. It displays only checkbox now.


Log in to reply