Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add description to value relation widget
Add the possibility to add a description to each value in a value relation widget.
  • Loading branch information
m-kuhn committed Mar 12, 2020
1 parent 4c49625 commit 94fc1ba
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 62 deletions.
Expand Up @@ -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
Expand All @@ -37,6 +37,7 @@ Constructor for ValueRelationItem

QVariant key;
QString value;
QString description;
};

typedef QVector < QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache;
Expand Down
2 changes: 1 addition & 1 deletion python/gui/auto_generated/qgsfieldexpressionwidget.sip.in
Expand Up @@ -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)
Expand Down
37 changes: 25 additions & 12 deletions src/core/fieldformatter/qgsvaluerelationfieldformatter.cpp
Expand Up @@ -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() )
Expand Down
4 changes: 3 additions & 1 deletion src/core/fieldformatter/qgsvaluerelationfieldformatter.h
Expand Up @@ -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 )
: key( key )
, value( value )
, description( description )
{}

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

QVariant key;
QString value;
QString description;
};

typedef QVector < QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache;
Expand Down
5 changes: 5 additions & 0 deletions src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp
Expand Up @@ -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 );

Expand All @@ -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 );
Expand Down Expand Up @@ -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() );
Expand All @@ -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() )
Expand Down
7 changes: 4 additions & 3 deletions src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
Expand Up @@ -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 )
Expand All @@ -365,6 +365,7 @@ void QgsValueRelationWidgetWrapper::populate( )
for ( const QgsValueRelationFieldFormatter::ValueRelationItem &element : qgis::as_const( mCache ) )
{
whileBlocking( mComboBox )->addItem( element.value, element.key );
mComboBox->setItemData( mComboBox->count() - 1, element.description, Qt::ToolTipRole );
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsfieldexpressionwidget.h
Expand Up @@ -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)
Expand Down
100 changes: 57 additions & 43 deletions src/ui/editorwidgets/qgsvaluerelationconfigdlgbase.ui
Expand Up @@ -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">
Expand All @@ -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>
Expand All @@ -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">
Expand All @@ -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">
Expand All @@ -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">
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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 94fc1ba

Please sign in to comment.