Search code examples
qtqt4qtableviewqabstracttablemodel

How to update data in QAbstractTableModel with different row count


I am developing an application that updates the data in QTableView from apache server once per second. The server sends data as XML table. Number of columns is constant, but the number of rows changes each time. The data in the rows may also vary.

To convert the XML into the data, I created a class TxTableData, which is used in TxTableModel (child of QAbstractTableModel). Also TxTableModel uses QTimer to update data from the server.

The problem is that if the number of lines decreases - QTableview did not react to it. When the number of rows increases - it's all right.

I need remove all rows from QTableView and fill it with new data, but QTableView does not do this. Can you

class TxTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    TxTableModel(QObject *parent = 0);

    void refreshData();
    void parseXml(const QByteArray &xml);

public slots:
    void httpDone(bool error);
    void timerDone();

protected:
    HttpConnect http;
    TxTableData m_Data;
    QTimer * timer;

};

TxTableModel::TxTableModel(QObject *parent) :
QAbstractTableModel(parent)
{
    timer = new QTimer(this);

    connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)));
    connect(timer, SIGNAL(timeout()), this, SLOT(timerDone()));

    timer->start(1000);
}

void TxTableModel::refreshData()
{
    TxRequest request;
    request.setObject("order");
    request.setMethod("getlist");
    request.addParam("begin_time", 60*60*4);
    request.addParam("end_time", 60*4);

    http.queryAsync(request);
}

void TxTableModel::parseXml(const QByteArray &xml)
{
    //qDebug() << xml;

    int count = m_Data.getRowCount();

    QXmlInputSource inputSource;
    QXmlSimpleReader reader;
    TxSaxTableHandler handler(&m_Data, false);

    inputSource.setData(xml);
    reader.setContentHandler(&handler);
    reader.setErrorHandler(&handler);

    beginResetModel();
    reader.parse(inputSource);
    endResetModel();
}

void TxTableModel::httpDone(bool error)
{
    if (error) {
        qDebug() << http.errorString();
    } else {
        parseXml(http.readAll());
    }
}

void TxTableModel::timerDone()
{
    refreshData();
}

Solution

  • It looks like you're not providing the full source of TxTableModel model, as it's missing implementation of rowCount, columnCount, data, setData, etc methods.

    As for the problem, my guess would be:

    1. As it was already suggested you can try cleaning the model before reloading it by calling removeRows(0, rowCount());

    2. in your removeRows implementation, you should call beginRemoveRows before updating the rows collection and endRemoveRows after you're done. This should notify views about the model content change.

    There is an example on how to implement the QAbstractTableModel here: Address Book Example

    hope this helps, regards