QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsvaluerelationwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvaluerelationwidgetwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 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 "qgis.h"
19 #include "qgsfields.h"
20 #include "qgsproject.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsfilterlineedit.h"
24 #include "qgsfeatureiterator.h"
26 #include "qgsattributeform.h"
27 #include "qgsattributes.h"
28 #include "qgsjsonutils.h"
29 #include "qgspostgresstringutils.h"
30 #include "qgsapplication.h"
31 
32 #include <QHeaderView>
33 #include <QComboBox>
34 #include <QLineEdit>
35 #include <QTableWidget>
36 #include <QStringListModel>
37 #include <QCompleter>
38 #include <QTimer>
39 
40 #include <nlohmann/json.hpp>
41 using namespace nlohmann;
42 
43 
44 QgsValueRelationWidgetWrapper::QgsValueRelationWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent )
45  : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
46 {
47 }
48 
49 
51 {
52  QVariant v;
53 
54  if ( mComboBox )
55  {
56  int cbxIdx = mComboBox->currentIndex();
57  if ( cbxIdx > -1 )
58  {
59  v = mComboBox->currentData();
60  if ( v.isNull() )
61  v = QVariant( field().type() );
62  }
63  }
64  else if ( mTableWidget )
65  {
66  const int nofColumns = columnCount();
67  QStringList selection;
68  for ( int j = 0; j < mTableWidget->rowCount(); j++ )
69  {
70  for ( int i = 0; i < nofColumns; ++i )
71  {
72  QTableWidgetItem *item = mTableWidget->item( j, i );
73  if ( item )
74  {
75  if ( item->checkState() == Qt::Checked )
76  selection << item->data( Qt::UserRole ).toString();
77  }
78  }
79  }
80 
81  // If there is no selection and allow NULL is not checked return NULL.
82  if ( selection.isEmpty() && ! config( QStringLiteral( "AllowNull" ) ).toBool( ) )
83  {
84  return QVariant( QVariant::Type::List );
85  }
86 
87  QVariantList vl;
88  //store as QVariantList because the field type supports data structure
89  for ( const QString &s : std::as_const( selection ) )
90  {
91  // Convert to proper type
92  const QVariant::Type type { fkType() };
93  switch ( type )
94  {
95  case QVariant::Type::Int:
96  vl.push_back( s.toInt() );
97  break;
98  case QVariant::Type::LongLong:
99  vl.push_back( s.toLongLong() );
100  break;
101  default:
102  vl.push_back( s );
103  break;
104  }
105  }
106 
107  if ( layer()->fields().at( fieldIdx() ).type() == QVariant::Map ||
108  layer()->fields().at( fieldIdx() ).type() == QVariant::List )
109  {
110  v = vl;
111  }
112  else
113  {
114  //make string
116  }
117  }
118  else if ( mLineEdit )
119  {
120  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &item : std::as_const( mCache ) )
121  {
122  if ( item.value == mLineEdit->text() )
123  {
124  v = item.key;
125  break;
126  }
127  }
128  }
129 
130  return v;
131 }
132 
134 {
135  QgsAttributeForm *form = qobject_cast<QgsAttributeForm *>( parent );
136  if ( form )
138 
139  mExpression = config().value( QStringLiteral( "FilterExpression" ) ).toString();
140 
141  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
142  {
143  return new QTableWidget( parent );
144  }
145  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
146  {
147  return new QgsFilterLineEdit( parent );
148  }
149  else
150  {
151  return new QComboBox( parent );
152  }
153 }
154 
156 {
157 
158  mComboBox = qobject_cast<QComboBox *>( editor );
159  mTableWidget = qobject_cast<QTableWidget *>( editor );
160  mLineEdit = qobject_cast<QLineEdit *>( editor );
161 
162  // Read current initial form values from the editor context
164 
165  if ( mComboBox )
166  {
167  mComboBox->view()->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
168  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
169  this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::emitValueChanged ), Qt::UniqueConnection );
170  }
171  else if ( mTableWidget )
172  {
173  mTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
174  mTableWidget->horizontalHeader()->setVisible( false );
175  mTableWidget->verticalHeader()->setSectionResizeMode( QHeaderView::Stretch );
176  mTableWidget->verticalHeader()->setVisible( false );
177  mTableWidget->setShowGrid( false );
178  mTableWidget->setEditTriggers( QAbstractItemView::NoEditTriggers );
179  mTableWidget->setSelectionMode( QAbstractItemView::NoSelection );
180  connect( mTableWidget, &QTableWidget::itemChanged, this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::emitValueChanged ), Qt::UniqueConnection );
181  }
182  else if ( mLineEdit )
183  {
184  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsValueRelationWidgetWrapper::emitValueChangedInternal, Qt::UniqueConnection );
185  }
186 }
187 
189 {
190  return mTableWidget || mLineEdit || mComboBox;
191 }
192 
193 void QgsValueRelationWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
194 {
195  if ( mTableWidget )
196  {
197  QStringList checkList;
198 
199  if ( layer()->fields().at( fieldIdx() ).type() == QVariant::Map ||
200  layer()->fields().at( fieldIdx() ).type() == QVariant::List )
201  {
202  checkList = value.toStringList();
203  }
204  else
205  {
207  }
208 
209  QTableWidgetItem *lastChangedItem = nullptr;
210 
211  const int nofColumns = columnCount();
212 
213  // This block is needed because item->setCheckState triggers dataChanged gets back to value()
214  // and iterate over all items again! This can be extremely slow on large items sets.
215  for ( int j = 0; j < mTableWidget->rowCount(); j++ )
216  {
217  auto signalBlockedTableWidget = whileBlocking( mTableWidget );
218  Q_UNUSED( signalBlockedTableWidget )
219 
220  for ( int i = 0; i < nofColumns; ++i )
221  {
222  QTableWidgetItem *item = mTableWidget->item( j, i );
223  if ( item )
224  {
225  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
226  //re-set enabled state because it's lost after reloading items
227  item->setFlags( mEnabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
228  lastChangedItem = item;
229  }
230  }
231  }
232  // let's trigger the signal now, once and for all
233  if ( lastChangedItem )
234  lastChangedItem->setCheckState( checkList.contains( lastChangedItem->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
235 
236  }
237  else if ( mComboBox )
238  {
239  // findData fails to tell a 0 from a NULL
240  // See: "Value relation, value 0 = NULL" - https://github.com/qgis/QGIS/issues/27803
241  int idx = -1; // default to not found
242  for ( int i = 0; i < mComboBox->count(); i++ )
243  {
244  QVariant v( mComboBox->itemData( i ) );
245  if ( qgsVariantEqual( v, value ) )
246  {
247  idx = i;
248  break;
249  }
250  }
251 
252  if ( idx == -1 )
253  {
254  // if value doesn't exist, we show it in '(...)' (just like value map widget)
255  if ( value.isNull( ) )
256  {
257  mComboBox->setCurrentIndex( -1 );
258  }
259  else
260  {
261  mComboBox->addItem( value.toString().prepend( '(' ).append( ')' ), value );
262  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
263  }
264  }
265  else
266  {
267  mComboBox->setCurrentIndex( idx );
268  }
269  }
270  else if ( mLineEdit )
271  {
272  mLineEdit->clear();
273  bool wasFound { false };
274  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &i : std::as_const( mCache ) )
275  {
276  if ( i.key == value )
277  {
278  mLineEdit->setText( i.value );
279  wasFound = true;
280  break;
281  }
282  }
283  // Value could not be found
284  if ( ! wasFound )
285  {
286  mLineEdit->setText( tr( "(no selection)" ) );
287  }
288  }
289 }
290 
291 void QgsValueRelationWidgetWrapper::widgetValueChanged( const QString &attribute, const QVariant &newValue, bool attributeChanged )
292 {
293 
294  // Do nothing if the value has not changed
295  if ( attributeChanged )
296  {
297  QVariant oldValue( value( ) );
298  setFormFeatureAttribute( attribute, newValue );
299  // Update combos if the value used in the filter expression has changed
301  && QgsValueRelationFieldFormatter::expressionFormAttributes( mExpression ).contains( attribute ) )
302  {
303  populate();
304  // Restore value
305  updateValues( value( ) );
306  // If the value has changed as a result of another widget's value change,
307  // we need to emit the signal to make sure other dependent widgets are
308  // updated.
309  QgsFields formFields( formFeature().fields() );
310 
311  // Also check for fields in the layer in case this is a multi-edit form
312  // and there is not form feature set
313  if ( formFields.count() == 0 && layer() )
314  {
315  formFields = layer()->fields();
316  }
317 
318  if ( oldValue != value() && fieldIdx() < formFields.count() )
319  {
320  QString attributeName( formFields.names().at( fieldIdx() ) );
321  setFormFeatureAttribute( attributeName, value( ) );
323  }
324  }
325  }
326 }
327 
328 
330 {
331  setFormFeature( feature );
332  whileBlocking( this )->populate();
333  whileBlocking( this )->setValue( feature.attribute( fieldIdx() ) );
334 
335  // As we block any signals, possible depending widgets will not being updated
336  // so we force emit signal once and for all
338 
339  // A bit of logic to set the default value if AllowNull is false and this is a new feature
340  // Note that this needs to be here after the cache has been created/updated by populate()
341  // and signals unblocked (we want this to propagate to the feature itself)
342  if ( context().attributeFormMode() != QgsAttributeEditorContext::Mode::MultiEditMode
343  && ! formFeature().attribute( fieldIdx() ).isValid()
344  && ! mCache.isEmpty()
345  && ! config( QStringLiteral( "AllowNull" ) ).toBool( ) )
346  {
347  // This is deferred because at the time the feature is set in one widget it is not
348  // set in the next, which is typically the "down" in a drill-down
349  QTimer::singleShot( 0, this, [ this ]
350  {
351  if ( ! mCache.isEmpty() )
352  {
353  updateValues( formFeature().attribute( fieldIdx() ).isValid() ? formFeature().attribute( fieldIdx() ) : mCache.at( 0 ).key );
354  }
355  } );
356  }
357 }
358 
359 int QgsValueRelationWidgetWrapper::columnCount() const
360 {
361  return std::max( 1, config( QStringLiteral( "NofColumns" ) ).toInt() );
362 }
363 
364 
365 QVariant::Type QgsValueRelationWidgetWrapper::fkType() const
366 {
368  if ( layer )
369  {
370  QgsFields fields = layer->fields();
371  int idx { fields.lookupField( config().value( QStringLiteral( "Key" ) ).toString() ) };
372  if ( idx >= 0 )
373  {
374  return fields.at( idx ).type();
375  }
376  }
377  return QVariant::Type::Invalid;
378 }
379 
380 void QgsValueRelationWidgetWrapper::populate( )
381 {
382  // Initialize, note that signals are blocked, to avoid double signals on new features
385  {
386  if ( context().parentFormFeature().isValid() )
387  {
388  mCache = QgsValueRelationFieldFormatter::createCache( config(), formFeature(), context().parentFormFeature() );
389  }
390  else
391  {
393  }
394  }
395  else if ( mCache.empty() )
396  {
398  }
399 
400  if ( mComboBox )
401  {
402  mComboBox->clear();
403  if ( config( QStringLiteral( "AllowNull" ) ).toBool( ) )
404  {
405  whileBlocking( mComboBox )->addItem( tr( "(no selection)" ), QVariant( field().type( ) ) );
406  }
407 
408  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &element : std::as_const( mCache ) )
409  {
410  whileBlocking( mComboBox )->addItem( element.value, element.key );
411  if ( !element.description.isEmpty() )
412  mComboBox->setItemData( mComboBox->count() - 1, element.description, Qt::ToolTipRole );
413  }
414 
415  }
416  else if ( mTableWidget )
417  {
418  const int nofColumns = columnCount();
419 
420  if ( ! mCache.empty() )
421  {
422  mTableWidget->setRowCount( ( mCache.size() + nofColumns - 1 ) / nofColumns );
423  }
424  else
425  mTableWidget->setRowCount( 1 );
426  mTableWidget->setColumnCount( nofColumns );
427 
428  whileBlocking( mTableWidget )->clear();
429  int row = 0;
430  int column = 0;
431  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &element : std::as_const( mCache ) )
432  {
433  if ( column == nofColumns )
434  {
435  row++;
436  column = 0;
437  }
438  QTableWidgetItem *item = nullptr;
439  item = new QTableWidgetItem( element.value );
440  item->setData( Qt::UserRole, element.key );
441  whileBlocking( mTableWidget )->setItem( row, column, item );
442  column++;
443  }
444 
445  }
446  else if ( mLineEdit )
447  {
448  QStringList values;
449  values.reserve( mCache.size() );
450  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &i : std::as_const( mCache ) )
451  {
452  values << i.value;
453  }
454  QStringListModel *m = new QStringListModel( values, mLineEdit );
455  QCompleter *completer = new QCompleter( m, mLineEdit );
456  completer->setCaseSensitivity( Qt::CaseInsensitive );
457  mLineEdit->setCompleter( completer );
458  }
459 }
460 
462 {
463  const int nofColumns = columnCount();
464 
465  if ( mTableWidget )
466  {
467  for ( int j = 0; j < mTableWidget->rowCount(); j++ )
468  {
469  for ( int i = 0; i < nofColumns; ++i )
470  {
471  whileBlocking( mTableWidget )->item( j, i )->setCheckState( Qt::PartiallyChecked );
472  }
473  }
474  }
475  else if ( mComboBox )
476  {
477  whileBlocking( mComboBox )->setCurrentIndex( -1 );
478  }
479  else if ( mLineEdit )
480  {
481  whileBlocking( mLineEdit )->clear();
482  }
483 }
484 
486 {
487  if ( mEnabled == enabled )
488  return;
489 
490  mEnabled = enabled;
491 
492  if ( mTableWidget )
493  {
494  auto signalBlockedTableWidget = whileBlocking( mTableWidget );
495  Q_UNUSED( signalBlockedTableWidget )
496 
497  for ( int j = 0; j < mTableWidget->rowCount(); j++ )
498  {
499  for ( int i = 0; i < mTableWidget->columnCount(); ++i )
500  {
501  QTableWidgetItem *item = mTableWidget->item( j, i );
502  if ( item )
503  {
504  item->setFlags( enabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
505  }
506  }
507  }
508  }
509  else
511 }
512 
513 void QgsValueRelationWidgetWrapper::parentFormValueChanged( const QString &attribute, const QVariant &value )
514 {
515 
516  // Update the parent feature in the context ( which means to replace the whole context :/ )
518  QgsFeature feature { context().parentFormFeature() };
519  feature.setAttribute( attribute, value );
520  ctx.setParentFormFeature( feature );
521  setContext( ctx );
522 
523  // Check if the change might affect the filter expression and the cache needs updates
525  && ( config( QStringLiteral( "Value" ) ).toString() == attribute ||
526  config( QStringLiteral( "Key" ) ).toString() == attribute ||
528  QgsValueRelationFieldFormatter::expressionParentFormAttributes( mExpression ).contains( attribute ) ) )
529  {
530  populate();
531  }
532 
533 }
534 
535 void QgsValueRelationWidgetWrapper::emitValueChangedInternal( const QString &value )
536 {
538  emit valueChanged( value );
540  emit valuesChanged( value );
541 }
qgsfields.h
QgsPostgresStringUtils::buildArray
static QString buildArray(const QVariantList &list)
Build a postgres array like formatted list in a string from a QVariantList.
Definition: qgspostgresstringutils.cpp:122
qgsvaluerelationfieldformatter.h
qgsattributeform.h
QgsValueRelationFieldFormatter::valueToStringList
static QStringList valueToStringList(const QVariant &value)
Utility to convert a list or a string representation of an (hstore style: {1,2...}) list in value to ...
Definition: qgsvaluerelationfieldformatter.cpp:228
qgspostgresstringutils.h
QgsEditorWidgetWrapper::setFormFeatureAttribute
bool setFormFeatureAttribute(const QString &attributeName, const QVariant &attributeValue)
Update the feature currently being edited by changing its attribute attributeName to attributeValue.
Definition: qgseditorwidgetwrapper.cpp:130
QgsValueRelationWidgetWrapper::value
QVariant value() const override
Will be used to access the widget's value.
Definition: qgsvaluerelationwidgetwrapper.cpp:50
QgsValueRelationWidgetWrapper::setFeature
void setFeature(const QgsFeature &feature) override
Will be called when the feature changes.
Definition: qgsvaluerelationwidgetwrapper.cpp:329
qgsfeatureiterator.h
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
qgsfilterlineedit.h
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:39
qgis.h
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsValueRelationFieldFormatter::expressionParentFormVariables
static QSet< QString > expressionParentFormVariables(const QString &expression)
Returns a list of variables required by the parent form's form context expression.
Definition: qgsvaluerelationfieldformatter.cpp:300
QgsValueRelationWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsvaluerelationwidgetwrapper.cpp:188
QgsValueRelationFieldFormatter::expressionRequiresParentFormScope
static bool expressionRequiresParentFormScope(const QString &expression)
Check if the expression requires a parent form scope (i.e.
Definition: qgsvaluerelationfieldformatter.cpp:314
QgsValueRelationFieldFormatter::expressionFormAttributes
static QSet< QString > expressionFormAttributes(const QString &expression)
Returns a list of attributes required by the form context expression.
Definition: qgsvaluerelationfieldformatter.cpp:344
QgsValueRelationWidgetWrapper::showIndeterminateState
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
Definition: qgsvaluerelationwidgetwrapper.cpp:461
QgsWidgetWrapper::context
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
Definition: qgswidgetwrapper.cpp:87
QgsEditorWidgetWrapper
Manages an editor widget Widget and wrapper share the same parent.
Definition: qgseditorwidgetwrapper.h:47
QgsValueRelationWidgetWrapper::widgetValueChanged
void widgetValueChanged(const QString &attribute, const QVariant &newValue, bool attributeChanged)
Will be called when a value in the current edited form or table row changes.
Definition: qgsvaluerelationwidgetwrapper.cpp:291
QgsEditorWidgetWrapper::fieldIdx
int fieldIdx() const
Access the field index.
Definition: qgseditorwidgetwrapper.cpp:34
qgsapplication.h
QgsEditorWidgetWrapper::valueChanged
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
QgsWidgetWrapper::layer
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Definition: qgswidgetwrapper.cpp:92
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsValueRelationWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsvaluerelationwidgetwrapper.cpp:155
QgsEditorWidgetWrapper::field
QgsField field() const
Access the field.
Definition: qgseditorwidgetwrapper.cpp:39
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
QgsEditorWidgetWrapper::emitValueChanged
void emitValueChanged()
Will call the value() method to determine the emitted value.
Definition: qgseditorwidgetwrapper.cpp:91
QgsAttributeEditorContext::parentFormFeature
QgsFeature parentFormFeature() const
Returns the feature of the currently edited parent form in its actual state.
Definition: qgsattributeeditorcontext.h:251
qgsvaluerelationwidgetwrapper.h
QgsValueRelationFieldFormatter::resolveLayer
static QgsVectorLayer * resolveLayer(const QVariantMap &config, const QgsProject *project)
Returns the (possibly NULL) layer from the widget's config and project.
Definition: qgsvaluerelationfieldformatter.cpp:397
qgsvectorlayer.h
QgsEditorWidgetWrapper::setFormFeature
void setFormFeature(const QgsFeature &feature)
Set the feature currently being edited to feature.
Definition: qgseditorwidgetwrapper.h:353
QgsFeature::setAttribute
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:262
QgsEditorWidgetWrapper::valuesChanged
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
QgsValueRelationWidgetWrapper::parentFormValueChanged
void parentFormValueChanged(const QString &attribute, const QVariant &value) override
Definition: qgsvaluerelationwidgetwrapper.cpp:513
qgsattributes.h
QgsValueRelationWidgetWrapper::setEnabled
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
Definition: qgsvaluerelationwidgetwrapper.cpp:485
QgsWidgetWrapper::config
QVariantMap config() const
Returns the whole config.
Definition: qgswidgetwrapper.cpp:82
qgsVariantEqual
bool qgsVariantEqual(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether they are equal, two NULL values are always treated a...
Definition: qgis.cpp:266
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsValueRelationFieldFormatter::createCache
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
Definition: qgsvaluerelationfieldformatter.cpp:116
QgsValueRelationWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsvaluerelationwidgetwrapper.cpp:133
QgsEditorWidgetWrapper::setEnabled
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
Definition: qgseditorwidgetwrapper.cpp:60
QgsValueRelationFieldFormatter::expressionRequiresFormScope
static bool expressionRequiresFormScope(const QString &expression)
Check if the expression requires a form scope (i.e.
Definition: qgsvaluerelationfieldformatter.cpp:309
qgsvaluerelationwidgetfactory.h
QgsAttributeForm::widgetValueChanged
void widgetValueChanged(const QString &attribute, const QVariant &value, bool attributeChanged)
Notifies about changes of attributes.
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsValueRelationWidgetWrapper::QgsValueRelationWidgetWrapper
QgsValueRelationWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr)
Constructor for QgsValueRelationWidgetWrapper.
Definition: qgsvaluerelationwidgetwrapper.cpp:44
QgsAttributeForm
Definition: qgsattributeform.h:44
QgsValueRelationFieldFormatter::expressionParentFormAttributes
static QSet< QString > expressionParentFormAttributes(const QString &expression)
Returns a list of attributes required by the parent form's form context expression.
Definition: qgsvaluerelationfieldformatter.cpp:319
qgsjsonutils.h
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsAttributeEditorContext
This class contains context information for attribute editor widgets. It will be passed to embedded w...
Definition: qgsattributeeditorcontext.h:40
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsWidgetWrapper::setContext
void setContext(const QgsAttributeEditorContext &context)
Set the context in which this widget is shown.
Definition: qgswidgetwrapper.cpp:67
QgsValueRelationFieldFormatter::ValueRelationItem
Definition: qgsvaluerelationfieldformatter.h:54
qgsproject.h
QgsField::type
QVariant::Type type
Definition: qgsfield.h:58
QgsFields::names
QStringList names() const
Returns a list with field names.
Definition: qgsfields.cpp:143
QgsEditorWidgetWrapper::formFeature
QgsFeature formFeature() const
The feature currently being edited, in its current state.
Definition: qgseditorwidgetwrapper.h:346