QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsrelationreferencewidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrelationreferencewidgetwrapper.cpp
3  --------------------------------------
4  Date : 20.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 
16 
18 #include "qgsproject.h"
19 #include "qgsrelationmanager.h"
21 
22 QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QgsMapCanvas *canvas, QgsMessageBar *messageBar, QWidget *parent )
23  : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
24  , mCanvas( canvas )
25  , mMessageBar( messageBar )
26  , mIndeterminateState( false )
27 {
28 }
29 
31 {
33  return w;
34 }
35 
37 {
38  QgsRelationReferenceWidget *w = qobject_cast<QgsRelationReferenceWidget *>( editor );
39  if ( !w )
40  {
41  w = new QgsRelationReferenceWidget( editor );
42  }
43 
44  mWidget = w;
45 
46  const QgsAttributeEditorContext *ctx = &context();
47 
48  mWidget->setEditorContext( *ctx, mCanvas, mMessageBar );
49 
50  bool showForm = config( QStringLiteral( "ShowForm" ), false ).toBool();
51  bool mapIdent = config( QStringLiteral( "MapIdentification" ), false ).toBool();
52  bool readOnlyWidget = config( QStringLiteral( "ReadOnly" ), false ).toBool();
53  bool orderByValue = config( QStringLiteral( "OrderByValue" ), false ).toBool();
54  bool showOpenFormButton = config( QStringLiteral( "ShowOpenFormButton" ), true ).toBool();
55 
56  mWidget->setEmbedForm( showForm );
57  mWidget->setReadOnlySelector( readOnlyWidget );
58  mWidget->setAllowMapIdentification( mapIdent );
59  mWidget->setOrderByValue( orderByValue );
60  mWidget->setOpenFormButtonVisible( showOpenFormButton );
61  if ( config( QStringLiteral( "FilterFields" ), QVariant() ).isValid() )
62  {
63  mWidget->setFilterFields( config( QStringLiteral( "FilterFields" ) ).toStringList() );
64  mWidget->setChainFilters( config( QStringLiteral( "ChainFilters" ) ).toBool() );
65  }
66  mWidget->setAllowAddFeatures( config( QStringLiteral( "AllowAddFeatures" ), false ).toBool() );
67 
68  const QVariant relationName = config( QStringLiteral( "Relation" ) );
69 
70  // Store relation data source and provider key
71  mWidget->setReferencedLayerDataSource( config( QStringLiteral( "ReferencedLayerDataSource" ) ).toString() );
72  mWidget->setReferencedLayerProviderKey( config( QStringLiteral( "ReferencedLayerProviderKey" ) ).toString() );
73  mWidget->setReferencedLayerId( config( QStringLiteral( "ReferencedLayerId" ) ).toString() );
74  mWidget->setReferencedLayerName( config( QStringLiteral( "ReferencedLayerName" ) ).toString() );
75 
76  QgsRelation relation; // invalid relation by default
77  if ( relationName.isValid() )
78  relation = QgsProject::instance()->relationManager()->relation( relationName.toString() );
79  if ( !relation.isValid() && !layer()->referencingRelations( fieldIdx() ).isEmpty() )
80  relation = layer()->referencingRelations( fieldIdx() )[0];
81 
82  // If this widget is already embedded by the same relation, reduce functionality
83  do
84  {
85  if ( ctx->relation().id() == relation.id() )
86  {
87  mWidget->setEmbedForm( false );
88  mWidget->setReadOnlySelector( true );
89  mWidget->setAllowMapIdentification( false );
90  mWidget->setOpenFormButtonVisible( false );
91  mWidget->setAllowAddFeatures( false );
92  break;
93  }
94  ctx = ctx->parentContext();
95  }
96  while ( ctx );
97 
98  mWidget->setRelation( relation, config( QStringLiteral( "AllowNULL" ) ).toBool() );
99 
100  connect( mWidget, &QgsRelationReferenceWidget::foreignKeysChanged, this, &QgsRelationReferenceWidgetWrapper::foreignKeysChanged );
101 }
102 
104 {
105  if ( !mWidget )
106  return QVariant( field().type() );
107 
108  const QVariantList fkeys = mWidget->foreignKeys();
109 
110  if ( fkeys.isEmpty() )
111  {
112  return QVariant( field().type() );
113  }
114  else
115  {
116  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
117  Q_ASSERT( fieldPairs.count() == fkeys.count() );
118  for ( int i = 0; i < fieldPairs.count(); i++ )
119  {
120  if ( fieldPairs.at( i ).referencingField() == field().name() )
121  return fkeys.at( i );
122  }
123  return QVariant( field().type() ); // should not happen
124  }
125 }
126 
128 {
129  return mWidget;
130 }
131 
133 {
134  if ( mWidget )
135  {
136  mWidget->showIndeterminateState();
137  }
138  mIndeterminateState = true;
139 }
140 
142 {
143  if ( !mWidget || !mWidget->relation().isValid() )
144  {
145  QVariantList values;
146  for ( int i = 0; i < mWidget->relation().fieldPairs().count(); i++ )
147  {
148  values << QVariant();
149  }
150  return values;
151  }
152  else
153  {
154  QVariantList values = mWidget->foreignKeys();
155  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
156  int fieldCount = std::min( fieldPairs.count(), values.count() );
157  for ( int i = 0; i < fieldCount; i++ )
158  {
159  if ( fieldPairs.at( i ).referencingField() == field().name() )
160  {
161  values.removeAt( i );
162  break;
163  }
164  }
165  return values;
166  }
167 }
168 
170 {
171  if ( !mWidget || !mWidget->relation().isValid() )
172  return QStringList();
173 
174  QStringList fields;
175  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
176  for ( int i = 0; i < fieldPairs.count(); i++ )
177  {
178  if ( fieldPairs.at( i ).referencingField() == field().name() )
179  continue;
180 
181  fields << fieldPairs.at( i ).referencingField();
182  }
183  return fields;
184 }
185 
186 void QgsRelationReferenceWidgetWrapper::updateValues( const QVariant &val, const QVariantList &additionalValues )
187 {
188  if ( !mWidget || ( !mIndeterminateState && val == value() && val.isNull() == value().isNull() ) )
189  return;
190 
191  mIndeterminateState = false;
192 
193  QVariantList values = additionalValues;
194  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
195  for ( int i = 0; i < fieldPairs.count(); i++ )
196  {
197  if ( fieldPairs.at( i ).referencingField() == field().name() )
198  {
199  values.insert( i, val );
200  break;
201  }
202  }
203  Q_ASSERT( values.count() == fieldPairs.count() );
204 
205  mWidget->setForeignKeys( values );
206  mWidget->setFormFeature( formFeature() );
207 }
208 
210 {
211  if ( !mWidget )
212  return;
213 
214  mWidget->setRelationEditable( enabled );
215 }
216 
217 void QgsRelationReferenceWidgetWrapper::foreignKeysChanged( const QVariantList &values )
218 {
219  QVariant mainValue = QVariant( field().type() );
220 
221  if ( !mWidget || !mWidget->relation().isValid() )
222  {
224  emit valueChanged( mainValue );
226  emit valuesChanged( mainValue );
227  return;
228  }
229 
230  QVariantList additionalValues = values;
231  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
232  for ( int i = 0; i < fieldPairs.count(); i++ )
233  {
234  if ( fieldPairs.at( i ).referencingField() == field().name() )
235  mainValue = additionalValues.takeAt( i ); // additional values in field pair order remain
236  }
237  Q_ASSERT( additionalValues.count() == values.count() - 1 );
238 
240  emit valueChanged( mainValue );
242  emit valuesChanged( mainValue, additionalValues );
243 }
244 
246 {
247  if ( mWidget )
248  {
249  if ( !constraintResultVisible() )
250  {
251  widget()->setStyleSheet( QString() );
252  }
253  else
254  {
255  switch ( constraintResult() )
256  {
258  mWidget->setStyleSheet( QString() );
259  break;
260 
262  mWidget->setStyleSheet( QStringLiteral( ".QComboBox { background-color: #dd7777; }" ) );
263  break;
264 
266  mWidget->setStyleSheet( QStringLiteral( ".QComboBox { background-color: #ffd85d; }" ) );
267  break;
268  }
269  }
270  }
271 }
QgsRelationReferenceWidget
Definition: qgsrelationreferencewidget.h:57
QgsProject::relationManager
QgsRelationManager relationManager
Definition: qgsproject.h:103
QgsRelationReferenceWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsrelationreferencewidgetwrapper.cpp:36
QgsEditorWidgetWrapper::ConstraintResultFailHard
@ ConstraintResultFailHard
Widget failed at least one hard (enforced) constraint.
Definition: qgseditorwidgetwrapper.h:63
QgsRelationReferenceWidget::setFilterFields
void setFilterFields(const QStringList &filterFields)
Sets the fields for which filter comboboxes will be created.
Definition: qgsrelationreferencewidget.cpp:473
QgsRelationReferenceWidget::showIndeterminateState
void showIndeterminateState()
Sets the widget to display in an indeterminate "mixed value" state.
Definition: qgsrelationreferencewidget.cpp:389
QgsMapCanvas
Definition: qgsmapcanvas.h:83
QgsRelationReferenceWidgetWrapper::updateConstraintWidgetStatus
void updateConstraintWidgetStatus() override
This should update the widget with a visual cue if a constraint status changed.
Definition: qgsrelationreferencewidgetwrapper.cpp:245
QgsRelationReferenceWidget::setReferencedLayerProviderKey
void setReferencedLayerProviderKey(const QString &referencedLayerProviderKey)
Set the data provider key of the referenced layer to referencedLayerProviderKey.
Definition: qgsrelationreferencewidget.cpp:1081
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsRelationManager::relation
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Definition: qgsrelationmanager.cpp:96
QgsRelationReferenceWidget::setRelationEditable
void setRelationEditable(bool editable)
Definition: qgsrelationreferencewidget.cpp:227
QgsRelationReferenceWidgetWrapper::value
QVariant value() const override
Will be used to access the widget's value.
Definition: qgsrelationreferencewidgetwrapper.cpp:103
QgsRelationReferenceWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsrelationreferencewidgetwrapper.cpp:127
QgsWidgetWrapper::context
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
Definition: qgswidgetwrapper.cpp:86
QgsEditorWidgetWrapper::constraintResultVisible
bool constraintResultVisible
Definition: qgseditorwidgetwrapper.h:51
QgsRelationReferenceWidget::setReferencedLayerName
void setReferencedLayerName(const QString &referencedLayerName)
Set the name of the referenced layer to referencedLayerName.
Definition: qgsrelationreferencewidget.cpp:1061
QgsRelationReferenceWidget::setForeignKeys
void setForeignKeys(const QVariantList &values)
Sets the related feature using the foreign keys.
Definition: qgsrelationreferencewidget.cpp:247
QgsWidgetWrapper::widget
QWidget * widget()
Access the widget managed by this wrapper.
Definition: qgswidgetwrapper.cpp:46
QgsEditorWidgetWrapper
Definition: qgseditorwidgetwrapper.h:47
QgsAttributeEditorContext::relation
const QgsRelation & relation() const
Returns the attribute relation.
Definition: qgsattributeeditorcontext.h:189
QgsEditorWidgetWrapper::fieldIdx
int fieldIdx() const
Access the field index.
Definition: qgseditorwidgetwrapper.cpp:34
QgsRelation::id
QString id
Definition: qgsrelation.h:45
QgsEditorWidgetWrapper::valueChanged
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:752
QgsRelationReferenceWidget::setAllowMapIdentification
void setAllowMapIdentification(bool allowMapIdentification)
Definition: qgsrelationreferencewidget.cpp:461
QgsEditorWidgetWrapper::ConstraintResultPass
@ ConstraintResultPass
Widget passed constraints successfully.
Definition: qgseditorwidgetwrapper.h:62
QgsRelationReferenceWidgetWrapper::showIndeterminateState
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
Definition: qgsrelationreferencewidgetwrapper.cpp:132
QgsRelationReferenceWidget::setAllowAddFeatures
void setAllowAddFeatures(bool allowAddFeatures)
Determines if a button for adding new features should be shown.
Definition: qgsrelationreferencewidget.cpp:738
QgsWidgetWrapper::layer
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Definition: qgswidgetwrapper.cpp:91
QgsRelationReferenceWidget::setEditorContext
void setEditorContext(const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar)
Sets the editor context.
Definition: qgsrelationreferencewidget.cpp:424
QgsRelationReferenceWidget::foreignKeysChanged
void foreignKeysChanged(const QVariantList &)
Emitted when the foreign keys changed.
QgsRelationReferenceWidget::setEmbedForm
void setEmbedForm(bool display)
Definition: qgsrelationreferencewidget.cpp:441
QgsRelationReferenceWidget::setReferencedLayerDataSource
void setReferencedLayerDataSource(const QString &referencedLayerDataSource)
Set the public data source of the referenced layer to referencedLayerDataSource.
Definition: qgsrelationreferencewidget.cpp:1091
QgsMessageBar
Definition: qgsmessagebar.h:60
QgsVectorLayer::referencingRelations
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
Definition: qgsvectorlayer.cpp:5158
QgsRelationReferenceWidgetWrapper::additionalFieldValues
QVariantList additionalFieldValues() const override
Will be used to access the widget's values for potential additional fields handled by the widget.
Definition: qgsrelationreferencewidgetwrapper.cpp:141
QgsEditorWidgetWrapper::field
QgsField field() const
Access the field.
Definition: qgseditorwidgetwrapper.cpp:39
QgsRelationReferenceWidgetWrapper::additionalFields
QStringList additionalFields() const override
Returns the list of additional fields which the editor handles.
Definition: qgsrelationreferencewidgetwrapper.cpp:169
qgsrelationmanager.h
QgsRelation::fieldPairs
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
Definition: qgsrelation.cpp:306
QgsRelationReferenceWidget::relation
QgsRelation relation() const
Returns the current relation, which might be invalid.
Definition: qgsrelationreferencewidget.cpp:744
QgsEditorWidgetWrapper::valuesChanged
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
QgsWidgetWrapper::config
QVariantMap config() const
Returns the whole config.
Definition: qgswidgetwrapper.cpp:81
QgsRelationReferenceWidget::foreignKeys
QVariantList foreignKeys() const
returns the related feature foreign key
Definition: qgsrelationreferencewidget.cpp:412
QgsRelationReferenceWidget::setRelation
void setRelation(const QgsRelation &relation, bool allowNullValue)
Definition: qgsrelationreferencewidget.cpp:176
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsEditorWidgetWrapper::ConstraintResultFailSoft
@ ConstraintResultFailSoft
Widget failed at least one soft (non-enforced) constraint.
Definition: qgseditorwidgetwrapper.h:64
QgsRelationReferenceWidget::setChainFilters
void setChainFilters(bool chainFilters)
Set if filters are chained.
Definition: qgsrelationreferencewidget.cpp:484
QgsRelation::isValid
bool isValid
Definition: qgsrelation.h:49
QgsRelationReferenceWidget::setOrderByValue
void setOrderByValue(bool orderByValue)
Sets if the widget will order the combobox entries by value.
Definition: qgsrelationreferencewidget.cpp:468
QgsRelationReferenceWidget::setReferencedLayerId
void setReferencedLayerId(const QString &referencedLayerId)
Set the id of the referenced layer to referencedLayerId.
Definition: qgsrelationreferencewidget.cpp:1071
QgsRelation
Definition: qgsrelation.h:41
QgsEditorWidgetWrapper::constraintResult
ConstraintResult constraintResult
Definition: qgseditorwidgetwrapper.h:52
QgsRelationReferenceWidgetWrapper::setEnabled
void setEnabled(bool enabled) override
Definition: qgsrelationreferencewidgetwrapper.cpp:209
qgsrelationreferencewidgetwrapper.h
QgsRelationReferenceWidget::setOpenFormButtonVisible
void setOpenFormButtonVisible(bool openFormButtonVisible)
Definition: qgsrelationreferencewidget.cpp:478
qgsrelationreferencewidget.h
QgsAttributeEditorContext::parentContext
const QgsAttributeEditorContext * parentContext() const
Definition: qgsattributeeditorcontext.h:229
QgsAttributeEditorContext
Definition: qgsattributeeditorcontext.h:40
QgsRelationReferenceWidgetWrapper::QgsRelationReferenceWidgetWrapper
QgsRelationReferenceWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QgsMapCanvas *canvas, QgsMessageBar *messageBar, QWidget *parent=nullptr)
Constructor for QgsRelationReferenceWidgetWrapper.
Definition: qgsrelationreferencewidgetwrapper.cpp:22
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:751
QgsRelationReferenceWidget::setReadOnlySelector
void setReadOnlySelector(bool readOnly)
Definition: qgsrelationreferencewidget.cpp:453
QgsRelationReferenceWidget::setFormFeature
void setFormFeature(const QgsFeature &formFeature)
Set the current form feature (from the referencing layer)
Definition: qgsrelationreferencewidget.cpp:1097
QgsRelationReferenceWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsrelationreferencewidgetwrapper.cpp:30
qgsproject.h
QgsEditorWidgetWrapper::formFeature
QgsFeature formFeature() const
The feature currently being edited, in its current state.
Definition: qgseditorwidgetwrapper.h:345