Results 1 to 14 of 14

Thread: QItemDelegate Editor Crash

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question QItemDelegate Editor Crash

    Greetings,

    I am using Qt4.2.2 on Windows. I am seeing a crash when trying to validate a string in a QLineEdit object created in a QItemDelegate.

    There are 6 characters that are invalid for this string. My thought was to create a delegate that would handle this (based off of the TrackEditor example in the "C++ GUI Programming With Qt4" book.

    If the user enters an invalid character in the string, '(' for example, a message will be displayed to inform them that the string will be changed to replace the '(' with '['. The string is then changed and displayed.

    This all happens after the user presses the Tab or Enter keys. Pressing the Tab key causes this to work as designed. Pressing the Enter key causes a crash. It is crashing after the processing in the SLOT_itemChanged() call, but before the commitData() call in delegate function, commitAndCloseEditor().

    My table also has eventHandler code to determine if the user is exiting the QTableWidgetItem via Tab or Enter key press. This code is not hit, the error occurs before this is called.

    It appears that the pointer to the actual string in the QLineEdit object is getting corrupted by me trying to change it. The fact that it works when a Tab is pressed but not when Enter is pressed is bothersome.

    Has anyone else seen this behavior? Or, might there be a better way to validate a string in a QTableWidget cell?

    Thanks for taking the time to look at this.

    In my table ctor:
    Qt Code:
    1. m_pTableCellKeyHandler = new TableCellKeyHandler( this );
    2.  
    3. setItemDelegate( new DMXTableCellDelegate( this ) );
    4.  
    5. connect( this, SIGNAL( itemChanged( QTableWidgetItem* ) ),
    6. this, SLOT( SLOT_itemChanged( QTableWidgetItem* ) ) );
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QWidget* DMXTableCellDelegate::createEditor( QWidget* parent,
    2. const QStyleOptionViewItem& option,
    3. const QModelIndex& index ) const
    4. {
    5. if ( index.column() == COL_Name )
    6. {
    7. QLineEdit* lineEdit = new QLineEdit( parent );
    8. lineEdit->setMaxLength( DEVICE_NAME_MAX );
    9.  
    10. connect( lineEdit, SIGNAL( editingFinished() ),
    11. this, SLOT( commitAndCloseEditor() ) );
    12.  
    13. return lineEdit;
    14. }
    15. else if ( index.column() == COL_Next )
    16. {
    17. ...
    18. }
    19. else
    20. return QItemDelegate::createEditor( parent, option, index );
    21. }
    22.  
    23.  
    24. void DMXTableCellDelegate::commitAndCloseEditor( void )
    25. {
    26. QLineEdit* editor = qobject_cast<QLineEdit*>( sender() );
    27. emit commitData( editor );
    28. emit closeEditor( editor );
    29. }
    30.  
    31.  
    32. void DMXTable::SLOT_itemChanged( QTableWidgetItem* pItem )
    33. {
    34. int nRow = pItem->row();
    35. int nCol = pItem->column();
    36.  
    37. CDMXGateway* pDevice = static_cast<CDMXGateway*>( GetDeviceData( nRow ) );
    38. if ( pDevice == NULL )
    39. return;
    40.  
    41. // Turn off sorting
    42. m_pDMXCfgTable->setSortingEnabled( false );
    43.  
    44. // Process device-specific cells
    45. bool bValueChanged = false;
    46. QString sNewName;
    47. bool bNameChanged = false;
    48.  
    49. switch ( nCol )
    50. {
    51. case COL_Name:
    52. {
    53. sNewName = pItem->text();
    54.  
    55. if ( (bNameChanged = updateNameItem( pItem, sNewName, static_cast<CNode*>( pDevice ) )) )
    56. bValueChanged = true;
    57.  
    58. break;
    59. }
    60. ...
    61. }
    62.  
    63. m_pDMXCfgTable->setSortingEnabled( true );
    64. }
    65.  
    66.  
    67. bool Table::updateNameItem( QTableWidgetItem* pItem,
    68. QString& sNewName, CNode* pNode )
    69. {
    70. bool bNameChanged = false;
    71.  
    72. QString sOldName = pNode->GetDeviceName();
    73.  
    74. // Compare new name to old name
    75. if ( sOldName.compare( sNewName, Qt::CaseSensitive ) != 0 )
    76. {
    77. QString sTypedName( sNewName );
    78. if ( !m_parent->ValidateDeviceName( sNewName ) )
    79. {
    80. // Restrict length
    81. if ( sNewName.length() > DEVICE_NAME_MAX )
    82. sNewName.truncate( DEVICE_NAME_MAX );
    83.  
    84. if ( !m_parent->ShowRestrictedCharMsg( sTypedName, sOldName, sNewName ) )
    85. {
    86. pItem->setText( sOldName );
    87. return false;
    88. }
    89.  
    90. pItem->setText( sNewName );
    91. }
    92.  
    93. pNode->SetDeviceName( sNewName );
    94. bNameChanged = true;
    95.  
    96. if ( !m_bIsCfgTable && pNode->IsOnline() ) // update and save now
    97. m_parent->m_pController->UpdateDeviceName( pNode->GetDevType(), sNewName, pNode, true );
    98. }
    99.  
    100. return bNameChanged;
    101. }
    102.  
    103.  
    104. bool MainWin::ValidateDeviceName( QString& sName )
    105. {
    106. bool bCharIsValid = true;
    107. QChar c;
    108.  
    109. // Substitute for illegal Discovery characters
    110. for ( int i = 0; i < sName.length(); i++ )
    111. {
    112. c = sName.at( i );
    113.  
    114. if ( c == '(' )
    115. {
    116. sName.replace( i, 1, "[" );
    117. bCharIsValid = false;
    118. }
    119. ...
    120. }
    121.  
    122. return bCharIsValid;
    123. }
    124.  
    125.  
    126. bool TableCellKeyHandler::eventFilter( QObject* obj, QEvent* pEvent )
    127. {
    128. if ( pEvent->type() == QEvent::KeyPress )
    129. {
    130. QKeyEvent* pKeyEvent = static_cast<QKeyEvent*>( pEvent );
    131. int nKey = pKeyEvent->key();
    132.  
    133. // Check for enter keys: 0x01000004 || 0x01000005
    134. if ( (nKey == Qt::Key_Return) || (nKey == Qt::Key_Enter) )
    135. {
    136. int nRow = m_pParent->currentRow();
    137. int nCol = m_pParent->currentColumn();
    138. qDebug( "eventFilter(): ( %u, %u )", nRow, nCol );
    139.  
    140. ...
    141. }
    142. }
    143. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QItemDelegate Editor Crash

    How about simply installing a QValidator subclass instance on the editor and letting it handle the validation for you? Alternatively you can handle validation in the model itself - in its setData() method (or in setData() of the item itself in case you're using convenience widgets and not the model approach).

  3. #3
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: QItemDelegate Editor Crash

    Thanks for the reply.

    I want to process the entire (finished) string. Using a QValidator subclass forces handling each restricted character as it is typed -- too cumbersome for what I want to do.

    I am somewhat of a newbie with Qt and don't understand how to access the setData() method you reference while using a QTableWidget. Is there an example or reference you could point me to in Qt Assistant or the Qt 4 book I mentioned?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QItemDelegate Editor Crash

    Quote Originally Posted by mclark View Post
    I am somewhat of a newbie with Qt and don't understand how to access the setData() method you reference while using a QTableWidget. Is there an example or reference you could point me to in Qt Assistant or the Qt 4 book I mentioned?
    You see, there are different ways of manipulating the edited data depending on what exactly you want to achieve. Basically using the model approach gives you more control over what is happening with your data. If you want to stick with the convenience approach (using *Widget instead of *View), you need to implement your own item class and reimplement its setData() method. In that method you can change the data supplied by the user so that it is valid for your model (with the model approach you could also reject the change). Alternatively you can manipulate the data by reimplementing setModelData() method of the delegate to achieve a similar effect.

  5. #5
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: QItemDelegate Editor Crash

    wysota, thanks for helping me with this.

    Since I inherited the QTableWidget, release deadlines require me to continue its use, although from everything I've read I really need a QTableView. Since I'm already using a delegate to handle other table cell validation it would seem to make sense to explore the setModelData() route.

    Does something like this appear appropriate (provided I don't mess up the validation code)?

    Qt Code:
    1. void DMXTableCellDelegate::setModelData( QWidget* editor, QAbstractItemModel* model,
    2. const QModelIndex& index ) const
    3. {
    4. if ( index.column() == COL_Name )
    5. {
    6. QLineEdit* lineEdit = qobject_cast<QLineEdit*>( editor );
    7.  
    8. if ( lineEdit != NULL && !lineEdit->text().isEmpty() )
    9. {
    10. QString sValidStr = lineEdit->text();
    11.  
    12. // validate will return true if the string was modified
    13. if ( validate( sValidStr ) == true )
    14. {
    15. // update the model with the modified string
    16. model->setData( index, sValidStr );
    17. return;
    18. }
    19. }
    20. }
    21.  
    22. // validate did NOT modify the string
    23. QItemDelegate::setModelData( editor, model, index );
    24. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QItemDelegate Editor Crash

    In general this is ok, but I think that setModelData will only be called if the contents of the editor is modified (I'm not sure about it though). But, as I said, your approach is correct. Note that the only problem is, that you have to have a valid piece of data here. At worst you can just ignore setData just like you seem to do. Oh, and remember about using the appropriate role! In most cases (but not always!) it will be Qt::EditRole.

  7. The following user says thank you to wysota for this useful post:

    mclark (11th September 2007)

  8. #7
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QItemDelegate Editor Crash

    Thanks wysota, I'll give this a try.

  9. #8
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: QItemDelegate Editor Crash

    I subclassed QItemDelegate::setModelData() and I am now getting multiple calls into it when the QTableWidgetItem loses focus. The end result is a crash in a moc_** file when pressing 'Enter'.

    Mouse-clicking, Tab and Enter all cause a double entry into the setModelData() function. Only the Enter key causes a crash.

    I am baffled. Can anyone see something wrong with my implementation of setModelData()?

    Qt Code:
    1. int Table::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    2. {
    3. --->_id = QTableWidget::qt_metacall(_c, _id, _a);
    4. . . .
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void DMXTableCellDelegate::setModelData( QWidget* editor, QAbstractItemModel* model,
    2. const QModelIndex& index ) const
    3. {
    4. if ( index.column() == COL_Name )
    5. {
    6. QLineEdit* lineEdit = qobject_cast<QLineEdit*>( editor );
    7.  
    8. // Validate the Name string
    9. if ( (lineEdit != NULL) || !lineEdit->text().isEmpty() )
    10. {
    11. QString sTypedName = lineEdit->text();
    12.  
    13. // Substitute for illegal characters
    14. QString sNewName = "";
    15. bool bIsValid = true;
    16. QChar c;
    17.  
    18. for ( int i = 0; i < sTypedName.length(); i++ )
    19. {
    20. c = sTypedName.at( i );
    21.  
    22. if ( (c == '(') || (c == '<') )
    23. {
    24. c = '[';
    25. bIsValid = false;
    26. }
    27. else if ( (c == ')') || (c == '>') )
    28. {
    29. . . .
    30. }
    31.  
    32. sNewName.append( c );
    33. }
    34.  
    35. if ( !bIsValid )
    36. {
    37. QString sOrigName = index.data( Qt::EditRole ).toString();
    38.  
    39. int rVal = QMessageBox::warning( qobject_cast<QWidget*>( m_parent ),
    40. "Restricted Characters Found"),
    41. "Message String"),
    42. QMessageBox::Ok, QMessageBox::Cancel );
    43. if ( rVal == QMessageBox::Cancel )
    44. model->setData( index, QVariant( sOrigName ) );
    45. else
    46. model->setData( index, QVariant( sNewName ) );
    47. }
    48. }
    49.  
    50. return;
    51. }
    52.  
    53. QItemDelegate::setModelData( editor, model, index );
    54. }
    To copy to clipboard, switch view to plain text mode 

  10. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QItemDelegate Editor Crash

    Try not to fetch any data from the model.

  11. #10
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Post Re: QItemDelegate Editor Crash

    Originally Posted by wysota
    Try not to fetch any data from the model.
    Are you speaking of the QModelIndex object?

    I only use this string, index.data( Qt::EditRole ).toString(), to form the message for the warning. But, even if I don't use this string I get the same results!

  12. #11
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: QItemDelegate Editor Crash

    All the problems I'm having are related to the QWidget* parameter in the QMessageBox() call that I'm using to warn the user. If I comment out only the QMessageBox call I do not get another call to setModelData(), nor do I get a crash.

    These will cause the crash in setModelData():
    Qt Code:
    1. QMessageBox::warning( editor,
    2. "Message Title",
    3. "Message String",
    4. QMessageBox::Ok, QMessageBox::NoButton );
    5.  
    6. QMessageBox::warning( qobject_cast<QWidget*>( m_parent ),
    7. "Message Title",
    8. "Message String",
    9. QMessageBox::Ok, QMessageBox::NoButton );
    To copy to clipboard, switch view to plain text mode 

    Is the problem that I cannot call QMessageBox from within the setModelData() function?

    If this is NOT the problem, what QWidget* pointer should I be using when I call QMessageBox? The above examples use the QWidget* editor parameter and the delegate owners pointer. What else could I use here?

Similar Threads

  1. QItemDelegate and QCheckBox
    By KShots in forum Qt Programming
    Replies: 5
    Last Post: 19th November 2008, 00:49
  2. setModelData for subclassed QItemDelegate
    By T4ng10r in forum Qt Programming
    Replies: 7
    Last Post: 27th May 2007, 12:09
  3. Problems with QItemDelegate
    By Jimmy2775 in forum Qt Programming
    Replies: 10
    Last Post: 12th June 2006, 20:18
  4. Replies: 3
    Last Post: 12th May 2006, 19:31

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.