mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
[forms][feature] Value relation: more options for sorting (#59404)
Implements a few newsorting options for the value relation widget: - reverse order - order by a specific field the default behavior is unchanged (Key). Fixes #54133 Funded by: Consorzio della Bonifica Renana
This commit is contained in:
parent
e96d090109
commit
3000b7f01f
@ -31,16 +31,6 @@ using namespace nlohmann;
|
|||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
bool orderByKeyLessThan( const QgsValueRelationFieldFormatter::ValueRelationItem &p1, const QgsValueRelationFieldFormatter::ValueRelationItem &p2 )
|
|
||||||
{
|
|
||||||
return p1.group == p2.group ? qgsVariantLessThan( p1.key, p2.key ) : qgsVariantLessThan( p1.group, p2.group );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool orderByValueLessThan( const QgsValueRelationFieldFormatter::ValueRelationItem &p1, const QgsValueRelationFieldFormatter::ValueRelationItem &p2 )
|
|
||||||
{
|
|
||||||
return p1.group == p2.group ? qgsVariantLessThan( p1.value, p2.value ) : qgsVariantLessThan( p1.group, p2.group );
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsValueRelationFieldFormatter::QgsValueRelationFieldFormatter()
|
QgsValueRelationFieldFormatter::QgsValueRelationFieldFormatter()
|
||||||
{
|
{
|
||||||
setFlags( flags() | QgsFieldFormatter::CanProvideAvailableValues );
|
setFlags( flags() | QgsFieldFormatter::CanProvideAvailableValues );
|
||||||
@ -176,6 +166,11 @@ QgsValueRelationFieldFormatter::ValueRelationCache QgsValueRelationFieldFormatte
|
|||||||
}
|
}
|
||||||
|
|
||||||
QgsFeatureIterator fit = layer->getFeatures( request );
|
QgsFeatureIterator fit = layer->getFeatures( request );
|
||||||
|
const bool orderByField { config.value( QStringLiteral( "OrderByField" ) ).toBool() };
|
||||||
|
const int fieldIdx { orderByField ? layer->fields().lookupField( config.value( QStringLiteral( "OrderByFieldName" ) ).toString() ) : -1 };
|
||||||
|
const bool reverseSort { config.value( QStringLiteral( "OrderByDescending" ) ).toBool() };
|
||||||
|
|
||||||
|
QMap<QVariant, QVariant> orderByFieldValues;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
while ( fit.nextFeature( f ) )
|
while ( fit.nextFeature( f ) )
|
||||||
@ -187,16 +182,47 @@ QgsValueRelationFieldFormatter::ValueRelationCache QgsValueRelationFieldFormatte
|
|||||||
description = descriptionExpression.evaluate( &context ).toString();
|
description = descriptionExpression.evaluate( &context ).toString();
|
||||||
}
|
}
|
||||||
const QVariant group = groupIdx > -1 ? f.attribute( groupIdx ) : QVariant();
|
const QVariant group = groupIdx > -1 ? f.attribute( groupIdx ) : QVariant();
|
||||||
cache.append( ValueRelationItem( f.attribute( keyIdx ), f.attribute( valueIdx ).toString(), description, group ) );
|
const QVariant keyValue = f.attribute( keyIdx );
|
||||||
|
if ( fieldIdx != -1 )
|
||||||
|
{
|
||||||
|
orderByFieldValues.insert( keyValue, f.attribute( fieldIdx ) );
|
||||||
|
}
|
||||||
|
cache.append( ValueRelationItem( keyValue, f.attribute( valueIdx ).toString(), description, group ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( config.value( QStringLiteral( "OrderByValue" ) ).toBool() )
|
if ( config.value( QStringLiteral( "OrderByValue" ) ).toBool() )
|
||||||
{
|
{
|
||||||
std::sort( cache.begin(), cache.end(), orderByValueLessThan );
|
std::sort( cache.begin(), cache.end(), [&reverseSort]( const QgsValueRelationFieldFormatter::ValueRelationItem & p1, const QgsValueRelationFieldFormatter::ValueRelationItem & p2 ) -> bool
|
||||||
|
{
|
||||||
|
if ( reverseSort )
|
||||||
|
return p1.group == p2.group ? qgsVariantGreaterThan( p1.value, p2.value ) : qgsVariantGreaterThan( p1.group, p2.group );
|
||||||
|
else
|
||||||
|
return p1.group == p2.group ? qgsVariantLessThan( p1.value, p2.value ) : qgsVariantLessThan( p1.group, p2.group );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
// Order by field
|
||||||
|
else if ( fieldIdx != -1 )
|
||||||
|
{
|
||||||
|
std::sort( cache.begin(), cache.end(), [&reverseSort, &orderByFieldValues]( const QgsValueRelationFieldFormatter::ValueRelationItem & p1, const QgsValueRelationFieldFormatter::ValueRelationItem & p2 ) -> bool
|
||||||
|
{
|
||||||
|
if ( reverseSort )
|
||||||
|
return p1.group == p2.group ? qgsVariantGreaterThan( orderByFieldValues.value( p1.key ), orderByFieldValues.value( p2.key ) ) : qgsVariantGreaterThan( p1.group, p2.group );
|
||||||
|
else
|
||||||
|
return p1.group == p2.group ? qgsVariantLessThan( orderByFieldValues.value( p1.key ), orderByFieldValues.value( p2.key ) ) : qgsVariantLessThan( p1.group, p2.group );
|
||||||
|
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
// OrderByKey is the default
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::sort( cache.begin(), cache.end(), orderByKeyLessThan );
|
std::sort( cache.begin(), cache.end(), [&reverseSort]( const QgsValueRelationFieldFormatter::ValueRelationItem & p1, const QgsValueRelationFieldFormatter::ValueRelationItem & p2 ) -> bool
|
||||||
|
{
|
||||||
|
if ( reverseSort )
|
||||||
|
return p1.group == p2.group ? qgsVariantGreaterThan( p1.key, p2.key ) : qgsVariantGreaterThan( p1.group, p2.group );
|
||||||
|
else
|
||||||
|
return p1.group == p2.group ? qgsVariantLessThan( p1.key, p2.key ) : qgsVariantLessThan( p1.group, p2.group );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -31,12 +31,20 @@ QgsValueRelationConfigDlg::QgsValueRelationConfigDlg( QgsVectorLayer *vl, int fi
|
|||||||
mGroupColumn->setLayer( mLayerName->currentLayer() );
|
mGroupColumn->setLayer( mLayerName->currentLayer() );
|
||||||
mGroupColumn->setAllowEmptyFieldName( true );
|
mGroupColumn->setAllowEmptyFieldName( true );
|
||||||
mDescriptionExpression->setLayer( mLayerName->currentLayer() );
|
mDescriptionExpression->setLayer( mLayerName->currentLayer() );
|
||||||
|
mOrderByFieldName->setLayer( mLayerName->currentLayer() );
|
||||||
|
mOrderByFieldName->setAllowEmptyFieldName( false );
|
||||||
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mKeyColumn, &QgsFieldComboBox::setLayer );
|
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mKeyColumn, &QgsFieldComboBox::setLayer );
|
||||||
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mValueColumn, &QgsFieldComboBox::setLayer );
|
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mValueColumn, &QgsFieldComboBox::setLayer );
|
||||||
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mGroupColumn, &QgsFieldComboBox::setLayer );
|
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mGroupColumn, &QgsFieldComboBox::setLayer );
|
||||||
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mDescriptionExpression, &QgsFieldExpressionWidget::setLayer );
|
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, mDescriptionExpression, &QgsFieldExpressionWidget::setLayer );
|
||||||
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, this, &QgsValueRelationConfigDlg::layerChanged );
|
connect( mLayerName, &QgsMapLayerComboBox::layerChanged, this, &QgsValueRelationConfigDlg::layerChanged );
|
||||||
connect( mEditExpression, &QAbstractButton::clicked, this, &QgsValueRelationConfigDlg::editExpression );
|
connect( mEditExpression, &QAbstractButton::clicked, this, &QgsValueRelationConfigDlg::editExpression );
|
||||||
|
connect( mOrderByField, &QAbstractButton::toggled, mOrderByFieldName, [ = ]( bool enabled )
|
||||||
|
{
|
||||||
|
mOrderByFieldName->setEnabled( enabled );
|
||||||
|
} );
|
||||||
|
|
||||||
|
mOrderByGroupBox->setCollapsed( true );
|
||||||
|
|
||||||
mNofColumns->setMinimum( 1 );
|
mNofColumns->setMinimum( 1 );
|
||||||
mNofColumns->setMaximum( 10 );
|
mNofColumns->setMaximum( 10 );
|
||||||
@ -93,6 +101,10 @@ QVariantMap QgsValueRelationConfigDlg::config()
|
|||||||
cfg.insert( QStringLiteral( "NofColumns" ), mNofColumns->value() );
|
cfg.insert( QStringLiteral( "NofColumns" ), mNofColumns->value() );
|
||||||
cfg.insert( QStringLiteral( "AllowNull" ), mAllowNull->isChecked() );
|
cfg.insert( QStringLiteral( "AllowNull" ), mAllowNull->isChecked() );
|
||||||
cfg.insert( QStringLiteral( "OrderByValue" ), mOrderByValue->isChecked() );
|
cfg.insert( QStringLiteral( "OrderByValue" ), mOrderByValue->isChecked() );
|
||||||
|
cfg.insert( QStringLiteral( "OrderByKey" ), mOrderByKey->isChecked() );
|
||||||
|
cfg.insert( QStringLiteral( "OrderByField" ), mOrderByField->isChecked() );
|
||||||
|
cfg.insert( QStringLiteral( "OrderByFieldName" ), mOrderByFieldName->currentField() );
|
||||||
|
cfg.insert( QStringLiteral( "OrderByDescending" ), mOrderByDescending->isChecked() );
|
||||||
cfg.insert( QStringLiteral( "FilterExpression" ), mFilterExpression->toPlainText() );
|
cfg.insert( QStringLiteral( "FilterExpression" ), mFilterExpression->toPlainText() );
|
||||||
cfg.insert( QStringLiteral( "UseCompleter" ), mUseCompleter->isChecked() );
|
cfg.insert( QStringLiteral( "UseCompleter" ), mUseCompleter->isChecked() );
|
||||||
const Qt::MatchFlags completerMatchFlags { mCompleterMatchFromStart->isChecked() ? Qt::MatchFlag::MatchStartsWith : Qt::MatchFlag::MatchContains };
|
const Qt::MatchFlags completerMatchFlags { mCompleterMatchFromStart->isChecked() ? Qt::MatchFlag::MatchStartsWith : Qt::MatchFlag::MatchContains };
|
||||||
@ -105,6 +117,7 @@ void QgsValueRelationConfigDlg::setConfig( const QVariantMap &config )
|
|||||||
{
|
{
|
||||||
QgsVectorLayer *lyr = QgsValueRelationFieldFormatter::resolveLayer( config, QgsProject::instance() );
|
QgsVectorLayer *lyr = QgsValueRelationFieldFormatter::resolveLayer( config, QgsProject::instance() );
|
||||||
mLayerName->setLayer( lyr );
|
mLayerName->setLayer( lyr );
|
||||||
|
mOrderByFieldName->setLayer( lyr );
|
||||||
mKeyColumn->setField( config.value( QStringLiteral( "Key" ) ).toString() );
|
mKeyColumn->setField( config.value( QStringLiteral( "Key" ) ).toString() );
|
||||||
mValueColumn->setField( config.value( QStringLiteral( "Value" ) ).toString() );
|
mValueColumn->setField( config.value( QStringLiteral( "Value" ) ).toString() );
|
||||||
mGroupColumn->setField( config.value( QStringLiteral( "Group" ) ).toString() );
|
mGroupColumn->setField( config.value( QStringLiteral( "Group" ) ).toString() );
|
||||||
@ -119,6 +132,22 @@ void QgsValueRelationConfigDlg::setConfig( const QVariantMap &config )
|
|||||||
}
|
}
|
||||||
mAllowNull->setChecked( config.value( QStringLiteral( "AllowNull" ) ).toBool() );
|
mAllowNull->setChecked( config.value( QStringLiteral( "AllowNull" ) ).toBool() );
|
||||||
mOrderByValue->setChecked( config.value( QStringLiteral( "OrderByValue" ) ).toBool() );
|
mOrderByValue->setChecked( config.value( QStringLiteral( "OrderByValue" ) ).toBool() );
|
||||||
|
mOrderByField->setChecked( config.value( QStringLiteral( "OrderByField" ) ).toBool() );
|
||||||
|
mOrderByKey->setChecked( config.value( QStringLiteral( "OrderByKey" ) ).toBool() );
|
||||||
|
mOrderByFieldName->setField( config.value( QStringLiteral( "OrderByFieldName" ) ).toString() );
|
||||||
|
mOrderByDescending->setChecked( config.value( QStringLiteral( "OrderByDescending" ) ).toBool() );
|
||||||
|
|
||||||
|
if ( !mOrderByField->isChecked() && !mOrderByValue->isChecked() && !mOrderByKey->isChecked() )
|
||||||
|
{
|
||||||
|
mOrderByKey->setChecked( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
// order by key is the default, if it is not checked, expand the config
|
||||||
|
if ( !mOrderByKey->isChecked() )
|
||||||
|
{
|
||||||
|
mOrderByGroupBox->setCollapsed( false );
|
||||||
|
}
|
||||||
|
|
||||||
mFilterExpression->setPlainText( config.value( QStringLiteral( "FilterExpression" ) ).toString() );
|
mFilterExpression->setPlainText( config.value( QStringLiteral( "FilterExpression" ) ).toString() );
|
||||||
mUseCompleter->setChecked( config.value( QStringLiteral( "UseCompleter" ) ).toBool() );
|
mUseCompleter->setChecked( config.value( QStringLiteral( "UseCompleter" ) ).toBool() );
|
||||||
// Default is MatchStartsWith for backwards compatibility
|
// Default is MatchStartsWith for backwards compatibility
|
||||||
@ -130,6 +159,7 @@ void QgsValueRelationConfigDlg::layerChanged()
|
|||||||
{
|
{
|
||||||
mFilterExpression->setEnabled( qobject_cast<QgsVectorLayer *>( mLayerName->currentLayer() ) );
|
mFilterExpression->setEnabled( qobject_cast<QgsVectorLayer *>( mLayerName->currentLayer() ) );
|
||||||
mEditExpression->setEnabled( qobject_cast<QgsVectorLayer *>( mLayerName->currentLayer() ) );
|
mEditExpression->setEnabled( qobject_cast<QgsVectorLayer *>( mLayerName->currentLayer() ) );
|
||||||
|
mOrderByFieldName->setLayer( mLayerName->currentLayer() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsValueRelationConfigDlg::editExpression()
|
void QgsValueRelationConfigDlg::editExpression()
|
||||||
|
@ -6,15 +6,116 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>318</width>
|
<width>342</width>
|
||||||
<height>490</height>
|
<height>620</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string notr="true">Form</string>
|
<string notr="true">Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
|
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
|
||||||
<item row="14" column="0" colspan="2">
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Key column</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mKeyColumn</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="0">
|
||||||
|
<widget class="QCheckBox" name="mUseCompleter">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use completer</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Description</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="1">
|
||||||
|
<widget class="QgsSpinBox" name="mNofColumns">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Group column</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mGroupColumn</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="20" column="0" colspan="2">
|
||||||
|
<widget class="QTextEdit" name="mFilterExpression"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QgsMapLayerComboBox" name="mLayerName"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QgsFieldComboBox" name="mKeyColumn"/>
|
||||||
|
</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="15" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="mAllowMulti">
|
||||||
|
<property name="text">
|
||||||
|
<string>Allow multiple selections</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Layer</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mLayerName</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="mAllowNull">
|
||||||
|
<property name="text">
|
||||||
|
<string>Allow NULL value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Value column</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>mValueColumn</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="1">
|
||||||
|
<widget class="QCheckBox" name="mCompleterMatchFromStart">
|
||||||
|
<property name="text">
|
||||||
|
<string>Only match from the beginning of the string</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="17" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_19">
|
<widget class="QLabel" name="label_19">
|
||||||
@ -32,7 +133,7 @@
|
|||||||
<enum>Qt::RightToLeft</enum>
|
<enum>Qt::RightToLeft</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset>
|
<iconset resource="../../../images/images.qrc">
|
||||||
<normaloff>:/images/themes/default/mIconExpression.svg</normaloff>:/images/themes/default/mIconExpression.svg</iconset>
|
<normaloff>:/images/themes/default/mIconExpression.svg</normaloff>:/images/themes/default/mIconExpression.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -52,137 +153,85 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="0">
|
<item row="8" column="1">
|
||||||
<widget class="QLabel" name="label_nofColumns">
|
|
||||||
<property name="text">
|
|
||||||
<string>Number of columns</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="17" 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">
|
|
||||||
<string>Layer</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>mLayerName</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QgsFieldComboBox" name="mValueColumn"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" 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="12" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="mAllowMulti">
|
|
||||||
<property name="text">
|
|
||||||
<string>Allow multiple selections</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="mAllowNull">
|
|
||||||
<property name="text">
|
|
||||||
<string>Allow NULL value</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="0">
|
|
||||||
<widget class="QCheckBox" name="mUseCompleter">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use completer</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="11" column="1">
|
|
||||||
<widget class="QCheckBox" name="mCompleterMatchFromStart">
|
|
||||||
<property name="text">
|
|
||||||
<string>Only match from the beginning of the string</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Key column</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>mKeyColumn</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="1">
|
|
||||||
<widget class="QgsSpinBox" name="mNofColumns">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>1</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</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">
|
|
||||||
<string>Value column</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>mValueColumn</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Group column</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>mGroupColumn</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QgsFieldComboBox" name="mGroupColumn"/>
|
<widget class="QgsFieldComboBox" name="mGroupColumn"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="mDisplayGroupName">
|
<widget class="QCheckBox" name="mDisplayGroupName">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Display group name</string>
|
<string>Display group name</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QgsFieldComboBox" name="mValueColumn"/>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="0">
|
||||||
|
<widget class="QLabel" name="label_nofColumns">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Description</string>
|
<string>Number of columns</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QgsFieldExpressionWidget" name="mDescriptionExpression" native="true"/>
|
<widget class="QgsFieldExpressionWidget" name="mDescriptionExpression" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0" rowspan="2" colspan="2">
|
||||||
|
<widget class="QgsCollapsibleGroupBox" name="mOrderByGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Order By</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="mOrderByKey">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Use the values in the key column for sorting</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Key</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="mOrderByValue">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Use the values in the value column for sorting</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="mOrderByField">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Use the values from a specific field for sorting</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Field</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QgsFieldComboBox" name="mOrderByFieldName"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="mOrderByDescending">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reverse the sorting</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Descending order</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@ -207,6 +256,12 @@
|
|||||||
<extends>QComboBox</extends>
|
<extends>QComboBox</extends>
|
||||||
<header>qgsmaplayercombobox.h</header>
|
<header>qgsmaplayercombobox.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QgsCollapsibleGroupBox</class>
|
||||||
|
<extends>QGroupBox</extends>
|
||||||
|
<header>qgscollapsiblegroupbox.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>mLayerName</tabstop>
|
<tabstop>mLayerName</tabstop>
|
||||||
@ -214,7 +269,6 @@
|
|||||||
<tabstop>mValueColumn</tabstop>
|
<tabstop>mValueColumn</tabstop>
|
||||||
<tabstop>mGroupColumn</tabstop>
|
<tabstop>mGroupColumn</tabstop>
|
||||||
<tabstop>mDescriptionExpression</tabstop>
|
<tabstop>mDescriptionExpression</tabstop>
|
||||||
<tabstop>mOrderByValue</tabstop>
|
|
||||||
<tabstop>mAllowNull</tabstop>
|
<tabstop>mAllowNull</tabstop>
|
||||||
<tabstop>mAllowMulti</tabstop>
|
<tabstop>mAllowMulti</tabstop>
|
||||||
<tabstop>mUseCompleter</tabstop>
|
<tabstop>mUseCompleter</tabstop>
|
||||||
@ -223,6 +277,8 @@
|
|||||||
<tabstop>mEditExpression</tabstop>
|
<tabstop>mEditExpression</tabstop>
|
||||||
<tabstop>mFilterExpression</tabstop>
|
<tabstop>mFilterExpression</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="../../../images/images.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -39,6 +39,8 @@ class TestQgsValueRelationFieldFormatter: public QObject
|
|||||||
void testDependencies();
|
void testDependencies();
|
||||||
void testSortValueNull();
|
void testSortValueNull();
|
||||||
void testGroup();
|
void testGroup();
|
||||||
|
void testOrderBy_data();
|
||||||
|
void testOrderBy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<QgsVectorLayer> mLayer1;
|
std::unique_ptr<QgsVectorLayer> mLayer1;
|
||||||
@ -112,7 +114,7 @@ void TestQgsValueRelationFieldFormatter::init()
|
|||||||
QgsFeature ft3( mLayer2->fields() );
|
QgsFeature ft3( mLayer2->fields() );
|
||||||
ft3.setAttribute( QStringLiteral( "pk" ), 11 );
|
ft3.setAttribute( QStringLiteral( "pk" ), 11 );
|
||||||
ft3.setAttribute( QStringLiteral( "material" ), "iron" );
|
ft3.setAttribute( QStringLiteral( "material" ), "iron" );
|
||||||
ft3.setAttribute( QStringLiteral( "diameter" ), 120 );
|
ft3.setAttribute( QStringLiteral( "diameter" ), 110 );
|
||||||
ft3.setAttribute( QStringLiteral( "raccord" ), "sleeve" );
|
ft3.setAttribute( QStringLiteral( "raccord" ), "sleeve" );
|
||||||
mLayer2->startEditing();
|
mLayer2->startEditing();
|
||||||
mLayer2->addFeature( ft3 );
|
mLayer2->addFeature( ft3 );
|
||||||
@ -121,7 +123,7 @@ void TestQgsValueRelationFieldFormatter::init()
|
|||||||
QgsFeature ft4( mLayer2->fields() );
|
QgsFeature ft4( mLayer2->fields() );
|
||||||
ft4.setAttribute( QStringLiteral( "pk" ), 12 );
|
ft4.setAttribute( QStringLiteral( "pk" ), 12 );
|
||||||
ft4.setAttribute( QStringLiteral( "material" ), "steel" );
|
ft4.setAttribute( QStringLiteral( "material" ), "steel" );
|
||||||
ft4.setAttribute( QStringLiteral( "diameter" ), 120 );
|
ft4.setAttribute( QStringLiteral( "diameter" ), 100 );
|
||||||
ft4.setAttribute( QStringLiteral( "raccord" ), "collar" );
|
ft4.setAttribute( QStringLiteral( "raccord" ), "collar" );
|
||||||
mLayer2->startEditing();
|
mLayer2->startEditing();
|
||||||
mLayer2->addFeature( ft4 );
|
mLayer2->addFeature( ft4 );
|
||||||
@ -180,5 +182,62 @@ void TestQgsValueRelationFieldFormatter::testGroup()
|
|||||||
QCOMPARE( cache.at( cache.size() - 1 ).group, QVariant( QStringLiteral( "steel" ) ) );
|
QCOMPARE( cache.at( cache.size() - 1 ).group, QVariant( QStringLiteral( "steel" ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsValueRelationFieldFormatter::testOrderBy_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>( "orderBy" );
|
||||||
|
QTest::addColumn<QString>( "fieldName" );
|
||||||
|
QTest::addColumn<QString>( "expectedFirst" );
|
||||||
|
QTest::addColumn<QString>( "expectedLast" );
|
||||||
|
|
||||||
|
QTest::newRow( "orderByDefault(pk)" ) << QString() << QString() << "brides" << "collar";
|
||||||
|
QTest::newRow( "orderByKey(pk)" ) << QString() << QStringLiteral( "Key" ) << "brides" << "collar";
|
||||||
|
QTest::newRow( "orderByValue(raccord)" ) << QString() << QStringLiteral( "Value" ) << "brides" << "collar";
|
||||||
|
QTest::newRow( "orderByField(raccord)" ) << QStringLiteral( "Field" ) << QStringLiteral( "raccord" ) << "brides" << "sleeve";
|
||||||
|
QTest::newRow( "orderByField(diameter)" ) << QStringLiteral( "Field" ) << QStringLiteral( "diameter" ) << "collar" << "brides";
|
||||||
|
QTest::newRow( "orderByField(material)" ) << QStringLiteral( "Field" ) << QStringLiteral( "material" ) << "brides" << "collar";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsValueRelationFieldFormatter::testOrderBy()
|
||||||
|
{
|
||||||
|
|
||||||
|
QFETCH( QString, orderBy );
|
||||||
|
QFETCH( QString, fieldName );
|
||||||
|
QFETCH( QString, expectedFirst );
|
||||||
|
QFETCH( QString, expectedLast );
|
||||||
|
|
||||||
|
QVariantMap config;
|
||||||
|
config.insert( QStringLiteral( "Layer" ), mLayer2->id() );
|
||||||
|
config.insert( QStringLiteral( "Key" ), QStringLiteral( "pk" ) );
|
||||||
|
config.insert( QStringLiteral( "Value" ), QStringLiteral( "raccord" ) );
|
||||||
|
|
||||||
|
if ( !orderBy.isEmpty() )
|
||||||
|
{
|
||||||
|
config.insert( QStringLiteral( "OrderBy%1" ).arg( orderBy ), true );
|
||||||
|
}
|
||||||
|
if ( !fieldName.isEmpty() )
|
||||||
|
{
|
||||||
|
config.insert( QStringLiteral( "OrderByFieldName" ), fieldName );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ascending
|
||||||
|
{
|
||||||
|
const QgsValueRelationFieldFormatter formatter;
|
||||||
|
QgsValueRelationFieldFormatter::ValueRelationCache cache = formatter.createCache( config );
|
||||||
|
QVERIFY( !cache.isEmpty() );
|
||||||
|
QCOMPARE( cache.at( 0 ).value, expectedFirst );
|
||||||
|
QCOMPARE( cache.at( mLayer2->featureCount() - 1 ).value, expectedLast );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descending
|
||||||
|
{
|
||||||
|
config.insert( QStringLiteral( "OrderByDescending" ), true );
|
||||||
|
const QgsValueRelationFieldFormatter formatter;
|
||||||
|
QgsValueRelationFieldFormatter::ValueRelationCache cache = formatter.createCache( config );
|
||||||
|
QVERIFY( !cache.isEmpty() );
|
||||||
|
QCOMPARE( cache.at( 0 ).value, expectedLast );
|
||||||
|
QCOMPARE( cache.at( mLayer2->featureCount() - 1 ).value, expectedFirst );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsValueRelationFieldFormatter )
|
QGSTEST_MAIN( TestQgsValueRelationFieldFormatter )
|
||||||
#include "testqgsvaluerelationfieldformatter.moc"
|
#include "testqgsvaluerelationfieldformatter.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user