QGIS/src/app/qgsvariantdelegate.cpp
Nyall Dawson e0fa9eb9cf Add QStringLiteral(), QStringLiteral( "" ) and QLatin1String( "" )
to banned keywords

And replace use with QString()
2018-08-31 12:31:27 +10:00

378 lines
12 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QComboBox>
#include <QLineEdit>
#include <QDateTime>
#include "qgsvariantdelegate.h"
QgsVariantDelegate::QgsVariantDelegate( QObject *parent )
: QItemDelegate( parent )
{
mBoolExp.setPattern( QStringLiteral( "true|false" ) );
mBoolExp.setCaseSensitivity( Qt::CaseInsensitive );
mByteArrayExp.setPattern( QStringLiteral( "[\\x00-\\xff]*" ) );
mCharExp.setPattern( QStringLiteral( "." ) );
mColorExp.setPattern( QStringLiteral( "\\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\\)" ) );
mDoubleExp.setPattern( QString() );
mPointExp.setPattern( QStringLiteral( "\\((-?[0-9]*),(-?[0-9]*)\\)" ) );
mRectExp.setPattern( QStringLiteral( "\\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\\)" ) );
mSignedIntegerExp.setPattern( QStringLiteral( "-?[0-9]*" ) );
mSizeExp = mPointExp;
mUnsignedIntegerExp.setPattern( QStringLiteral( "[0-9]*" ) );
mDateExp.setPattern( QStringLiteral( "([0-9]{,4})-([0-9]{,2})-([0-9]{,2})" ) );
mTimeExp.setPattern( QStringLiteral( "([0-9]{,2}):([0-9]{,2}):([0-9]{,2})" ) );
mDateTimeExp.setPattern( mDateExp.pattern() + 'T' + mTimeExp.pattern() );
}
void QgsVariantDelegate::paint( QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const
{
if ( index.column() == 2 )
{
QVariant value = index.model()->data( index, Qt::UserRole );
if ( !isSupportedType( QgsVariantDelegate::type( value ) ) )
{
QStyleOptionViewItem myOption = option;
myOption.state &= ~QStyle::State_Enabled;
QItemDelegate::paint( painter, myOption, index );
return;
}
}
QItemDelegate::paint( painter, option, index );
}
QWidget *QgsVariantDelegate::createEditor( QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const
{
Q_UNUSED( option )
if ( index.column() != 2 )
return nullptr;
QVariant originalValue = index.model()->data( index, Qt::UserRole );
if ( !isSupportedType( QgsVariantDelegate::type( originalValue ) ) )
return nullptr;
QRegExp regExp;
switch ( QgsVariantDelegate::type( originalValue ) )
{
case QVariant::ByteArray:
regExp = mByteArrayExp;
break;
case QVariant::Char:
regExp = mCharExp;
break;
case QVariant::Color:
regExp = mColorExp;
break;
case QVariant::Date:
regExp = mDateExp;
break;
case QVariant::DateTime:
regExp = mDateTimeExp;
break;
case QVariant::Double:
regExp = mDoubleExp;
break;
case QVariant::Int:
case QVariant::LongLong:
regExp = mSignedIntegerExp;
break;
case QVariant::Point:
regExp = mPointExp;
break;
case QVariant::Rect:
regExp = mRectExp;
break;
case QVariant::Size:
regExp = mSizeExp;
break;
case QVariant::Time:
regExp = mTimeExp;
break;
case QVariant::UInt:
case QVariant::ULongLong:
regExp = mUnsignedIntegerExp;
break;
default:
;
}
if ( QgsVariantDelegate::type( originalValue ) == QVariant::Bool )
{
QComboBox *comboBox = new QComboBox( parent );
comboBox->addItem( QStringLiteral( "false" ) );
comboBox->addItem( QStringLiteral( "true" ) );
return comboBox;
}
else
{
QLineEdit *lineEdit = new QLineEdit( parent );
lineEdit->setFrame( false );
if ( !regExp.isEmpty() )
{
QValidator *validator = new QRegExpValidator( regExp, lineEdit );
lineEdit->setValidator( validator );
}
return lineEdit;
}
}
void QgsVariantDelegate::setEditorData( QWidget *editor,
const QModelIndex &index ) const
{
QVariant value = index.model()->data( index, Qt::UserRole );
if ( QComboBox *comboBox = qobject_cast<QComboBox * >( editor ) )
{
comboBox->setCurrentIndex( value.toBool() ? 1 : 0 );
}
else if ( QLineEdit *lineEdit = qobject_cast<QLineEdit * >( editor ) )
{
lineEdit->setText( displayText( value ) );
}
}
void QgsVariantDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index ) const
{
QVariant originalValue = index.model()->data( index, Qt::UserRole );
QVariant value;
if ( QComboBox *comboBox = qobject_cast<QComboBox * >( editor ) )
{
value = comboBox->currentIndex() == 1;
}
else if ( QLineEdit *lineEdit = qobject_cast<QLineEdit * >( editor ) )
{
if ( !lineEdit->isModified() )
return;
QString text = lineEdit->text();
const QValidator *validator = lineEdit->validator();
if ( validator )
{
int pos;
if ( validator->validate( text, pos ) != QValidator::Acceptable )
return;
}
switch ( QgsVariantDelegate::type( originalValue ) )
{
case QVariant::Char:
value = text.at( 0 );
break;
case QVariant::Color:
( void )mColorExp.exactMatch( text );
value = QColor( std::min( mColorExp.cap( 1 ).toInt(), 255 ),
std::min( mColorExp.cap( 2 ).toInt(), 255 ),
std::min( mColorExp.cap( 3 ).toInt(), 255 ),
std::min( mColorExp.cap( 4 ).toInt(), 255 ) );
break;
case QVariant::Date:
{
QDate date = QDate::fromString( text, Qt::ISODate );
if ( !date.isValid() )
return;
value = date;
}
break;
case QVariant::DateTime:
{
QDateTime dateTime = QDateTime::fromString( text, Qt::ISODate );
if ( !dateTime.isValid() )
return;
value = dateTime;
}
break;
case QVariant::Point:
( void )mPointExp.exactMatch( text );
value = QPoint( mPointExp.cap( 1 ).toInt(), mPointExp.cap( 2 ).toInt() );
break;
case QVariant::Rect:
( void )mRectExp.exactMatch( text );
value = QRect( mRectExp.cap( 1 ).toInt(), mRectExp.cap( 2 ).toInt(),
mRectExp.cap( 3 ).toInt(), mRectExp.cap( 4 ).toInt() );
break;
case QVariant::Size:
( void )mSizeExp.exactMatch( text );
value = QSize( mSizeExp.cap( 1 ).toInt(), mSizeExp.cap( 2 ).toInt() );
break;
case QVariant::StringList:
value = text.split( ',' );
break;
case QVariant::Time:
{
QTime time = QTime::fromString( text, Qt::ISODate );
if ( !time.isValid() )
return;
value = time;
}
break;
default:
value = text;
value.convert( QgsVariantDelegate::type( originalValue ) );
}
}
model->setData( index, displayText( value ), Qt::DisplayRole );
model->setData( index, value, Qt::UserRole );
}
bool QgsVariantDelegate::isSupportedType( QVariant::Type type )
{
switch ( type )
{
case QVariant::Bool:
case QVariant::ByteArray:
case QVariant::Char:
case QVariant::Color:
case QVariant::Date:
case QVariant::DateTime:
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
case QVariant::Point:
case QVariant::Rect:
case QVariant::Size:
case QVariant::String:
case QVariant::StringList:
case QVariant::Time:
case QVariant::UInt:
case QVariant::ULongLong:
return true;
default:
return false;
}
}
QString QgsVariantDelegate::displayText( const QVariant &value )
{
switch ( QgsVariantDelegate::type( value ) )
{
case QVariant::Bool:
case QVariant::ByteArray:
case QVariant::Char:
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
case QVariant::String:
case QVariant::UInt:
case QVariant::ULongLong:
return value.toString();
case QVariant::Color:
{
QColor color = qvariant_cast<QColor>( value );
return QStringLiteral( "(%1,%2,%3,%4)" )
.arg( color.red() ).arg( color.green() )
.arg( color.blue() ).arg( color.alpha() );
}
case QVariant::Date:
return value.toDate().toString( Qt::ISODate );
case QVariant::DateTime:
return value.toDateTime().toString( Qt::ISODate );
case QVariant::Invalid:
return QStringLiteral( "<Invalid>" );
case QVariant::Point:
{
QPoint point = value.toPoint();
return QStringLiteral( "(%1,%2)" ).arg( point.x() ).arg( point.y() );
}
case QVariant::Rect:
{
QRect rect = value.toRect();
return QStringLiteral( "(%1,%2,%3,%4)" )
.arg( rect.x() ).arg( rect.y() )
.arg( rect.width() ).arg( rect.height() );
}
case QVariant::Size:
{
QSize size = value.toSize();
return QStringLiteral( "(%1,%2)" ).arg( size.width() ).arg( size.height() );
}
case QVariant::StringList:
return value.toStringList().join( QStringLiteral( "," ) );
case QVariant::Time:
return value.toTime().toString( Qt::ISODate );
default:
break;
}
return QStringLiteral( "<%1>" ).arg( value.toString() );
}
/* hack to get "real" type of a variant, because QVariant::type() almost always returns QString */
QVariant::Type QgsVariantDelegate::type( const QVariant &value )
{
if ( value.type() == QVariant::String )
{
QString str = value.toString();
QRegExp regExp;
bool ok;
// is this a bool (true,false)
regExp.setPattern( QStringLiteral( "true|false" ) );
regExp.setCaseSensitivity( Qt::CaseInsensitive );
if ( regExp.indexIn( str ) != -1 )
return QVariant::Bool;
// is this an int?
// perhaps we should treat as double for more flexibility
str.toInt( &ok );
if ( ok )
return QVariant::Int;
// is this a double?
str.toDouble( &ok );
if ( ok )
return QVariant::Double;
}
// fallback to QVariant::type()
return value.type();
}