Skip to content
Permalink
Browse files

Merge pull request #35035 from m-kuhn/value_relation_description

Add description to value relation widget
  • Loading branch information
m-kuhn committed Mar 17, 2020
2 parents 54ff937 + 3b941e4 commit 2770e2c327ef6098d7440b162e3ecc554d432d4e
@@ -25,7 +25,7 @@ features on another layer.
public:
struct ValueRelationItem
{
ValueRelationItem( const QVariant &key, const QString &value );
ValueRelationItem( const QVariant &key, const QString &value, const QString &description );
%Docstring
Constructor for ValueRelationItem
%End
@@ -37,6 +37,7 @@ Constructor for ValueRelationItem

QVariant key;
QString value;
QString description;
};

typedef QVector < QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache;
@@ -16,7 +16,7 @@ class QgsFieldExpressionWidget : QWidget
{
%Docstring
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions
It contains a combo boxto display the fields and expression and a button to open the expression dialog.
It contains a combo box to display the fields and expression and a button to open the expression dialog.
The combo box is editable, allowing expressions to be edited inline.
The validity of the expression is checked live on key press, invalid expressions are displayed in red.
The expression will be added to the model (and the fieldChanged signals emitted)
@@ -140,33 +140,46 @@ QgsValueRelationFieldFormatter::ValueRelationCache QgsValueRelationFieldFormatte
QgsFeatureRequest request;

request.setFlags( QgsFeatureRequest::NoGeometry );
request.setSubsetOfAttributes( QgsAttributeList() << ki << vi );
QgsAttributeIds subsetOfAttributes { ki, vi };

const QString expression = config.value( QStringLiteral( "FilterExpression" ) ).toString();
const QString descriptionExpressionString = config.value( "Description" ).toString();
QgsExpression descriptionExpression( descriptionExpressionString );
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
descriptionExpression.prepare( &context );
subsetOfAttributes += descriptionExpression.referencedAttributeIndexes( layer->fields() );
request.setSubsetOfAttributes( subsetOfAttributes.toList() );

const QString filterExpression = config.value( QStringLiteral( "FilterExpression" ) ).toString();

// Skip the filter and build a full cache if the form scope is required and the feature
// is not valid or the attributes required for the filter have no valid value
// Note: parent form scope is not checked for usability because it's supposed to
// be used into a coalesce that retrieve the current value of the parent
// from the parent layer when used outside of an embedded form
if ( ! expression.isEmpty() && ( !( expressionRequiresFormScope( expression ) )
|| expressionIsUsable( expression, formFeature ) ) )
if ( ! filterExpression.isEmpty() && ( !( expressionRequiresFormScope( filterExpression ) )
|| expressionIsUsable( filterExpression, formFeature ) ) )
{
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
if ( formFeature.isValid( ) && QgsValueRelationFieldFormatter::expressionRequiresFormScope( expression ) )
context.appendScope( QgsExpressionContextUtils::formScope( formFeature ) );
if ( parentFormFeature.isValid() && QgsValueRelationFieldFormatter::expressionRequiresParentFormScope( expression ) )
context.appendScope( QgsExpressionContextUtils::parentFormScope( parentFormFeature ) );
request.setExpressionContext( context );
request.setFilterExpression( expression );
QgsExpressionContext filterContext = context;
if ( formFeature.isValid( ) && QgsValueRelationFieldFormatter::expressionRequiresFormScope( filterExpression ) )
filterContext.appendScope( QgsExpressionContextUtils::formScope( formFeature ) );
if ( parentFormFeature.isValid() && QgsValueRelationFieldFormatter::expressionRequiresParentFormScope( filterExpression ) )
filterContext.appendScope( QgsExpressionContextUtils::parentFormScope( parentFormFeature ) );
request.setExpressionContext( filterContext );
request.setFilterExpression( filterExpression );
}

QgsFeatureIterator fit = layer->getFeatures( request );

QgsFeature f;
while ( fit.nextFeature( f ) )
{
cache.append( ValueRelationItem( f.attribute( ki ), f.attribute( vi ).toString() ) );
QString description;
if ( descriptionExpression.isValid() )
{
context.setFeature( f );
description = descriptionExpression.evaluate( &context ).toString();
}
cache.append( ValueRelationItem( f.attribute( ki ), f.attribute( vi ).toString(), description ) );
}

if ( config.value( QStringLiteral( "OrderByValue" ) ).toBool() )
@@ -39,16 +39,18 @@ class CORE_EXPORT QgsValueRelationFieldFormatter : public QgsFieldFormatter
struct ValueRelationItem
{
//! Constructor for ValueRelationItem
ValueRelationItem( const QVariant &key, const QString &value )
ValueRelationItem( const QVariant &key, const QString &value, const QString &description = QString() )
: key( key )
, value( value )
, description( description )
{}

//! Constructor for ValueRelationItem
ValueRelationItem() = default;

QVariant key;
QString value;
QString description;
};

typedef QVector < QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache;
@@ -27,8 +27,10 @@ QgsValueRelationConfigDlg::QgsValueRelationConfigDlg( QgsVectorLayer *vl, int fi
mLayerName->setFilters( QgsMapLayerProxyModel::VectorLayer );
mKeyColumn->setLayer( mLayerName->currentLayer() );
mValueColumn->setLayer( mLayerName->currentLayer() );
mDescriptionExpression->setLayer( mLayerName->currentLayer() );
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mKeyColumn, &QgsFieldComboBox::setLayer );
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mValueColumn, &QgsFieldComboBox::setLayer );
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mDescriptionExpression, &QgsFieldExpressionWidget::setLayer );
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, this, &QgsValueRelationConfigDlg::layerChanged );
connect( mEditExpression, &QAbstractButton::clicked, this, &QgsValueRelationConfigDlg::editExpression );

@@ -39,6 +41,7 @@ QgsValueRelationConfigDlg::QgsValueRelationConfigDlg( QgsVectorLayer *vl, int fi
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, this, &QgsEditorConfigWidget::changed );
connect( mKeyColumn, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
connect( mValueColumn, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
connect( mDescriptionExpression, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsEditorConfigWidget::changed );
connect( mAllowMulti, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
connect( mAllowNull, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
connect( mOrderByValue, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
@@ -68,6 +71,7 @@ QVariantMap QgsValueRelationConfigDlg::config()
QString() );
cfg.insert( QStringLiteral( "Key" ), mKeyColumn->currentField() );
cfg.insert( QStringLiteral( "Value" ), mValueColumn->currentField() );
cfg.insert( QStringLiteral( "Description" ), mDescriptionExpression->expression() );
cfg.insert( QStringLiteral( "AllowMulti" ), mAllowMulti->isChecked() );
cfg.insert( QStringLiteral( "NofColumns" ), mNofColumns->value() );
cfg.insert( QStringLiteral( "AllowNull" ), mAllowNull->isChecked() );
@@ -84,6 +88,7 @@ void QgsValueRelationConfigDlg::setConfig( const QVariantMap &config )
mLayerName->setLayer( lyr );
mKeyColumn->setField( config.value( QStringLiteral( "Key" ) ).toString() );
mValueColumn->setField( config.value( QStringLiteral( "Value" ) ).toString() );
mDescriptionExpression->setField( config.value( QStringLiteral( "Description" ) ).toString() );
mAllowMulti->setChecked( config.value( QStringLiteral( "AllowMulti" ) ).toBool() );
mNofColumns->setValue( config.value( QStringLiteral( "NofColumns" ), 1 ).toInt() );
if ( !mAllowMulti->isChecked() )
@@ -342,16 +342,16 @@ void QgsValueRelationWidgetWrapper::populate( )
{
if ( context().parentFormFeature().isValid() )
{
mCache = QgsValueRelationFieldFormatter::createCache( config( ), formFeature(), context().parentFormFeature() );
mCache = QgsValueRelationFieldFormatter::createCache( config(), formFeature(), context().parentFormFeature() );
}
else
{
mCache = QgsValueRelationFieldFormatter::createCache( config( ), formFeature() );
mCache = QgsValueRelationFieldFormatter::createCache( config(), formFeature() );
}
}
else if ( mCache.empty() )
{
mCache = QgsValueRelationFieldFormatter::createCache( config( ) );
mCache = QgsValueRelationFieldFormatter::createCache( config() );
}

if ( mComboBox )
@@ -365,6 +365,8 @@ void QgsValueRelationWidgetWrapper::populate( )
for ( const QgsValueRelationFieldFormatter::ValueRelationItem &element : qgis::as_const( mCache ) )
{
whileBlocking( mComboBox )->addItem( element.value, element.key );
if ( !element.description.isEmpty() )
mComboBox->setItemData( mComboBox->count() - 1, element.description, Qt::ToolTipRole );
}

}
@@ -37,7 +37,7 @@ class QgsExpressionContextGenerator;
/**
* \ingroup gui
* \brief The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions
* It contains a combo boxto display the fields and expression and a button to open the expression dialog.
* It contains a combo box to display the fields and expression and a button to open the expression dialog.
* The combo box is editable, allowing expressions to be edited inline.
* The validity of the expression is checked live on key press, invalid expressions are displayed in red.
* The expression will be added to the model (and the fieldChanged signals emitted)
@@ -7,14 +7,14 @@
<x>0</x>
<y>0</y>
<width>427</width>
<height>474</height>
<height>489</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0">
<item row="12" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
<item row="13" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_19">
@@ -32,7 +32,7 @@
<enum>Qt::RightToLeft</enum>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mIconExpression.svg</normaloff>:/images/themes/default/mIconExpression.svg</iconset>
</property>
</widget>
@@ -52,6 +52,23 @@
</item>
</layout>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_nofColumns">
<property name="text">
<string>Number of columns</string>
</property>
</widget>
</item>
<item row="14" column="0" colspan="2">
<widget class="QTextEdit" name="mFilterExpression"/>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Select layer, key column and value column</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
@@ -62,33 +79,40 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_8">
<item row="3" column="1">
<widget class="QgsFieldComboBox" name="mValueColumn"/>
</item>
<item row="1" column="1">
<widget class="QgsMapLayerComboBox" name="mLayerName"/>
</item>
<item row="8" column="0" colspan="2">
<widget class="QCheckBox" name="mAllowMulti">
<property name="text">
<string>Select layer, key column and value column</string>
<string>Allow multiple selections</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="mAllowNull">
<property name="text">
<string>Allow NULL value</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsFieldComboBox" name="mKeyColumn"/>
</item>
<item row="3" column="1">
<widget class="QgsFieldComboBox" name="mValueColumn"/>
</item>
<item row="10" column="0" colspan="2">
<item row="11" column="0" colspan="2">
<widget class="QCheckBox" name="mUseCompleter">
<property name="text">
<string>Use completer</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="mOrderByValue">
<property name="text">
<string>Order by value</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
@@ -99,6 +123,12 @@
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="mNofColumns"/>
</item>
<item row="2" column="1">
<widget class="QgsFieldComboBox" name="mKeyColumn"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
@@ -109,35 +139,15 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="mOrderByValue">
<property name="text">
<string>Order by value</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsMapLayerComboBox" name="mLayerName"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_nofColumns">
<property name="text">
<string>Number of columns</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<widget class="QTextEdit" name="mFilterExpression"/>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="mAllowMulti">
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Allow multiple selections</string>
<string>Description column</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="mNofColumns"/>
<item row="4" column="1">
<widget class="QgsFieldExpressionWidget" name="mDescriptionExpression" native="true"/>
</item>
</layout>
</widget>
@@ -152,6 +162,12 @@
<extends>QComboBox</extends>
<header>qgsmaplayercombobox.h</header>
</customwidget>
<customwidget>
<class>QgsFieldExpressionWidget</class>
<extends>QWidget</extends>
<header>qgsfieldexpressionwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mLayerName</tabstop>
@@ -164,8 +180,6 @@
<tabstop>mEditExpression</tabstop>
<tabstop>mFilterExpression</tabstop>
</tabstops>
<resources>
<include location="../../../images/images.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

0 comments on commit 2770e2c

Please sign in to comment.
You can’t perform that action at this time.