PDA

View Full Version : Possible QTableWidget bug appeared in new Qt 4.5.3?



lalesculiviu
19th October 2009, 13:32
Hello!

I am the author of a free software for timetabling, http://lalescu.ro/liviu/fet/

I have met a problem with latest Qt 4.5.3 (not shown in previous versions of Qt), problem which exists on Linux and on Windows.

The problem is that if I change data in a QTableWidget using function table->item(row,col)->setText("new text"), the first row of the table is not update until I move the mouse over it. For this, run the attached sample, press the button and see that the first row is not updated until you move mouse over table.

I have a very small example, attached.

I found that the bug can be avoided if I write "table->viewport()->update()" after changing of one or more values. But this may consume unnecessary time?

Maybe you can help me with advice on how to avoid better this bug. It is important that my software works well with Qt 4.5.3 and with future versions.

I submitted this possible bug to Qt task tracker, but I have not received answer until now.

I write below the example (it is the same as the archived attachment):

bug.h:


#include <QApplication>

#include <QtGui>

class Dialog: public QDialog
{
Q_OBJECT

public:
QVBoxLayout* layout;
QTableWidget* table;
QPushButton* pb;

Dialog();
~Dialog();

public slots:
void pbClicked();
};

bug.cpp:


#include "bug.h"

#include <QApplication>

#include <QtGui>

Dialog::Dialog()
{
layout=new QVBoxLayout(this);

table=new QTableWidget();

pb=new QPushButton("Press me");

layout->addWidget(table);
layout->addWidget(pb);

connect(pb, SIGNAL(clicked()), this, SLOT(pbClicked()));

table->setRowCount(5);
table->setColumnCount(5);

for(int i=0; i<5; i++)
for(int j=0; j<5; j++){
QTableWidgetItem* item=new QTableWidgetItem();
item->setText("initial");
table->setItem(i, j, item);
}
table->resizeRowsToContents();
}

Dialog::~Dialog()
{
}

void Dialog::pbClicked()
{
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
table->item(i,j)->setText(tr("Cell %1,%2 modified").arg(i).arg(j));
}

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

Dialog dialog;
dialog.show();

return app.exec();
}

lyuts
19th October 2009, 14:57
Works fine for me with Qt 4.5.3.

lalesculiviu
19th October 2009, 15:22
Works fine for me with Qt 4.5.3.

On what platform? Windows, Linux, Mac? I have AMD64 bit dual core.

I meant the problem is this: initially, the table has all cells with text "Initial". After you press the button "Press me", all the cells should have the text: "Cell i,j modified". But the first row still shows text "Initial", until you move mouse over table or make some clicks.

lyuts
19th October 2009, 15:48
Yeah, I do understand the actual behavior and the desired one.

I'm on 32bit Linux, though i don't have AMD.

lalesculiviu
20th October 2009, 12:41
I tried the same code on another computer, old laptop with Windows XP, I get the same bug. I also get this bug on my computer, GNU/Linux openSUSE 11.1 64 bit.

Yes, it is a bug, I found it on my computer and I found that they fixed it (by comparing the 4.5.2, 4.5.3 (buggy) and 4.6.0-snapshot (fixed).

My question: I found a hack to make my program work in Qt 4.5.3. Should I keep this hack only for 4.5.3? It is a time taking step and I don't want to do it unnecessarily.

Below are the code parts from Qt, if you are interested. They changed from 4.5.3 to 4.6.0 the part of d->viewport->geometry() to d->viewport->rect()

I found practically with my sample that for instance viewport geometry is: 15,20,100,100 and viewport rect is 0,0,100,100 (so you need to take care of 0,0 and not of 15,20, which is the relative distance to father widget).

4.5.2 (working OK, probably not optimized):


void QAbstractItemView::update(const QModelIndex &index)
{
Q_D(QAbstractItemView);
if (index.isValid())
d->viewport->update(visualRect(index));
}

4.5.3 (buggy):


void QAbstractItemView::update(const QModelIndex &index)
{
Q_D(QAbstractItemView);
if (index.isValid()) {
const QRect rect = visualRect(index);
//this test is important for peformance reason
//For example in dataChanged we simply update all the cells without checking
//it can be a major bottleneck to update rects that aren't even part of the viewport
if (d->viewport->geometry().intersects(rect))
d->viewport->update(rect);
}
}

4.6.0-snapshot (solved):


void QAbstractItemView::update(const QModelIndex &index)
{
Q_D(QAbstractItemView);
if (index.isValid()) {
const QRect rect = visualRect(index);
//this test is important for peformance reason
//For example in dataChanged we simply update all the cells without checking
//it can be a major bottleneck to update rects that aren't even part of the viewport
if (d->viewport->rect().intersects(rect))
d->viewport->update(rect);
}
}

http://qt.gitorious.org/qt/qt/commit/0baa15e68c7b2e009c1f81f81148939725c216c8

is the bug listed on Gitorious.

So, could you please tell me, can I expect that this bug is only in Qt 4.5.3, so my program works OK?

Teuniz
20th October 2009, 17:26
I noticed this bug as well using Qt 4.5.3 on OpenSUSE 11.0.

I use the following workaround:

Instead of

function table->item(row,col)->setText("new text")

I use

((QLabel *)(function table->cellwidget(row,col)))->setText("new text")

Ofcourse you have to change your code in such a way that it use QLabels instead of itemtext's.

Your new code will look like:


#include "bug.h"

#include <QApplication>

#include <QtGui>

Dialog::Dialog()
{
layout=new QVBoxLayout(this);

table=new QTableWidget();

pb=new QPushButton("Press me");

layout->addWidget(table);
layout->addWidget(pb);

connect(pb, SIGNAL(clicked()), this, SLOT(pbClicked()));

table->setRowCount(5);
table->setColumnCount(5);

for(int i=0; i<5; i++)
for(int j=0; j<5; j++){
QLabel *label=new QLabel();
label->setText("initial");
table->setCellWidget(i, j, label);
}
table->resizeRowsToContents();
}

Dialog::~Dialog()
{
}

void Dialog::pbClicked()
{
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
((QLabel *)(table->cellWidget(i,j)))->setText(tr("Cell %1,%2 modified").arg(i).arg(j));
}

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

Dialog dialog;
dialog.show();

return app.exec();
}

lalesculiviu
20th October 2009, 17:52
Thanks, Teuniz, but I think your solution to avoid this bug is less convenient (at least for me) than my hack (solution) to avoid this bug.

Do you think that since they fixed this bug in the repositories, Qt 4.5.3 will remain the only Qt version with this bug? I do not want to apply my hack uselessly, but I want to make sure my program is bug free for future Qt versions.