KernelPanic
KernelPanic

Reputation: 2432

QAbstractTableModel::insertRows appending new data to internal QList

I have following class, which represents record in data structure:

#ifndef UECONNECTEDCLIENTRECORD_H
#define UECONNECTEDCLIENTRECORD_H

#include <QtGlobal>
#include <QObject>
#include <QHostAddress>
#include <QString>

class UeConnectedClientRecord : public QObject
{
    Q_OBJECT

private:
    /**
     * @brief m_ueClientName
     */
    QString m_ueClientName;

    /**
     * @brief m_ueClientAddress
     */
    QHostAddress m_ueClientAddress;

    /**
     * @brief m_ueClientPort
     */
    QString m_ueClientPort;

public:
    /**
     * @brief UeConnectedClientRecord
     * @param parent
     */
    explicit UeConnectedClientRecord(const QString& clientName=QString(),
                                     const QHostAddress& clientAddress=QHostAddress(),
                                     const QString& clientPort=QString());

    /**
     * @brief ueSetClientName
     * @param name
     */
    inline void ueSetClientName(const QString& name)
        { this->m_ueClientName=name; }

    /**
     * @brief ueSetClientAddress
     * @param address
     */
    inline void ueSetClientAddress(const QHostAddress& address)
        { this->m_ueClientAddress=address; }

    /**
     * @brief ueSetClientPort
     * @param port
     */
    inline void ueSetClientPort(const QString& port)
        { this->m_ueClientPort=port; }

    /**
     * @brief ueClientName
     * @return client name
     */
    inline const QString& ueClientName() const
        { return this->m_ueClientName; }

    /**
     * @brief ueClientAddress
     * @return client address
     */
    inline const QHostAddress& ueClientAddress() const
        { return this->m_ueClientAddress; }

    /**
     * @brief ueClientPort
     * @return client port
     */
    inline const QString& ueClientPort() const
        { return this->m_ueClientPort; }
};

#endif // UECONNECTEDCLIENTRECORD_H

which is used in subclassed QAbstractTableModel:

#ifndef UECONNECTEDCLIENTSTABLEMODEL_H
#define UECONNECTEDCLIENTSTABLEMODEL_H

#include <QObject>
#include <QAbstractTableModel>
#include <QList>
#include <QModelIndex>
#include <QVariant>
#include <QHash>
#include <QByteArray>

#include "ueconnectedclientrecord.h"

class UeConnectedClientsTableModel : public QAbstractTableModel
{
    Q_OBJECT

private:
    /**
     * @brief m_ueConnectedClientData
     */
    QList<UeConnectedClientRecord*> m_ueConnectedClientData;

protected:
    /**
     * @brief ueSetConnectedClientData
     * @param clientData
     */
    inline void ueSetConnectedClientData(const QList<UeConnectedClientRecord*>& clientData)
        { this->m_ueConnectedClientData=clientData; }

public:
    /**
     * @brief UeConnectedClientsTableModel
     * @param parent
     */
    UeConnectedClientsTableModel(QObject* parent=Q_NULLPTR);

    /**
     * @brief ueConnectedClientData
     * @return connected client data
     */
    inline const QList<UeConnectedClientRecord*>& ueConnectedClientData() const
        { return this->m_ueConnectedClientData; }

    /**
     * @brief rowCount
     * @param parent
     * @return number of rows in model
     */
    inline int rowCount(const QModelIndex& /*parent*/) const
        { return this->ueConnectedClientData().size(); }

    /**
     * @brief columnCount
     * @return number of columns in model
     */
    inline int columnCount(const QModelIndex& /*parent*/) const
        { return 3; }

    /**
     * @brief data
     * @param index
     * @param role
     * @return data for index
     */
    QVariant data(const QModelIndex& index,
                  int role=Qt::DisplayRole) const;

    /**
     * @brief roleNames
     * @return role names
     */
    QHash<int, QByteArray> roleNames() const;

    /**
     * @brief headerData
     * @param section
     * @param orientation
     * @param role
     * @return header data
     */
    QVariant headerData(int section,
                        Qt::Orientation orientation,
                        int role=Qt::DisplayRole) const;

    /**
     * @brief insertRows
     * @param row
     * @param count
     * @param parent
     * @return true if the rows were successfully inserted; otherwise returns false
     */
    bool insertRows(int row,
                    int count,
                    const QModelIndex& parent=QModelIndex());

    /**
     * @brief removeRows
     * @param row
     * @param count
     * @param parent
     * @return true if the rows were successfully removed; otherwise returns false
     */
    bool removeRows(int row,
                    int count,
                    const QModelIndex& parent=QModelIndex());

public:
    /**
     * @brief ueRoleClientName
     */
    static const int ueRoleClientName=Qt::UserRole+1;

    /**
     * @brief ueRoleClientAddress
     */
    static const int ueRoleClientAddress=Qt::UserRole+2;

    /**
     * @brief ueRoleCllientPort
     */
    static const int ueRoleCllientPort=Qt::UserRole+3;
};

#endif // UECONNECTEDCLIENTSTABLEMODEL_H

and its implementation:

#include "ueconnectedclientstablemodel.h"

UeConnectedClientsTableModel::UeConnectedClientsTableModel(QObject* parent)
    : QAbstractTableModel(parent)
{
}   // constructor

QVariant UeConnectedClientsTableModel::data(const QModelIndex& index,
                                            int role) const
{
    switch(role)
    {
        case ueRoleClientName:
        {
            return this->ueConnectedClientData().at(index.row())->ueClientName();
        }   // case

        case ueRoleClientAddress:
        {
            return this->ueConnectedClientData().at(index.row())->ueClientAddress().toString();
        }   // case

        case ueRoleCllientPort:
        {
            return this->ueConnectedClientData().at(index.row())->ueClientPort().toInt();
        }   // case

        default:
        {
            return UeConnectedClientsTableModel::data(index,
                                                      role);
        }   // default
    }   // switch
}   // data

QHash<int, QByteArray> UeConnectedClientsTableModel::roleNames() const
{
    QHash<int, QByteArray> roles;

    const int roleClientName=UeConnectedClientsTableModel::ueRoleClientName;
    const int roleClientAddress=UeConnectedClientsTableModel::ueRoleClientAddress;
    const int roleCllientPort=UeConnectedClientsTableModel::ueRoleCllientPort;

    roles.insert(roleClientName,
                 "roleClientName");
    roles.insert(roleClientAddress,
                 "roleClientAddress");
    roles.insert(roleCllientPort,
                 "roleCllientPort");

    return roles;
}   // roleNames

QVariant UeConnectedClientsTableModel::headerData(int section,
                                                  Qt::Orientation orientation,
                                                  int role) const
{
    Q_UNUSED(orientation)

    if(role!=Qt::DisplayRole)
        return QVariant();

    switch(section)
    {
        case 0:
        {
            return tr("Client name");
        }   // case

        case 1:
        {
            return tr("Client address");
        }   // case

        case 2:
        {
            return tr("Client port");
        }   // case

        default:
        {
            return QVariant();
        }   // default
    }   // switch
}   // headerData

bool UeConnectedClientsTableModel::insertRows(int row,
                                              int count,
                                              const QModelIndex& parent)
{
    this->beginInsertRows(parent,
                          row,
                          row+count);

    for(int index=row; index<row+count; index++)
    {
        m_ueConnectedClientData.append(new UeConnectedClientRecord());
    }   // for

    this->endInsertRows();

    return true;
}   // insertRows

bool UeConnectedClientsTableModel::removeRows(int row,
                                              int count,
                                              const QModelIndex& parent)
{
    this->beginRemoveRows(parent,
                          row,
                          row+count);

    for(int index=row; index<row+count; index++)
    {
        m_ueConnectedClientData.removeLast();
    }   // for

    this->endRemoveRows();

    return true;
}   // removeRows

Now, how do I call insertRows() from code to insert new UeConnectedClientRecord with real data (not new UeConnectedClientRecord() - default constructor) to internal QList? I am asking the because I've searched accross internet to see examples and I've found Qt Address Book Example, however, insertRows() from official docs and insertRows() from Address Book Example are declared differently:

Why?

Upvotes: 4

Views: 4073

Answers (1)

ilotXXI
ilotXXI

Reputation: 1085

From documentation:

If you implement your own model, you can reimplement this function if you want to support insertions. Alternatively, you can provide your own API for altering the data. In either case, you will need to call beginInsertRows() and endInsertRows() to notify other components that the model has changed.

Way 1. Use insertRows + setData. Qt supposes that null-records are possible and that to add row is not to add data. As your internal list is a Qlist of pointers, you can insert nullptr there to prevent default constructor call. In this case you will need item check on each data call: if the item is nullptr, a default value should be returned.

Way 2. You can implement your own insert function. As far as I know, the insertRows function is not used by views and usually is called manually. But "usually" is not "always". For example, proxy models can use it.

Upvotes: 5

Related Questions