QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 "qgseditorwidgetfactory.h"
19 #include "qgsfields.h"
20 #include "qgsproject.h"
21 #include "qgsrelationmanager.h"
22 #include "qgsvectorlayer.h"
25 
27  : QgsEditorConfigWidget( vl, fieldIdx, parent )
28 
29 {
30  setupUi( this );
31  connect( mAddFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mAddFilterButton_clicked );
32  connect( mRemoveFilterButton, &QToolButton::clicked, this, &QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked );
33 
34  mExpressionWidget->registerExpressionContextGenerator( vl );
35 
36  connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRelationReferenceConfigDlg::relationChanged );
37 
38  const auto constReferencingRelations = vl->referencingRelations( fieldIdx );
39  for ( const QgsRelation &relation : constReferencingRelations )
40  {
41  if ( relation.name().isEmpty() )
42  mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.id(), relation.referencedLayerId() ), relation.id() );
43  else
44  mComboRelation->addItem( QStringLiteral( "%1 (%2)" ).arg( relation.name(), relation.referencedLayerId() ), relation.id() );
45  if ( auto *lReferencedLayer = relation.referencedLayer() )
46  {
47  mExpressionWidget->setField( lReferencedLayer->displayExpression() );
48  }
49  }
50 
51  connect( mCbxAllowNull, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
52  connect( mCbxOrderByValue, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
53  connect( mCbxShowForm, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
54  connect( mCbxShowOpenFormButton, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
55  connect( mCbxMapIdentification, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
56  connect( mCbxReadOnly, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
57  connect( mComboRelation, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
58  connect( mCbxAllowAddFeatures, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
59  connect( mFilterGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
60  connect( mFilterFieldsList, &QListWidget::itemChanged, this, &QgsEditorConfigWidget::changed );
61  connect( mCbxChainFilters, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
62  connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsEditorConfigWidget::changed );
63  connect( mEditExpression, &QAbstractButton::clicked, this, &QgsRelationReferenceConfigDlg::mEditExpression_clicked );
64  connect( mFilterExpression, &QTextEdit::textChanged, this, &QgsEditorConfigWidget::changed );
65 }
66 
67 void QgsRelationReferenceConfigDlg::mEditExpression_clicked()
68 {
69  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer() );
70  if ( !vl )
71  return;
72 
76 
77  context.setHighlightedFunctions( QStringList() << QStringLiteral( "current_value" ) << QStringLiteral( "current_parent_value" ) );
78  context.setHighlightedVariables( QStringList() << QStringLiteral( "current_geometry" )
79  << QStringLiteral( "current_feature" )
80  << QStringLiteral( "form_mode" )
81  << QStringLiteral( "current_parent_geometry" )
82  << QStringLiteral( "current_parent_feature" ) );
83 
84  QgsExpressionBuilderDialog dlg( vl, mFilterExpression->toPlainText(), this, QStringLiteral( "generic" ), context );
85  dlg.setWindowTitle( tr( "Edit Filter Expression" ) );
86 
87  if ( dlg.exec() == QDialog::Accepted )
88  {
89  mFilterExpression->setPlainText( dlg.expressionBuilder()->expressionText() );
90  }
91 }
92 
93 void QgsRelationReferenceConfigDlg::setConfig( const QVariantMap &config )
94 {
95  mCbxAllowNull->setChecked( config.value( QStringLiteral( "AllowNULL" ), false ).toBool() );
96  mCbxOrderByValue->setChecked( config.value( QStringLiteral( "OrderByValue" ), false ).toBool() );
97  mCbxShowForm->setChecked( config.value( QStringLiteral( "ShowForm" ), false ).toBool() );
98  mCbxShowOpenFormButton->setChecked( config.value( QStringLiteral( "ShowOpenFormButton" ), true ).toBool() );
99 
100  if ( config.contains( QStringLiteral( "Relation" ) ) )
101  {
102  mComboRelation->setCurrentIndex( mComboRelation->findData( config.value( QStringLiteral( "Relation" ) ).toString() ) );
103  relationChanged( mComboRelation->currentIndex() );
104  }
105 
106  mCbxMapIdentification->setChecked( config.value( QStringLiteral( "MapIdentification" ), false ).toBool() );
107  mCbxAllowAddFeatures->setChecked( config.value( QStringLiteral( "AllowAddFeatures" ), false ).toBool() );
108  mCbxReadOnly->setChecked( config.value( QStringLiteral( "ReadOnly" ), false ).toBool() );
109  mFilterExpression->setPlainText( config.value( QStringLiteral( "FilterExpression" ) ).toString() );
110 
111  if ( config.contains( QStringLiteral( "FilterFields" ) ) )
112  {
113  mFilterGroupBox->setChecked( true );
114  const auto constToStringList = config.value( "FilterFields" ).toStringList();
115  for ( const QString &fld : constToStringList )
116  {
117  addFilterField( fld );
118  }
119 
120  mCbxChainFilters->setChecked( config.value( QStringLiteral( "ChainFilters" ) ).toBool() );
121  }
122 }
123 
124 void QgsRelationReferenceConfigDlg::relationChanged( int idx )
125 {
126  QString relName = mComboRelation->itemData( idx ).toString();
128 
129  mReferencedLayer = rel.referencedLayer();
130  mExpressionWidget->setLayer( mReferencedLayer ); // set even if 0
131  if ( mReferencedLayer )
132  {
133  mExpressionWidget->setField( mReferencedLayer->displayExpression() );
134  mCbxMapIdentification->setEnabled( mReferencedLayer->isSpatial() );
135  }
136 
137  loadFields();
138 }
139 
140 void QgsRelationReferenceConfigDlg::mAddFilterButton_clicked()
141 {
142  const auto constSelectedItems = mAvailableFieldsList->selectedItems();
143  for ( QListWidgetItem *item : constSelectedItems )
144  {
145  addFilterField( item );
146  }
147 }
148 
149 void QgsRelationReferenceConfigDlg::mRemoveFilterButton_clicked()
150 {
151  const auto constSelectedItems = mFilterFieldsList->selectedItems();
152  for ( QListWidgetItem *item : constSelectedItems )
153  {
154  mFilterFieldsList->takeItem( indexFromListWidgetItem( item ) );
155  mAvailableFieldsList->addItem( item );
156  }
157 }
158 
160 {
161  QVariantMap myConfig;
162  myConfig.insert( QStringLiteral( "AllowNULL" ), mCbxAllowNull->isChecked() );
163  myConfig.insert( QStringLiteral( "OrderByValue" ), mCbxOrderByValue->isChecked() );
164  myConfig.insert( QStringLiteral( "ShowForm" ), mCbxShowForm->isChecked() );
165  myConfig.insert( QStringLiteral( "ShowOpenFormButton" ), mCbxShowOpenFormButton->isChecked() );
166  myConfig.insert( QStringLiteral( "MapIdentification" ), mCbxMapIdentification->isEnabled() && mCbxMapIdentification->isChecked() );
167  myConfig.insert( QStringLiteral( "ReadOnly" ), mCbxReadOnly->isChecked() );
168  myConfig.insert( QStringLiteral( "Relation" ), mComboRelation->currentData() );
169  myConfig.insert( QStringLiteral( "AllowAddFeatures" ), mCbxAllowAddFeatures->isChecked() );
170 
171  if ( mFilterGroupBox->isChecked() )
172  {
173  QStringList filterFields;
174  filterFields.reserve( mFilterFieldsList->count() );
175  for ( int i = 0; i < mFilterFieldsList->count(); i++ )
176  {
177  filterFields << mFilterFieldsList->item( i )->data( Qt::UserRole ).toString();
178  }
179  myConfig.insert( QStringLiteral( "FilterFields" ), filterFields );
180 
181  myConfig.insert( QStringLiteral( "ChainFilters" ), mCbxChainFilters->isChecked() );
182  myConfig.insert( QStringLiteral( "FilterExpression" ), mFilterExpression->toPlainText() );
183  }
184 
185  if ( mReferencedLayer )
186  {
187  // Store referenced layer data source and provider
188  myConfig.insert( QStringLiteral( "ReferencedLayerDataSource" ), mReferencedLayer->publicSource() );
189  myConfig.insert( QStringLiteral( "ReferencedLayerProviderKey" ), mReferencedLayer->providerType() );
190  myConfig.insert( QStringLiteral( "ReferencedLayerId" ), mReferencedLayer->id() );
191  myConfig.insert( QStringLiteral( "ReferencedLayerName" ), mReferencedLayer->name() );
192  mReferencedLayer->setDisplayExpression( mExpressionWidget->currentField() );
193  }
194 
195  return myConfig;
196 }
197 
198 void QgsRelationReferenceConfigDlg::loadFields()
199 {
200  mAvailableFieldsList->clear();
201  mFilterFieldsList->clear();
202 
203  if ( mReferencedLayer )
204  {
205  QgsVectorLayer *l = mReferencedLayer;
206  const QgsFields &flds = l->fields();
207  for ( int i = 0; i < flds.count(); i++ )
208  {
209  mAvailableFieldsList->addItem( flds.at( i ).displayName() );
210  mAvailableFieldsList->item( mAvailableFieldsList->count() - 1 )->setData( Qt::UserRole, flds.at( i ).name() );
211  }
212  }
213 }
214 
215 void QgsRelationReferenceConfigDlg::addFilterField( const QString &field )
216 {
217  for ( int i = 0; i < mAvailableFieldsList->count(); i++ )
218  {
219  if ( mAvailableFieldsList->item( i )->data( Qt::UserRole ).toString() == field )
220  {
221  addFilterField( mAvailableFieldsList->item( i ) );
222  break;
223  }
224  }
225 }
226 
227 void QgsRelationReferenceConfigDlg::addFilterField( QListWidgetItem *item )
228 {
229  mAvailableFieldsList->takeItem( indexFromListWidgetItem( item ) );
230  mFilterFieldsList->addItem( item );
231 }
232 
233 int QgsRelationReferenceConfigDlg::indexFromListWidgetItem( QListWidgetItem *item )
234 {
235  QListWidget *lw = item->listWidget();
236 
237  for ( int i = 0; i < lw->count(); i++ )
238  {
239  if ( lw->item( i ) == item )
240  return i;
241  }
242 
243  return -1;
244 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsProject::relationManager
QgsRelationManager * relationManager
Definition: qgsproject.h:105
qgsfields.h
qgsexpressioncontextutils.h
QgsEditorConfigWidget
This class should be subclassed for every configurable editor widget type.
Definition: qgseditorconfigwidget.h:39
QgsExpressionContextUtils::formScope
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...
Definition: qgsexpressioncontextutils.cpp:201
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsRelationManager::relation
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Definition: qgsrelationmanager.cpp:96
QgsVectorLayer::isSpatial
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Definition: qgsvectorlayer.cpp:3599
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:307
field
const QgsField & field
Definition: qgsfield.h:456
QgsField::name
QString name
Definition: qgsfield.h:59
QgsMapLayer::providerType
QString providerType() const
Returns the provider type (provider key) for this layer.
Definition: qgsmaplayer.cpp:1617
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsEditorConfigWidget::field
int field()
Returns the field for which this configuration widget applies.
Definition: qgseditorconfigwidget.cpp:28
QgsEditorConfigWidget::layer
QgsVectorLayer * layer()
Returns the layer for which this configuration widget applies.
Definition: qgseditorconfigwidget.cpp:33
QgsExpressionBuilderDialog
A generic dialog for building expression strings.
Definition: qgsexpressionbuilderdialog.h:31
QgsRelation::referencedLayer
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:47
QgsFieldExpressionWidget::fieldChanged
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QgsExpressionContextUtils::parentFormScope
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...
Definition: qgsexpressioncontextutils.cpp:212
QgsVectorLayer::referencingRelations
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
Definition: qgsvectorlayer.cpp:5177
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:148
QgsRelationReferenceConfigDlg::setConfig
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
Definition: qgsrelationreferenceconfigdlg.cpp:93
QgsVectorLayer::setDisplayExpression
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
Definition: qgsvectorlayer.cpp:3533
qgsrelationmanager.h
qgsvectorlayer.h
QgsMapLayer::publicSource
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
Definition: qgsmaplayer.cpp:184
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
qgseditorwidgetfactory.h
QgsRelationReferenceConfigDlg::config
QVariantMap config() override
Create a configuration from the current GUI state.
Definition: qgsrelationreferenceconfigdlg.cpp:159
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:86
QgsRelation
Definition: qgsrelation.h:42
QgsEditorConfigWidget::changed
void changed()
Emitted when the configuration of the widget is changed.
QgsField::displayName
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:88
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsVectorLayer::displayExpression
QString displayExpression
Definition: qgsvectorlayer.h:391
QgsFieldExpressionWidget
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
Definition: qgsfieldexpressionwidget.h:47
qgsrelationreferenceconfigdlg.h
qgsproject.h
QgsRelationReferenceConfigDlg::QgsRelationReferenceConfigDlg
QgsRelationReferenceConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent)
Definition: qgsrelationreferenceconfigdlg.cpp:26
qgsexpressionbuilderdialog.h