QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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 connect( mAddFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mAddFilterButton_clicked );
31 connect( mRemoveFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked );
32
33 mExpressionWidget->registerExpressionContextGenerator( vl );
34
35 connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRelationReferenceConfigDlg::relationChanged );
36
37 const auto constReferencingRelations = vl->referencingRelations( fieldIdx );
38 for ( const QgsRelation &relation : constReferencingRelations )
39 {
40 if ( relation.name().isEmpty() )
41 mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.id(), relation.referencedLayerId() ), relation.id() );
42 else
43 mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.name(), relation.referencedLayerId() ), relation.id() );
44
45 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( mComboRelation->model() );
46 QStandardItem *item = model->item( model->rowCount() - 1 );
47 item->setFlags( relation.type() == Qgis::RelationshipType::Generated
48 ? item->flags() & ~Qt::ItemIsEnabled
49 : item->flags() | Qt::ItemIsEnabled );
50
51 if ( auto *lReferencedLayer = relation.referencedLayer() )
52 {
53 mExpressionWidget->setField( lReferencedLayer->displayExpression() );
54 }
55 }
56
57 connect( mCbxAllowNull, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
58 connect( mCbxOrderByValue, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
59 connect( mCbxShowForm, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
60 connect( mCbxShowOpenFormButton, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
61 connect( mCbxMapIdentification, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
62 connect( mCbxReadOnly, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
63 connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
64 connect( mCbxAllowAddFeatures, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
65 connect( mFilterGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
66 connect( mFilterFieldsList, &QListWidget::itemChanged, this, &QgsEditorConfigWidget::changed );
67 connect( mCbxChainFilters, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
68 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsEditorConfigWidget::changed );
69 connect( mEditExpression, &QAbstractButton::clicked, this, &QgsRelationReferenceConfigDlg::mEditExpression_clicked );
70 connect( mFilterExpression, &QTextEdit::textChanged, this, &QgsEditorConfigWidget::changed );
71}
72
73void QgsRelationReferenceConfigDlg::mEditExpression_clicked()
74{
75 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer() );
76 if ( !vl )
77 return;
78
82
83 context.setHighlightedFunctions( QStringList() << QStringLiteral( "current_value" ) << QStringLiteral( "current_parent_value" ) );
84 context.setHighlightedVariables( QStringList() << QStringLiteral( "current_geometry" )
85 << QStringLiteral( "current_feature" )
86 << QStringLiteral( "form_mode" )
87 << QStringLiteral( "current_parent_geometry" )
88 << QStringLiteral( "current_parent_feature" ) );
89
90 QgsExpressionBuilderDialog dlg( vl, mFilterExpression->toPlainText(), this, QStringLiteral( "generic" ), context );
91 dlg.setWindowTitle( tr( "Edit Filter Expression" ) );
92
93 if ( dlg.exec() == QDialog::Accepted )
94 {
95 mFilterExpression->setPlainText( dlg.expressionBuilder()->expressionText() );
96 }
97}
98
99void QgsRelationReferenceConfigDlg::setConfig( const QVariantMap &config )
100{
101 mCbxAllowNull->setChecked( config.value( QStringLiteral( "AllowNULL" ), false ).toBool() );
102 mCbxOrderByValue->setChecked( config.value( QStringLiteral( "OrderByValue" ), false ).toBool() );
103 mCbxShowForm->setChecked( config.value( QStringLiteral( "ShowForm" ), false ).toBool() );
104 mCbxShowOpenFormButton->setChecked( config.value( QStringLiteral( "ShowOpenFormButton" ), true ).toBool() );
105
106 if ( config.contains( QStringLiteral( "Relation" ) ) )
107 {
108 mComboRelation->setCurrentIndex( mComboRelation->findData( config.value( QStringLiteral( "Relation" ) ).toString() ) );
109 relationChanged( mComboRelation->currentIndex() );
110 }
111
112 mCbxMapIdentification->setChecked( config.value( QStringLiteral( "MapIdentification" ), false ).toBool() );
113 mCbxAllowAddFeatures->setChecked( config.value( QStringLiteral( "AllowAddFeatures" ), false ).toBool() );
114 mCbxReadOnly->setChecked( config.value( QStringLiteral( "ReadOnly" ), false ).toBool() );
115 mFilterExpression->setPlainText( config.value( QStringLiteral( "FilterExpression" ) ).toString() );
116
117 if ( config.contains( QStringLiteral( "FilterFields" ) ) )
118 {
119 mFilterGroupBox->setChecked( true );
120 const auto constToStringList = config.value( "FilterFields" ).toStringList();
121 for ( const QString &fld : constToStringList )
122 {
123 addFilterField( fld );
124 }
125
126 mCbxChainFilters->setChecked( config.value( QStringLiteral( "ChainFilters" ) ).toBool() );
127 }
128}
129
130void QgsRelationReferenceConfigDlg::relationChanged( int idx )
131{
132 const QString relName = mComboRelation->itemData( idx ).toString();
133 const QgsRelation rel = QgsProject::instance()->relationManager()->relation( relName );
134
135 mReferencedLayer = rel.referencedLayer();
136 mExpressionWidget->setLayer( mReferencedLayer ); // set even if 0
137 if ( mReferencedLayer )
138 {
139 mExpressionWidget->setField( mReferencedLayer->displayExpression() );
140 mCbxMapIdentification->setEnabled( mReferencedLayer->isSpatial() );
141 }
142
143 loadFields();
144}
145
146void QgsRelationReferenceConfigDlg::mAddFilterButton_clicked()
147{
148 const auto constSelectedItems = mAvailableFieldsList->selectedItems();
149 for ( QListWidgetItem *item : constSelectedItems )
150 {
151 addFilterField( item );
152 }
153}
154
155void QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked()
156{
157 const auto constSelectedItems = mFilterFieldsList->selectedItems();
158 for ( QListWidgetItem *item : constSelectedItems )
159 {
160 mFilterFieldsList->takeItem( indexFromListWidgetItem( item ) );
161 mAvailableFieldsList->addItem( item );
162 }
163}
164
166{
167 QVariantMap myConfig;
168 myConfig.insert( QStringLiteral( "AllowNULL" ), mCbxAllowNull->isChecked() );
169 myConfig.insert( QStringLiteral( "OrderByValue" ), mCbxOrderByValue->isChecked() );
170 myConfig.insert( QStringLiteral( "ShowForm" ), mCbxShowForm->isChecked() );
171 myConfig.insert( QStringLiteral( "ShowOpenFormButton" ), mCbxShowOpenFormButton->isChecked() );
172 myConfig.insert( QStringLiteral( "MapIdentification" ), mCbxMapIdentification->isEnabled() && mCbxMapIdentification->isChecked() );
173 myConfig.insert( QStringLiteral( "ReadOnly" ), mCbxReadOnly->isChecked() );
174 myConfig.insert( QStringLiteral( "Relation" ), mComboRelation->currentData() );
175 myConfig.insert( QStringLiteral( "AllowAddFeatures" ), mCbxAllowAddFeatures->isChecked() );
176
177 if ( mFilterGroupBox->isChecked() )
178 {
179 QStringList filterFields;
180 filterFields.reserve( mFilterFieldsList->count() );
181 for ( int i = 0; i < mFilterFieldsList->count(); i++ )
182 {
183 filterFields << mFilterFieldsList->item( i )->data( Qt::UserRole ).toString();
184 }
185 myConfig.insert( QStringLiteral( "FilterFields" ), filterFields );
186
187 myConfig.insert( QStringLiteral( "ChainFilters" ), mCbxChainFilters->isChecked() );
188 myConfig.insert( QStringLiteral( "FilterExpression" ), mFilterExpression->toPlainText() );
189 }
190
191 if ( mReferencedLayer )
192 {
193 // Store referenced layer data source and provider
194 myConfig.insert( QStringLiteral( "ReferencedLayerDataSource" ), mReferencedLayer->publicSource() );
195 myConfig.insert( QStringLiteral( "ReferencedLayerProviderKey" ), mReferencedLayer->providerType() );
196 myConfig.insert( QStringLiteral( "ReferencedLayerId" ), mReferencedLayer->id() );
197 myConfig.insert( QStringLiteral( "ReferencedLayerName" ), mReferencedLayer->name() );
198 mReferencedLayer->setDisplayExpression( mExpressionWidget->currentField() );
199 }
200
201 return myConfig;
202}
203
204void QgsRelationReferenceConfigDlg::loadFields()
205{
206 mAvailableFieldsList->clear();
207 mFilterFieldsList->clear();
208
209 if ( mReferencedLayer )
210 {
211 QgsVectorLayer *l = mReferencedLayer;
212 const QgsFields &flds = l->fields();
213 for ( int i = 0; i < flds.count(); i++ )
214 {
215 mAvailableFieldsList->addItem( flds.at( i ).displayName() );
216 mAvailableFieldsList->item( mAvailableFieldsList->count() - 1 )->setData( Qt::UserRole, flds.at( i ).name() );
217 }
218 }
219}
220
221void QgsRelationReferenceConfigDlg::addFilterField( const QString &field )
222{
223 for ( int i = 0; i < mAvailableFieldsList->count(); i++ )
224 {
225 if ( mAvailableFieldsList->item( i )->data( Qt::UserRole ).toString() == field )
226 {
227 addFilterField( mAvailableFieldsList->item( i ) );
228 break;
229 }
230 }
231}
232
233void QgsRelationReferenceConfigDlg::addFilterField( QListWidgetItem *item )
234{
235 mAvailableFieldsList->takeItem( indexFromListWidgetItem( item ) );
236 mFilterFieldsList->addItem( item );
237}
238
239int QgsRelationReferenceConfigDlg::indexFromListWidgetItem( QListWidgetItem *item )
240{
241 QListWidget *lw = item->listWidget();
242
243 for ( int i = 0; i < lw->count(); i++ )
244 {
245 if ( lw->item( i ) == item )
246 return i;
247 }
248
249 return -1;
250}
@ 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 reates 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:60
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:90
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:76
QString providerType() const
Returns the provider type (provider key) for this layer.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QgsRelationManager * relationManager
Definition: qgsproject.h:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
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
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
const QgsField & field
Definition: qgsfield.h:463