PDA

View Full Version : QLineEdit actions in Delegate



mclark
15th January 2009, 20:36
Using Qt 4.4.2, I have a QTableWidget where one of the columns contains a string representation of a UUID (2C44E5CE-C463-3CE4-B4D6-785C0F93124A). I use delegates to handle all the in-cell editing in my table (QLineEdit & QComboBoxes) which works fine.

I am required to support editing the UUID and need to validate the entry. My problem is that when the QLineEdit object is created the entire UUID is selected and the cursor is at the end of the string. If I explicitly select the first character I can change it but then the cursor moves to the end of the string. Having the cursor continually moving to the end is not acceptable behavior when editing a 32-character value. I can paste an existing UUID into the QLineEdit object just fine, the problem is editing character-by-character.

The default string is either a valid UUID or a 'NULL' UUID (00000000-0000-0000-0000-000400000000). I want to be able to start typing at the leftmost character of the string and continue typing without having to reselect the character I want to replace.

I must be doing something wrong or just forgetting to do something to accomplish this. Does anyone have any suggestions?


QWidget* UUIDColumnDelegate::createEditor( QWidget* parent,
const QStyleOptionViewItem& option,
const QModelIndex& index ) const
{
QLineEdit* lineEdit = new QLineEdit( parent );
if ( lineEdit == NULL )
{
// report error
return QItemDelegate::createEditor( parent, option, index );
}

QString sRegExp( "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$" );
QRegExp regExp( sRegExp, Qt::CaseInsensitive, QRegExp::RegExp );
QRegExpValidator* uuidValidator = new QRegExpValidator( regExp, lineEdit );
if ( uuidValidator == NULL )
{
// report error
return QItemDelegate::createEditor( parent, option, index );
}

lineEdit->setInputMask( "HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH" );
lineEdit->setMaxLength( 36 );
lineEdit->setCursorPosition( 0 ); // appears to have no effect
lineEdit->setSelection( 0, 1 ); // appears to have no effect
lineEdit->setValidator( uuidValidator );

connect( lineEdit, SIGNAL( textEdited( const QString& ) ),
this, SLOT( uuidTextEdited( const QString& ) ) );
connect( lineEdit, SIGNAL( editingFinished() ),
this, SLOT( commitAndCloseEditor() ) );

lineEdit->installEventFilter( const_cast<UUIDColumnDelegate*>( this ) );
return lineEdit;
}

void AbstractColumnDelegate::uuidTextEdited( const QString& sValue )
{
if ( sValue.isEmpty() )
return;
QString sText = sValue.toUpper();
qobject_cast<QLineEdit*>( sender() )->setText( sText );
}

mclark
15th January 2009, 22:34
In case anyone runs into this problem: I now have the QLineEdit object acting mostly civilized. It's not perfect but acceptable.

I removed the following code from the createEditor() method:


lineEdit->setCursorPosition( 0 ); // appears to have no effect
lineEdit->setSelection( 0, 1 ); // appears to have no effect

I added a slot for the cursorPositionChanged() connection that does:

void AbstractColumnDelegate::uuidCursorChanged( int nOldPos, int nNewPos )
{
if ( nNewPos == 36 ) // 36 is the string max
{
QLineEdit* pEditor = qobject_cast<QLineEdit*>( sender() );

// Allow for full selection from either direction using mouse
// or Ctrl+Shift Arrow keys
if ( pEditor->selectionStart() == 0 )
return;

int nPos = nOldPos + 1;

// Left to right editing: skip over the '-' characters
if ( (nPos == 8) || (nPos == 13) || (nPos == 18) || (nPos == 23) )
nPos++;

pEditor->setCursorPosition( nPos );
}
}

This allows the cursor to move 1 character at a time right or left, skip over the '-' characters and allows the entire string to be selected from either the right or left using a mouse drag or the Ctrl+Shift+Arrow keys.