QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsrelationreferenceconfigdlg.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrelationreferenceconfigdlg.cpp
3 --------------------------------------
4 Date : 21.4.2013
5 Copyright : (C) 2013 Matthias Kuhn
6 Email : matthias at opengis dot ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsfields.h"
19#include "qgsproject.h"
20#include "qgsrelationmanager.h"
21#include "qgsvectorlayer.h"
24
26 : QgsEditorConfigWidget( vl, fieldIdx, parent )
27
28{
29 setupUi( this );
30
31 mFetchLimit->setMaximum( std::numeric_limits<int>::max() );
32
33 connect( mAddFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mAddFilterButton_clicked );
34 connect( mRemoveFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked );
35
36 mExpressionWidget->registerExpressionContextGenerator( vl );
37
38 connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRelationReferenceConfigDlg::relationChanged );
39
40 const auto constReferencingRelations = vl->referencingRelations( fieldIdx );
41 for ( const QgsRelation &relation : constReferencingRelations )
42 {
43 if ( relation.name().isEmpty() )
44 mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.id(), relation.referencedLayerId() ), relation.id() );
45 else
46 mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.name(), relation.referencedLayerId() ), relation.id() );
47
48 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( mComboRelation->model() );
49 QStandardItem *item = model->item( model->rowCount() - 1 );
50 item->setFlags( relation.type() == Qgis::RelationshipType::Generated
51 ? item->flags() & ~Qt::ItemIsEnabled
52 : item->flags() | Qt::ItemIsEnabled );
53
54 if ( auto *lReferencedLayer = relation.referencedLayer() )
55 {
56 mExpressionWidget->setField( lReferencedLayer->displayExpression() );
57 }
58 }
59
60 connect( mCbxAllowNull, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
61 connect( mCbxShowForm, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
62 connect( mCbxShowOpenFormButton, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
63 connect( mCbxMapIdentification, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
64 connect( mCbxReadOnly, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
65 connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
66 connect( mCbxAllowAddFeatures, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
67 connect( mFilterGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
68 connect( mFilterFieldsList, &QListWidget::itemChanged, this, &QgsEditorConfigWidget::changed );
69 connect( mCbxChainFilters, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
70 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsEditorConfigWidget::changed );
71 connect( mEditExpression, &QAbstractButton::clicked, this, &QgsRelationReferenceConfigDlg::mEditExpression_clicked );
72 connect( mFilterExpression, &QTextEdit::textChanged, this, &QgsEditorConfigWidget::changed );
73 connect( mFetchLimitCheckBox, &QCheckBox::toggled, mFetchLimit, &QSpinBox::setEnabled );
74}
75
76void QgsRelationReferenceConfigDlg::mEditExpression_clicked()
77{
78 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer() );
79 if ( !vl )
80 return;
81
85
86 context.setHighlightedFunctions( QStringList() << QStringLiteral( "current_value" ) << QStringLiteral( "current_parent_value" ) );
87 context.setHighlightedVariables( QStringList() << QStringLiteral( "current_geometry" )
88 << QStringLiteral( "current_feature" )
89 << QStringLiteral( "form_mode" )
90 << QStringLiteral( "current_parent_geometry" )
91 << QStringLiteral( "current_parent_feature" ) );
92
93 QgsExpressionBuilderDialog dlg( vl, mFilterExpression->toPlainText(), this, QStringLiteral( "generic" ), context );
94 dlg.setWindowTitle( tr( "Edit Filter Expression" ) );
95
96 if ( dlg.exec() == QDialog::Accepted )
97 {
98 mFilterExpression->setPlainText( dlg.expressionBuilder()->expressionText() );
99 }
100}
101
102void QgsRelationReferenceConfigDlg::setConfig( const QVariantMap &config )
103{
104 mCbxAllowNull->setChecked( config.value( QStringLiteral( "AllowNULL" ), false ).toBool() );
105 mCbxShowForm->setChecked( config.value( QStringLiteral( "ShowForm" ), false ).toBool() );
106 mCbxShowOpenFormButton->setChecked( config.value( QStringLiteral( "ShowOpenFormButton" ), true ).toBool() );
107
108 if ( config.contains( QStringLiteral( "Relation" ) ) )
109 {
110 mComboRelation->setCurrentIndex( mComboRelation->findData( config.value( QStringLiteral( "Relation" ) ).toString() ) );
111 relationChanged( mComboRelation->currentIndex() );
112 }
113
114 mCbxMapIdentification->setChecked( config.value( QStringLiteral( "MapIdentification" ), false ).toBool() );
115 mCbxAllowAddFeatures->setChecked( config.value( QStringLiteral( "AllowAddFeatures" ), false ).toBool() );
116 mCbxReadOnly->setChecked( config.value( QStringLiteral( "ReadOnly" ), false ).toBool() );
117 mFetchLimitCheckBox->setChecked( config.value( QStringLiteral( "FetchLimitActive" ), QgsSettings().value( QStringLiteral( "maxEntriesRelationWidget" ), 100, QgsSettings::Gui ).toInt() > 0 ).toBool() );
118 mFetchLimit->setValue( config.value( QStringLiteral( "FetchLimitNumber" ), QgsSettings().value( QStringLiteral( "maxEntriesRelationWidget" ), 100, QgsSettings::Gui ) ).toInt() );
119 mFilterExpression->setPlainText( config.value( QStringLiteral( "FilterExpression" ) ).toString() );
120
121 if ( config.contains( QStringLiteral( "FilterFields" ) ) )
122 {
123 mFilterGroupBox->setChecked( true );
124 const auto constToStringList = config.value( "FilterFields" ).toStringList();
125 for ( const QString &fld : constToStringList )
126 {
127 addFilterField( fld );
128 }
129
130 mCbxChainFilters->setChecked( config.value( QStringLiteral( "ChainFilters" ) ).toBool() );
131 }
132}
133
134void QgsRelationReferenceConfigDlg::relationChanged( int idx )
135{
136 const QString relName = mComboRelation->itemData( idx ).toString();
137 const QgsRelation rel = QgsProject::instance()->relationManager()->relation( relName );
138
139 mReferencedLayer = rel.referencedLayer();
140 mExpressionWidget->setLayer( mReferencedLayer ); // set even if 0
141 if ( mReferencedLayer )
142 {
143 mExpressionWidget->setField( mReferencedLayer->displayExpression() );
144 mCbxMapIdentification->setEnabled( mReferencedLayer->isSpatial() );
145 }
146
147 loadFields();
148}
149
150void QgsRelationReferenceConfigDlg::mAddFilterButton_clicked()
151{
152 const auto constSelectedItems = mAvailableFieldsList->selectedItems();
153 for ( QListWidgetItem *item : constSelectedItems )
154 {
155 addFilterField( item );
156 }
157}
158
159void QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked()
160{
161 const auto constSelectedItems = mFilterFieldsList->selectedItems();
162 for ( QListWidgetItem *item : constSelectedItems )
163 {
164 mFilterFieldsList->takeItem( indexFromListWidgetItem( item ) );
165 mAvailableFieldsList->addItem( item );
166 }
167}
168
170{
171 QVariantMap myConfig;
172 myConfig.insert( QStringLiteral( "AllowNULL" ), mCbxAllowNull->isChecked() );
173 myConfig.insert( QStringLiteral( "ShowForm" ), mCbxShowForm->isChecked() );
174 myConfig.insert( QStringLiteral( "ShowOpenFormButton" ), mCbxShowOpenFormButton->isChecked() );
175 myConfig.insert( QStringLiteral( "MapIdentification" ), mCbxMapIdentification->isEnabled() && mCbxMapIdentification->isChecked() );
176 myConfig.insert( QStringLiteral( "ReadOnly" ), mCbxReadOnly->isChecked() );
177 myConfig.insert( QStringLiteral( "Relation" ), mComboRelation->currentData() );
178 myConfig.insert( QStringLiteral( "AllowAddFeatures" ), mCbxAllowAddFeatures->isChecked() );
179 myConfig.insert( QStringLiteral( "FetchLimitActive" ), mFetchLimitCheckBox->isChecked() );
180 myConfig.insert( QStringLiteral( "FetchLimitNumber" ), mFetchLimit->value() );
181
182 if ( mFilterGroupBox->isChecked() )
183 {
184 QStringList filterFields;
185 filterFields.reserve( mFilterFieldsList->count() );
186 for ( int i = 0; i < mFilterFieldsList->count(); i++ )
187 {
188 filterFields << mFilterFieldsList->item( i )->data( Qt::UserRole ).toString();
189 }
190 myConfig.insert( QStringLiteral( "FilterFields" ), filterFields );
191
192 myConfig.insert( QStringLiteral( "ChainFilters" ), mCbxChainFilters->isChecked() );
193 myConfig.insert( QStringLiteral( "FilterExpression" ), mFilterExpression->toPlainText() );
194 }
195
196 if ( mReferencedLayer )
197 {
198 // Store referenced layer data source and provider
199 myConfig.insert( QStringLiteral( "ReferencedLayerDataSource" ), mReferencedLayer->publicSource() );
200 myConfig.insert( QStringLiteral( "ReferencedLayerProviderKey" ), mReferencedLayer->providerType() );
201 myConfig.insert( QStringLiteral( "ReferencedLayerId" ), mReferencedLayer->id() );
202 myConfig.insert( QStringLiteral( "ReferencedLayerName" ), mReferencedLayer->name() );
203 mReferencedLayer->setDisplayExpression( mExpressionWidget->currentField() );
204 }
205
206 return myConfig;
207}
208
209void QgsRelationReferenceConfigDlg::loadFields()
210{
211 mAvailableFieldsList->clear();
212 mFilterFieldsList->clear();
213
214 if ( mReferencedLayer )
215 {
216 QgsVectorLayer *l = mReferencedLayer;
217 const QgsFields &flds = l->fields();
218 for ( int i = 0; i < flds.count(); i++ )
219 {
220 mAvailableFieldsList->addItem( flds.at( i ).displayName() );
221 mAvailableFieldsList->item( mAvailableFieldsList->count() - 1 )->setData( Qt::UserRole, flds.at( i ).name() );
222 }
223 }
224}
225
226void QgsRelationReferenceConfigDlg::addFilterField( const QString &field )
227{
228 for ( int i = 0; i < mAvailableFieldsList->count(); i++ )
229 {
230 if ( mAvailableFieldsList->item( i )->data( Qt::UserRole ).toString() == field )
231 {
232 addFilterField( mAvailableFieldsList->item( i ) );
233 break;
234 }
235 }
236}
237
238void QgsRelationReferenceConfigDlg::addFilterField( QListWidgetItem *item )
239{
240 mAvailableFieldsList->takeItem( indexFromListWidgetItem( item ) );
241 mFilterFieldsList->addItem( item );
242}
243
244int QgsRelationReferenceConfigDlg::indexFromListWidgetItem( QListWidgetItem *item )
245{
246 QListWidget *lw = item->listWidget();
247
248 for ( int i = 0; i < lw->count(); i++ )
249 {
250 if ( lw->item( i ) == item )
251 return i;
252 }
253
254 return -1;
255}
@ Generated
A generated relation is a child of a polymorphic relation.
This class should be subclassed for every configurable editor widget type.
int field()
Returns the field for which this configuration widget applies.
QgsVectorLayer * layer()
Returns the layer for which this configuration widget applies.
void changed()
Emitted when the configuration of the widget is changed.
A generic dialog for building expression strings.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
The QgsFieldExpressionWidget class creates a widget to choose fields and edit expressions It contains...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QString name
Definition: qgsfield.h:62
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:88
Container of fields for a vector layer.
Definition: qgsfields.h:45
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QString name
Definition: qgsmaplayer.h:78
QString providerType() const
Returns the provider type (provider key) for this layer.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsRelationManager * relationManager
Definition: qgsproject.h:117
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:481
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
QgsRelationReferenceConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
QVariantMap config() override
Create a configuration from the current GUI state.
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:47
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
Represents a vector layer which manages a vector based data sets.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
QString displayExpression