PDA

View Full Version : QTableView massive model data updates issue



cyberbob
1st December 2010, 21:56
Hi,

Just learning QT as an option for replacing existing WPF application which shows horizontally scrolled set of mid size grids (10 grids, 100 rows x 20 cols) with custom cell contents (some numbers, arrows, signs ...). Grid contents are refreshed about 2-3 times per second, almost all cells. Updates are done through model.

The issue is the following, application crashes randomly and I think it is related to QVariant object manipulation, check/set/get variant from model. Here is the sample code that is crashing after running for some time (10 sec to 2-3 mins):

Here is the code:



#include <QApplication>
#include <QtCore>
#include <QWidget>
#include <QStandardItemModel>
#include <QTableView>
#include <QScrollArea>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QSizePolicy>
#include <QMainWindow>
#include <iostream>
#include <QtGui>
#include <stdlib.h>

using namespace std;

class MyObject {

};

Q_DECLARE_METATYPE(MyObject)


class PaintDelegate : public QStyledItemDelegate {

public:
PaintDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}

void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (qVariantCanConvert<MyObject>(index.data(Qt::UserRole + 1))) {
MyObject myObj = qVariantValue<MyObject>(index.data(Qt::UserRole + 1));

painter->save();
painter->translate(option.rect.x() + 5, option.rect.y() + 10);
painter->drawText(0, 0, QString("test %1").arg(rand()%1000));
painter->restore();

} else {
QStyledItemDelegate::paint(painter, option, index);
}
}

QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
qVariantCanConvert<MyObject>(index.data(Qt::UserRole + 1));
return QSize(50, 10);
}
};

int main(int argc, char** argv)
{
QApplication app( argc, argv );

QStandardItemModel *model = new QStandardItemModel();
QStandardItem * item = new QStandardItem("item 1");
item->setData(qVariantFromValue(MyObject()));
model->setItem(0, 0, item);
QTableView * tableView2 = new QTableView();
tableView2->setModel(model);
tableView2->setItemDelegate(new PaintDelegate);
tableView2->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
tableView2->show();

extern void updateModel(QStandardItemModel*);
QtConcurrent::run(updateModel, model);

return app.exec();
}

void updateModel(QStandardItemModel* model){
for (;;){
model->item(0, 0)->setData(qVariantFromValue(MyObject()));
usleep(1000);
}
}



Here is the error:



*** glibc detected *** /home/bob/Documents/TableViewTest-build-desktop/TableViewTest: free(): invalid pointer: 0x00007f57d000a190 ***
======= Backtrace: =========
/lib/libc.so.6(+0x774b6)[0x7f57ea7cd4b6]
/lib/libc.so.6(cfree+0x73)[0x7f57ea7d3c83]
/home/bob/Documents/TableViewTest-build-desktop/TableViewTest[0x4031e8]
/usr/lib/libQtCore.so.4(_ZN9QMetaType7destroyEiPv+0x62)[0x7f57eb6089a2]
/usr/lib/libQtCore.so.4(+0x18bfe2)[0x7f57eb620fe2]
/home/bob/Documents/TableViewTest-build-desktop/TableViewTest[0x402db7]
/usr/lib/libQtGui.so.4(+0x73f04d)[0x7f57ec07004d]
/usr/lib/libQtGui.so.4(_ZN10QTableView10paintEventEP11QPain tEvent+0x913)[0x7f57ec071753]
/usr/lib/libQtGui.so.4(_ZN7QWidget5eventEP6QEvent+0x59e)[0x7f57ebb3ec2e]
/usr/lib/libQtGui.so.4(_ZN6QFrame5eventEP6QEvent+0x26)[0x7f57ebf0a5e6]
/usr/lib/libQtGui.so.4(_ZN17QAbstractItemView13viewportEven tEP6QEvent+0x3eb)[0x7f57ec043a8b]
/usr/lib/libQtCore.so.4(_ZN23QCoreApplicationPrivate29sendT hroughObjectEventFiltersEP7QObjectP6QEvent+0x87)[0x7f57eb5fd507]
/usr/lib/libQtGui.so.4(_ZN19QApplicationPrivate13notify_hel perEP7QObjectP6QEvent+0x7c)[0x7f57ebae8fac]
/usr/lib/libQtGui.so.4(_ZN12QApplication6notifyEP7QObjectP6 QEvent+0x14d)[0x7f57ebaeeaed]
/usr/lib/libQtCore.so.4(_ZN16QCoreApplication14notifyIntern alEP7QObjectP6QEvent+0x8c)[0x7f57eb5fdcdc]
/usr/lib/libQtGui.so.4(_ZN14QWidgetPrivate10drawWidgetEP12Q PaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidge tBackingStore+0x3bd)[0x7f57ebb4567d]
/usr/lib/libQtGui.so.4(+0x3e83a6)[0x7f57ebd193a6]
/usr/lib/libQtGui.so.4(_ZN14QWidgetPrivate16syncBackingStor eEv+0x80)[0x7f57ebb38730]
/usr/lib/libQtGui.so.4(_ZN7QWidget5eventEP6QEvent+0xc65)[0x7f57ebb3f2f5]
/usr/lib/libQtGui.so.4(_ZN6QFrame5eventEP6QEvent+0x26)[0x7f57ebf0a5e6]
/usr/lib/libQtGui.so.4(_ZN19QAbstractScrollArea5eventEP6QEv ent+0x8b)[0x7f57ebf9871b]
/usr/lib/libQtGui.so.4(_ZN17QAbstractItemView5eventEP6QEven t+0x9b)[0x7f57ec03c51b]
/usr/lib/libQtGui.so.4(_ZN19QApplicationPrivate13notify_hel perEP7QObjectP6QEvent+0xac)[0x7f57ebae8fdc]
/usr/lib/libQtGui.so.4(_ZN12QApplication6notifyEP7QObjectP6 QEvent+0x14d)[0x7f57ebaeeaed]
/usr/lib/libQtCore.so.4(_ZN16QCoreApplication14notifyIntern alEP7QObjectP6QEvent+0x8c)[0x7f57eb5fdcdc]
/usr/lib/libQtCore.so.4(_ZN23QCoreApplicationPrivate16sendP ostedEventsEP7QObjectiP11QThreadData+0x2d2)[0x7f57eb600c22]
/usr/lib/libQtCore.so.4(+0x195653)[0x7f57eb62a653]
/lib/libglib-2.0.so.0(g_main_context_dispatch+0x1f2)[0x7f57e9deb342]
/lib/libglib-2.0.so.0(+0x442a8)[0x7f57e9def2a8]
/lib/libglib-2.0.so.0(g_main_context_iteration+0x6c)[0x7f57e9def45c]
/usr/lib/libQtCore.so.4(_ZN20QEventDispatcherGlib13processE ventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE+0 x73)[0x7f57eb62a193]
/usr/lib/libQtGui.so.4(+0x26aa4e)[0x7f57ebb9ba4e]
/usr/lib/libQtCore.so.4(_ZN10QEventLoop13processEventsE6QFl agsINS_17ProcessEventsFlagEE+0x32)[0x7f57eb5fca02]
/usr/lib/libQtCore.so.4(_ZN10QEventLoop4execE6QFlagsINS_17P rocessEventsFlagEE+0xdc)[0x7f57eb5fcdec]
/usr/lib/libQtCore.so.4(_ZN16QCoreApplication4execEv+0xbb)[0x7f57eb600ebb]
/home/bob/Documents/TableViewTest-build-desktop/TableViewTest[0x4025e6]
/lib/libc.so.6(__libc_start_main+0xfe)[0x7f57ea774d8e]
/home/bob/Documents/TableViewTest-build-desktop/TableViewTest[0x4022c9]


Please advice or correct me if I am using View/Model approach incorrectly.

cyberbob
2nd December 2010, 15:52
Simplified version of the code which gives the same error:


#include <QApplication>
#include <QtCore>
#include <QStandardItemModel>
#include <QTableView>
#include <QtGui>

using namespace std;

class MyObject {

};

Q_DECLARE_METATYPE(MyObject)


class PaintDelegate : public QStyledItemDelegate {

public:
PaintDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}

void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (qVariantCanConvert<MyObject>(index.data(Qt::UserRole + 1))) {
MyObject myObj = qVariantValue<MyObject>(index.data(Qt::UserRole + 1));
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}

};

int main(int argc, char** argv)
{
QApplication app( argc, argv );

QStandardItemModel *model = new QStandardItemModel();
QStandardItem * item = new QStandardItem("item 1");
item->setData(qVariantFromValue(MyObject()));
model->setItem(0, 0, item);
QTableView * tableView2 = new QTableView();
tableView2->setModel(model);
tableView2->setItemDelegate(new PaintDelegate);
tableView2->show();

extern void updateModel(QStandardItemModel*);
QtConcurrent::run(updateModel, model);

return app.exec();
}

void updateModel(QStandardItemModel* model){
for (;;){
model->item(0, 0)->setData(qVariantFromValue(MyObject()));
}
}

ChrisW67
2nd December 2010, 22:26
The original code didn't fail here on 32-bit Linux after a few minutes of running, the new code crashes immediately probably because the delay is no longer in your update loop. It could be a thread synchronisation issue. Have you considered locking? Have you tried using a QTimer and dispensing with the separate thread?

Are you intending to paint anything if the item contains a MyObject?

cyberbob
7th December 2010, 23:09
Hi, Thanks for the try.

This is just an example to show the error. If this is a defect inside qt maybe it should be logged as such so someone could fix it.

In my real app I used two QTimers and a synchronized temporary store (QSet) to accumulate changes. First QTimer puts data into the store (high frequency) another updates UI (less frequently). This approach has not crashed yet, maybe because I am not touching model at such a high rate.

I have 63bit Linux. The example above crashed once on 32bit windows virtual box.