PDA

View Full Version : closeEditor() not always closing QLineEdit



mclark
26th November 2007, 18:16
While using my custom QItemDelegate, the QLineEdit editor is not always closing. The closeEditor() signal is emitted but the QLineEdit object remains in the QTableWidgetItem.

I am using 4.2.2 and setting the edit triggers using QAbstractItemView::AllEditTriggers.

This happens when I have multiple rows in the table and I click (speed is irrelevant) on the editable items:
Click on row 0, column 1
Click on row 1, column 1
Click on row 2, column 1
repeat
Eventually one of the editors in column 1 will get stuck on, even though the closeEditor() signal was emitted. The qDebug() statement shows the contents of the item where the editor should be closed and is displayed even when the editor does not go away. This state does not allow any other editors to appear in the table, effectively stopping the user from editing any other items.

Has anyone else seen this type of behavior? Any ideas how to prevent this?


class DMXTableCellDelegate : public QItemDelegate
{
Q_OBJECT

public:
DMXTableCellDelegate( QObject* parent = 0 ) : QItemDelegate( parent )
{ m_parent = parent; }

QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option,
const QModelIndex& index ) const;

private slots:
void commitAndCloseEditor( void );

private:
QObject* m_parent;

};

QWidget* DMXTableCellDelegate::createEditor( QWidget* parent,
const QStyleOptionViewItem& option,
const QModelIndex& index ) const
{
if ( index.column() == COL_Name )
{
QLineEdit* lineEdit = new QLineEdit( parent );
lineEdit->setMaxLength( DEVICE_NAME_MAX );

connect( lineEdit, SIGNAL( returnPressed() ),
this, SLOT( commitAndCloseEditor() ) );
connect( lineEdit, SIGNAL( editingFinished() ),
this, SLOT( commitAndCloseEditor() ) );

return lineEdit;
}
else
return QItemDelegate::createEditor( parent, option, index );
}

void DMXTableCellDelegate::commitAndCloseEditor( void )
{
QLineEdit* editor = qobject_cast<QLineEdit*>( sender() );
emit commitData( editor );
qDebug( "emit closeEditor(): %s", editor->text().toAscii().data() );
emit closeEditor( editor, QAbstractItemDelegate::EditNextItem );
}

wysota
26th November 2007, 19:06
Are you sure you should emit the signal yourself? I'm not sure the signal is meant to be used this way. From what I see you should reimplement QAbstractItemDelegate::setModelData() instead.

mclark
26th November 2007, 19:54
Are you sure you should emit the signal yourself? I'm not sure the signal is meant to be used this way. From what I see you should reimplement QAbstractItemDelegate::setModelData() instead.

I believe I'm safe using the code this way because I took it directly from an example in the C++ GUI Programming With Qt 4 book (Chap. 10 Implementing Custom Delegates).

mclark
26th November 2007, 23:05
I added the following connection to verify that the QLineEdit object was not being destroyed by the delegate:

connect( lineEdit, SIGNAL( destroyed( QObject* ) ),
this, SLOT( DEBUG_destroyed( QObject* ) ) );

. . .

void DMXTableCellDelegate::DEBUG_destroyed( QObject* obj )
{
qDebug( "destroyed() - 0x%x", obj );
}
The output result was:

emit closeEditor( 0x17118b8 ): Larry Fist
destroyed() - 0x17118b8
emit closeEditor( 0x1716900 ): Thing 2
destroyed() - 0x1716900
emit closeEditor( 0x1706258 ): Thing 1The destroyed() signals were received by my delegate for each focus change until the last when no destroyed() signal was received. At this point the editor was still active while focus was on another item.

UPDATE:
I placed a qDebug() call in the createEditor() and what I noticed, for 3 table rows, as I slowly clicked through each column 1 item, was that editor objects were created at only two memory locations. As soon as a third memory location was used the editor froze. A closeEditor() was emitted but no destroyed() signal was received. Could this be a clue?

wysota
27th November 2007, 00:05
I think your connect statements are incorrect. editingFinished() is emited when return is pressed, so there is no need to connect to returnPressed as well... Maybe that's your problem? Lose one of those connect statements and see if the situation improves.

mclark
27th November 2007, 00:16
Lose one of those connect statements and see if the situation improves.

Thanks wysota, you are partially right. By removing the returnPressed() connection other items can now be edited when an editor in an item gets stuck 'on'. But, I still get an editor stuck 'on', the delegate never gets sent the destroyed() signal.

wysota
27th November 2007, 00:26
Maybe there is a bug in your version of Qt? Upgrade might fix the problem. Or at least search the task-tracker to see if a similar issue was reported.

mclark
27th November 2007, 00:34
Thanks again wysota, I'm putting together a 'simple' application to test my thought that this may be a bug in Qt 4.2.2. I may have to update to 4.3... If I find a solution I'll post it here.

wysota
27th November 2007, 02:44
As I said, check the task-tracker. It might save you a lot of time and effort.