Skip to content

Commit

Permalink
Enum class for ColumnDataIndex + constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso authored and nyalldawson committed Apr 3, 2020
1 parent 1ef0c65 commit 5d720fb
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 36 deletions.
11 changes: 11 additions & 0 deletions python/gui/auto_additions/qgsfieldmappingmodel.py
@@ -0,0 +1,11 @@
# The following has been generated automatically from src/gui/qgsfieldmappingmodel.h
# monkey patching scoped based enum
QgsFieldMappingModel.ColumnDataIndex.SourceExpression.__doc__ = "Expression"
QgsFieldMappingModel.ColumnDataIndex.DestinationName.__doc__ = "Destination field name"
QgsFieldMappingModel.ColumnDataIndex.DestinationType.__doc__ = "Destination field QVariant::Type casted to (int)"
QgsFieldMappingModel.ColumnDataIndex.DestinationLength.__doc__ = "Destination field length"
QgsFieldMappingModel.ColumnDataIndex.DestinationPrecision.__doc__ = "Destination field precision"
QgsFieldMappingModel.ColumnDataIndex.DestinationConstraints.__doc__ = "Destination field constraints"
QgsFieldMappingModel.ColumnDataIndex.__doc__ = 'The ColumnDataIndex enum represents the column index for the view\n\n' + '* ``SourceExpression``: ' + QgsFieldMappingModel.ColumnDataIndex.SourceExpression.__doc__ + '\n' + '* ``DestinationName``: ' + QgsFieldMappingModel.ColumnDataIndex.DestinationName.__doc__ + '\n' + '* ``DestinationType``: ' + QgsFieldMappingModel.ColumnDataIndex.DestinationType.__doc__ + '\n' + '* ``DestinationLength``: ' + QgsFieldMappingModel.ColumnDataIndex.DestinationLength.__doc__ + '\n' + '* ``DestinationPrecision``: ' + QgsFieldMappingModel.ColumnDataIndex.DestinationPrecision.__doc__ + '\n' + '* ``DestinationConstraints``: ' + QgsFieldMappingModel.ColumnDataIndex.DestinationConstraints.__doc__
# --
QgsFieldMappingModel.ColumnDataIndex.baseClass = QgsFieldMappingModel
6 changes: 4 additions & 2 deletions python/gui/auto_generated/qgsfieldmappingmodel.sip.in
Expand Up @@ -26,15 +26,17 @@ the mapping expression is editable.
%End
public:

enum ColumnDataIndex
enum class ColumnDataIndex
{
SourceExpression,
DestinationName,
DestinationType,
DestinationLength,
DestinationPrecision
DestinationPrecision,
DestinationConstraints,
};


struct Field
{
QString originalName;
Expand Down
86 changes: 69 additions & 17 deletions src/gui/qgsfieldmappingmodel.cpp
Expand Up @@ -37,23 +37,23 @@ QVariant QgsFieldMappingModel::headerData( int section, Qt::Orientation orientat
{
switch ( section )
{
case ColumnDataIndex::SourceExpression:
case static_cast<int>( ColumnDataIndex::SourceExpression ):
{
return tr( "Source expression" );
}
case ColumnDataIndex::DestinationName:
case static_cast<int>( ColumnDataIndex::DestinationName ):
{
return tr( "Name" );
}
case ColumnDataIndex::DestinationType:
case static_cast<int>( ColumnDataIndex::DestinationType ):
{
return tr( "Type" );
}
case ColumnDataIndex::DestinationLength:
case static_cast<int>( ColumnDataIndex::DestinationLength ):
{
return tr( "Length" );
}
case ColumnDataIndex::DestinationPrecision:
case static_cast<int>( ColumnDataIndex::DestinationPrecision ):
{
return tr( "Precision" );
}
Expand Down Expand Up @@ -81,7 +81,7 @@ int QgsFieldMappingModel::rowCount( const QModelIndex &parent ) const
int QgsFieldMappingModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );
return 5;
return 6;
}

QVariant QgsFieldMappingModel::data( const QModelIndex &index, int role ) const
Expand All @@ -91,34 +91,64 @@ QVariant QgsFieldMappingModel::data( const QModelIndex &index, int role ) const
const int col { index.column() };
const Field &f { mMapping.at( index.row() ) };

const QgsFieldConstraints::Constraints constraints { fieldConstraints( f.field ) };

if ( role == Qt::DisplayRole || role == Qt::EditRole )
{
switch ( col )
{
{
case ColumnDataIndex::SourceExpression:
case static_cast<int>( ColumnDataIndex::SourceExpression ):
{
return f.expression.expression();
}
case ColumnDataIndex::DestinationName:
case static_cast<int>( ColumnDataIndex::DestinationName ):
{
return f.field.displayName();
}
case ColumnDataIndex::DestinationType:
case static_cast<int>( ColumnDataIndex::DestinationType ):
{
return static_cast<int>( f.field.type() );
}
case ColumnDataIndex::DestinationLength:
case static_cast<int>( ColumnDataIndex::DestinationLength ):
{
return f.field.length();
}
case ColumnDataIndex::DestinationPrecision:
case static_cast<int>( ColumnDataIndex::DestinationPrecision ):
{
return f.field.precision();
}
case static_cast<int>( ColumnDataIndex::DestinationConstraints ):
{
return constraints != 0 ? tr( "Constraints active" ) : QString();
}
}
}
}
else if ( role == Qt::ToolTipRole &&
col == static_cast<int>( ColumnDataIndex::DestinationConstraints ) &&
constraints != 0 )
{
QStringList constraintDescription;
if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintUnique ) )
{
constraintDescription.push_back( tr( "Unique" ) );
}
if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull ) )
{
constraintDescription.push_back( tr( "Not null" ) );
}
if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull ) )
{
constraintDescription.push_back( tr( "Expression" ) );
}
return constraintDescription.join( QStringLiteral( "<br>" ) );
}
else if ( role == Qt::BackgroundRole &&
constraints != 0 )
{
return QBrush( QColor( 255, 224, 178 ) );
}
}
return QVariant();
}
Expand Down Expand Up @@ -148,7 +178,8 @@ QgsExpressionContext QgsFieldMappingModel::ExpressionContextGenerator::createExp
Qt::ItemFlags QgsFieldMappingModel::flags( const QModelIndex &index ) const
{
if ( index.isValid() &&
( index.column() == ColumnDataIndex::SourceExpression || destinationEditable() ) )
index.column() != static_cast<int>( ColumnDataIndex::DestinationConstraints ) &&
( index.column() == static_cast<int>( ColumnDataIndex::SourceExpression ) || destinationEditable() ) )
{
return Qt::ItemFlags( Qt::ItemIsSelectable |
Qt::ItemIsEditable |
Expand All @@ -166,31 +197,31 @@ bool QgsFieldMappingModel::setData( const QModelIndex &index, const QVariant &va
Field &f = mMapping[index.row()];
switch ( index.column() )
{
case ColumnDataIndex::SourceExpression:
case static_cast<int>( ColumnDataIndex::SourceExpression ):
{
const QgsExpression exp { value.toString() };
f.expression = exp;
break;
}
case ColumnDataIndex::DestinationName:
case static_cast<int>( ColumnDataIndex::DestinationName ):
{
f.field.setName( value.toString() );
break;
}
case ColumnDataIndex::DestinationType:
case static_cast<int>( ColumnDataIndex::DestinationType ):
{
f.field.setType( static_cast<QVariant::Type>( value.toInt( ) ) );
break;
}
case ColumnDataIndex::DestinationLength:
case static_cast<int>( ColumnDataIndex::DestinationLength ):
{
bool ok;
const int length { value.toInt( &ok ) };
if ( ok )
f.field.setLength( length );
break;
}
case ColumnDataIndex::DestinationPrecision:
case static_cast<int>( ColumnDataIndex::DestinationPrecision ):
{
bool ok;
const int precision { value.toInt( &ok ) };
Expand All @@ -205,6 +236,27 @@ bool QgsFieldMappingModel::setData( const QModelIndex &index, const QVariant &va
return true;
}

QgsFieldConstraints::Constraints QgsFieldMappingModel::fieldConstraints( const QgsField &field ) const
{
QgsFieldConstraints::Constraints constraints;

const QgsFieldConstraints fieldConstraints { field.constraints() };

if ( fieldConstraints.constraints() & QgsFieldConstraints::ConstraintNotNull &&
fieldConstraints.constraintStrength( QgsFieldConstraints::ConstraintNotNull ) & QgsFieldConstraints::ConstraintStrengthHard )
constraints.setFlag( QgsFieldConstraints::ConstraintNotNull );

if ( fieldConstraints.constraints() & QgsFieldConstraints::ConstraintUnique &&
fieldConstraints.constraintStrength( QgsFieldConstraints::ConstraintUnique ) & QgsFieldConstraints::ConstraintStrengthHard )
constraints.setFlag( QgsFieldConstraints::ConstraintUnique );

if ( fieldConstraints.constraints() & QgsFieldConstraints::ConstraintExpression &&
fieldConstraints.constraintStrength( QgsFieldConstraints::ConstraintExpression ) & QgsFieldConstraints::ConstraintStrengthHard )
constraints.setFlag( QgsFieldConstraints::ConstraintExpression );

return constraints;
}

bool QgsFieldMappingModel::moveUpOrDown( const QModelIndex &index, bool up )
{
if ( ! index.isValid() && index.model() == this )
Expand Down
18 changes: 12 additions & 6 deletions src/gui/qgsfieldmappingmodel.h
Expand Up @@ -22,6 +22,7 @@
#include "qgsfields.h"
#include "qgsexpression.h"
#include "qgsexpressioncontextgenerator.h"
#include "qgsfieldconstraints.h"
#include "qgis_gui.h"


Expand All @@ -45,15 +46,18 @@ class GUI_EXPORT QgsFieldMappingModel: public QAbstractTableModel
/**
* The ColumnDataIndex enum represents the column index for the view
*/
enum ColumnDataIndex
enum class ColumnDataIndex : int
{
SourceExpression, //!< Expression
DestinationName, //!< Destination field name
DestinationType, //!< Destination field QVariant::Type casted to (int)
DestinationLength, //!< Destination field length
DestinationPrecision //!< Destination field precision
SourceExpression, //!< Expression
DestinationName, //!< Destination field name
DestinationType, //!< Destination field QVariant::Type casted to (int)
DestinationLength, //!< Destination field length
DestinationPrecision, //!< Destination field precision
DestinationConstraints, //!< Destination field constraints
};

Q_ENUM( ColumnDataIndex );

/**
* The Field struct holds information about a mapped field
*/
Expand Down Expand Up @@ -146,6 +150,8 @@ class GUI_EXPORT QgsFieldMappingModel: public QAbstractTableModel

};

QgsFieldConstraints::Constraints fieldConstraints( const QgsField &field ) const;

bool moveUpOrDown( const QModelIndex &index, bool up = true );

QList<Field> mMapping;
Expand Down
8 changes: 4 additions & 4 deletions src/gui/qgsfieldmappingwidget.cpp
Expand Up @@ -28,8 +28,8 @@ QgsFieldMappingWidget::QgsFieldMappingWidget( const QgsFields &sourceFields,

mModel = new QgsFieldMappingModel( sourceFields, destinationFields, expressions, this );
mTableView->setModel( mModel );
mTableView->setItemDelegateForColumn( QgsFieldMappingModel::ColumnDataIndex::SourceExpression, new ExpressionDelegate( mTableView ) );
mTableView->setItemDelegateForColumn( QgsFieldMappingModel::ColumnDataIndex::DestinationType, new TypeDelegate( mTableView ) );
mTableView->setItemDelegateForColumn( static_cast<int>( QgsFieldMappingModel::ColumnDataIndex::SourceExpression ), new ExpressionDelegate( mTableView ) );
mTableView->setItemDelegateForColumn( static_cast<int>( QgsFieldMappingModel::ColumnDataIndex::DestinationType ), new TypeDelegate( mTableView ) );
updateColumns();
}

Expand Down Expand Up @@ -137,9 +137,9 @@ void QgsFieldMappingWidget::updateColumns()
{
for ( int i = 0; i < mModel->rowCount(); ++i )
{
mTableView->openPersistentEditor( mModel->index( i, QgsFieldMappingModel::ColumnDataIndex::SourceExpression ) );
mTableView->openPersistentEditor( mModel->index( i, static_cast<int>( QgsFieldMappingModel::ColumnDataIndex::SourceExpression ) ) );
if ( destinationEditable() )
mTableView->openPersistentEditor( mModel->index( i, QgsFieldMappingModel::ColumnDataIndex::DestinationType ) );
mTableView->openPersistentEditor( mModel->index( i, static_cast<int>( QgsFieldMappingModel::ColumnDataIndex::DestinationType ) ) );
}

for ( int i = 0; i < mModel->columnCount(); ++i )
Expand Down
24 changes: 17 additions & 7 deletions tests/src/python/test_qgsfieldmappingwidget.py
Expand Up @@ -16,6 +16,7 @@
from qgis.core import (
QgsFields,
QgsField,
QgsFieldConstraints,
)
from qgis.gui import (
QgsFieldMappingWidget,
Expand All @@ -28,7 +29,9 @@
QModelIndex,
QItemSelectionModel,
)

from qgis.PyQt.QtGui import (
QColor
)
from qgis.testing import start_app, unittest


Expand Down Expand Up @@ -201,12 +204,19 @@ def _compare(widget, expected):
self.assertEqual(mapping[1].originalName, 'destination_field2')
self.assertEqual(mapping[2].originalName, 'destination_field3')

def __testWidget(self):
"""Test the mapping widget"""

widget = QgsFieldMappingWidget(self.source_fields, self.destination_fields)
widget.setDestinationEditable(True)
self._showDialog(widget)
# Test constraints
f = QgsField('constraint_field')
constraints = QgsFieldConstraints()
constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull, QgsFieldConstraints.ConstraintOriginProvider)
constraints.setConstraint(QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintOriginProvider)
constraints.setConstraint(QgsFieldConstraints.ConstraintUnique, QgsFieldConstraints.ConstraintOriginProvider)
f.setConstraints(constraints)
fields = QgsFields()
fields.append(f)
widget.setDestinationFields(fields)
self.assertEqual(widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.DisplayRole), "Constraints active")
self.assertEqual(widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.ToolTipRole), "Unique<br>Not null<br>Expression")
self.assertEqual(widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.BackgroundColorRole), QColor(255, 224, 178))


if __name__ == '__main__':
Expand Down

0 comments on commit 5d720fb

Please sign in to comment.