Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, May 2008
Problem with SIGNAL currentCellChanged(int, int, int, int) in QTableWidget


Message 1 in thread

Hi,

I came across this peculiar problem with SIGNAL currentCellChanged(int, 
int, int, int)  in QTableWidget.

I am using QTableWidget class for the application that I am developing 
and have made the following settings with it.

tablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

There is a pushbutton next to the table which calls a function to remove 
a selected row on receiving a click.

Now, for example, if there are 8 rows in the tableWidget, and I select 
row 4 and click on remove button. Row 4 will be removed and the 
selection will jump up to row 3. SIGNAL currentCellChanged will also 
emit the new row as row 3. This behaviour is fine. The problem comes 
when row 0 (THE FIRST ROW) is the one that is selected and removed.  Now 
since there is no place to  jump 'up', the next automatic selection 
jumps 'down'  to row 1 SIGNAL currentCellChanged emits that row 1 is the 
new row............. BUT row 1 is now new row 0 (since row 0 was 
removed) .  This means that SIGNAL currentCellChanged emits wrong row 
number as the new row. It emits row 1 instead of row 0. *All this 
assumes that we manually (by clicking with mouse or by keyboard tab 
button) don't intervene in the selection process.*

Now if we click on the remove button to remove the currently selected 
row 0, then the row 0 *does not get deleted (removed)* rather the one 
down below gets removed.

I hope I have been able to explain the problem.  I have written a small 
example to demonstrate it.


#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QPushButton>
#include <QRect>

class TableTest : public QTableWidget {

Q_OBJECT

public:
	TableTest(QWidget *parent);

private slots:
	void removeRow();
	void updateSelection(int row);

private:
	QPushButton *button;
	QTableWidget *tw;
	int selectedRow;
};

TableTest::TableTest(QWidget *parent) : QTableWidget(parent) {
	tw = new QTableWidget (5, 1, parent);
	tw->setGeometry(QRect(30, 30, 291, 201));
	tw->resizeRowsToContents();
	tw->setSelectionBehavior(QAbstractItemView::SelectRows);
	tw->setSelectionMode(QAbstractItemView::SingleSelection);
	for (int i=0; i<6; i++){
		tw->setItem(i, 0, new QTableWidgetItem("This is row 
"+QString::number(i+1)));
	}
	button = new QPushButton(parent);
	button->setGeometry(QRect(110, 250, 83, 28));
	button->setText("Remove Row");
	connect(tw, SIGNAL(currentCellChanged(int, int, int, int)), this, 
SLOT(updateSelection(int)));
	connect(button, SIGNAL(clicked()), this, SLOT(removeRow()));
	tw->setCurrentCell(0,0);
}

void TableTest::updateSelection(int row){
	selectedRow=row;
}

void TableTest::removeRow(){
	tw->removeRow(selectedRow);
}

#include "main.moc"

int main(int argc, char *argv[] ){
	QApplication app(argc, argv);
	QWidget *w = new QWidget();
	w->resize(346, 289);
	TableTest  tt(w);
	w->show();
	return app.exec();
}


Start the program and click on 'Remove Row' button. On clicking the 
button,  'This is row 1' gets deleted (removed) from the table and the 
selection automatically goes to 'This is row 2'. Now *without clicking 
anywhere else* in the table, click on the 'Remove Row' button again. 
Logically, 'This is row 2' should get removed because that is the one 
with the selection. But, instead 'This is row 3' will get deleted 
(removed). That is because the SIGNAL currentCellChanged is emitting the 
wrong current row number.

Is this a bug or am I doing something wrong?

Rajen.

--
 [ signature omitted ] 

Message 2 in thread

I think QT emit signal currentCellChanged before deleting the row.

So, if you have selected row > 0, QT select 'row - 1' (emit signal whit 
newRow = row - 1) and later will be deleted oldRow.
And, if you have selected row  0, QT select row  1 (emit signal whit 
newRow = 1) and later will be deleted row 0. So, the signal is correct, 
newRow is row 1.

Well, if you want assuring you could create new slot whit four params, 
and connect this slot whit the signal currentCellChanged, then you are 
going to be assured by printing the params (current column/row and 
previous column/row).

I hope it will be useful for you.
Salu2.

Sorry for my (bad)English.


Rajen M. Parekh escribió:
> Hi,
>
> I came across this peculiar problem with SIGNAL 
> currentCellChanged(int, int, int, int)  in QTableWidget.
>
> I am using QTableWidget class for the application that I am developing 
> and have made the following settings with it.
>
> tablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
> tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
>
> There is a pushbutton next to the table which calls a function to 
> remove a selected row on receiving a click.
>
> Now, for example, if there are 8 rows in the tableWidget, and I select 
> row 4 and click on remove button. Row 4 will be removed and the 
> selection will jump up to row 3. SIGNAL currentCellChanged will also 
> emit the new row as row 3. This behaviour is fine. The problem comes 
> when row 0 (THE FIRST ROW) is the one that is selected and removed.  
> Now since there is no place to  jump 'up', the next automatic 
> selection jumps 'down'  to row 1 SIGNAL currentCellChanged emits that 
> row 1 is the new row............. BUT row 1 is now new row 0 (since 
> row 0 was removed) .  This means that SIGNAL currentCellChanged emits 
> wrong row number as the new row. It emits row 1 instead of row 0. *All 
> this assumes that we manually (by clicking with mouse or by keyboard 
> tab button) don't intervene in the selection process.*
>
> Now if we click on the remove button to remove the currently selected 
> row 0, then the row 0 *does not get deleted (removed)* rather the one 
> down below gets removed.
>
> I hope I have been able to explain the problem.  I have written a 
> small example to demonstrate it.
>
>
> #include <QApplication>
> #include <QTableWidget>
> #include <QTableWidgetItem>
> #include <QPushButton>
> #include <QRect>
>
> class TableTest : public QTableWidget {
>
> Q_OBJECT
>
> public:
>     TableTest(QWidget *parent);
>
> private slots:
>     void removeRow();
>     void updateSelection(int row);
>
> private:
>     QPushButton *button;
>     QTableWidget *tw;
>     int selectedRow;
> };
>
> TableTest::TableTest(QWidget *parent) : QTableWidget(parent) {
>     tw = new QTableWidget (5, 1, parent);
>     tw->setGeometry(QRect(30, 30, 291, 201));
>     tw->resizeRowsToContents();
>     tw->setSelectionBehavior(QAbstractItemView::SelectRows);
>     tw->setSelectionMode(QAbstractItemView::SingleSelection);
>     for (int i=0; i<6; i++){
>         tw->setItem(i, 0, new QTableWidgetItem("This is row 
> "+QString::number(i+1)));
>     }
>     button = new QPushButton(parent);
>     button->setGeometry(QRect(110, 250, 83, 28));
>     button->setText("Remove Row");
>     connect(tw, SIGNAL(currentCellChanged(int, int, int, int)), this, 
> SLOT(updateSelection(int)));
>     connect(button, SIGNAL(clicked()), this, SLOT(removeRow()));
>     tw->setCurrentCell(0,0);
> }
>
> void TableTest::updateSelection(int row){
>     selectedRow=row;
> }
>
> void TableTest::removeRow(){
>     tw->removeRow(selectedRow);
> }
>
> #include "main.moc"
>
> int main(int argc, char *argv[] ){
>     QApplication app(argc, argv);
>     QWidget *w = new QWidget();
>     w->resize(346, 289);
>     TableTest  tt(w);
>     w->show();
>     return app.exec();
> }
>
>
> Start the program and click on 'Remove Row' button. On clicking the 
> button,  'This is row 1' gets deleted (removed) from the table and the 
> selection automatically goes to 'This is row 2'. Now *without clicking 
> anywhere else* in the table, click on the 'Remove Row' button again. 
> Logically, 'This is row 2' should get removed because that is the one 
> with the selection. But, instead 'This is row 3' will get deleted 
> (removed). That is because the SIGNAL currentCellChanged is emitting 
> the wrong current row number.
>
> Is this a bug or am I doing something wrong?
>
> Rajen.
>
> -- 
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with 
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>


-- 
 [ signature omitted ] 

Message 3 in thread

> I came across this peculiar problem with SIGNAL 
> currentCellChanged(int, int, int, int)  in QTableWidget.

While it could be argued that the signal is wrong (you should send a
mail to qt-bugs or use the form
http://trolltech.com/developer/bugreport-form), why do you store the
"selectedRow" at all?

Instead use tw->currentRow() or tw->selectionModel()->selectedRows().

Cheers,
Peter

--
 [ signature omitted ] 

Message 4 in thread

Please reply to the list, not to me in private.

Rajen M. Parekh wrote:
> Peter Prade wrote:
> >> I came across this peculiar problem with SIGNAL 
> >> currentCellChanged(int, int, int, int)  in QTableWidget.
> > 
> > While it could be argued that the signal is wrong (you should send a
> > mail to qt-bugs or use the form
> > http://trolltech.com/developer/bugreport-form), why do you store the
> > "selectedRow" at all?
> > 
> > Instead use tw->currentRow() or 
> tw->selectionModel()->selectedRows().
> 
> Even currentRow() gives wrong row number of the row which is 
> selected. 
> What I mean is that the selection lies on first row (row 0) but the 
> currentRow() function gives result as 1 (row 1), when 
> actually it should 
> be 0 (row 0).
> 
> Same is the case with  tw->selectionModel()->selectedRows().
> 
> Rajen.

I've just modified your example code, change the removeRow slot to:

void TableTest::removeRow(){
	tw->removeRow(tw->currentRow());
}

Works for me, using Qt 4.3.3!

Cheers,
Peter

--
 [ signature omitted ] 

Message 5 in thread

Miguel Ángel Orenes Fernández wrote:

>> The signal is correct *before* the removal, because it emits before 
>> the row is removed. But that is wrong. The signal should be emitted 
>> *after* the row is removed, thereby giving the correct selected row 
>> number.

> Why?
> QT emits this signal when the new row is selected (not when the row is 
> deleted), 

Correct.

> then if the new row is selected *before* deleting the old row, 
> will emits signal *before* deleting.
> I think QT emits the signal correctly.

The signal is wrong in the sense that it should emit *after* the row is
removed. Then it would probably emit the correct row number where the
selection lies. I am trying to explain again below.

When the current selection lies on row 0 (the first row) currentRow()
function will give result 0 (meaning row 0). When you remove this row
the selection goes on row 1 (the second row). At this point the signal
gets emitted saying that current cell of the second row (row 1).  But
since we have removed the first row (row 0), the second  row has now
become the first row (row 0 ). This means that the signal which emitted
row 1 as current row is wrong. It becomes wrong because it was called
*before* the row was removed, if it was called *after* the row was
removed then I think it would emit the correct row number with the
selection.

I sincerely hope that I have been able to explain my view.

Rajen.

--
 [ signature omitted ]