QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgseditorwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgseditorwidgetwrapper.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 #include "qgseditorwidgetwrapper.h"
17 #include "qgsvectorlayer.h"
18 #include "qgsvectordataprovider.h"
19 #include "qgsfields.h"
20 #include "qgsvectorlayerutils.h"
22 #include "qgsvectorlayerjoininfo.h"
23 
24 #include <QTableView>
25 
26 QgsEditorWidgetWrapper::QgsEditorWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent )
27  : QgsWidgetWrapper( vl, editor, parent )
28  , mFieldIdx( fieldIdx )
29  , mValidConstraint( true )
30  , mIsBlockingCommit( false )
31 {
32 }
33 
35 {
36  return mFieldIdx;
37 }
38 
40 {
41  QgsVectorLayer *vl = layer();
42  if ( vl && mFieldIdx < vl->fields().count() )
43  return vl->fields().at( mFieldIdx );
44  else
45  return QgsField();
46 }
47 
49 {
50  mDefaultValue = layer()->dataProvider()->defaultValueClause( mFieldIdx );
51 
52  return mDefaultValue;
53 }
54 
56 {
57  if ( !widget )
58  return nullptr;
59 
60  return qobject_cast<QgsEditorWidgetWrapper *>( widget->property( "EWV2Wrapper" ).value<QgsWidgetWrapper *>() );
61 }
62 
64 {
65  QWidget *wdg = widget();
66  if ( wdg )
67  {
68  wdg->setEnabled( enabled );
69  }
70 }
71 
73 {
74  setFormFeature( feature );
75  QVariantList newAdditionalFieldValues;
76  const QStringList constAdditionalFields = additionalFields();
77  for ( const QString &fieldName : constAdditionalFields )
78  newAdditionalFieldValues << feature.attribute( fieldName );
79  setValues( feature.attribute( mFieldIdx ), newAdditionalFieldValues );
80 }
81 
82 void QgsEditorWidgetWrapper::setValue( const QVariant &value )
83 {
84  isRunningDeprecatedSetValue = true;
85  updateValues( value, QVariantList() );
86  isRunningDeprecatedSetValue = false;
87 }
88 
89 void QgsEditorWidgetWrapper::setValues( const QVariant &value, const QVariantList &additionalValues )
90 {
91  updateValues( value, additionalValues );
92 }
93 
95 {
97  emit valueChanged( value() );
100 }
101 
102 void QgsEditorWidgetWrapper::parentFormValueChanged( const QString &attribute, const QVariant &value )
103 {
104  Q_UNUSED( attribute )
105  Q_UNUSED( value )
106 }
107 
109 {
110  if ( !mConstraintResultVisible )
111  {
112  widget()->setStyleSheet( QString() );
113  }
114  else
115  {
116  switch ( mConstraintResult )
117  {
119  widget()->setStyleSheet( QString() );
120  break;
121 
123  widget()->setStyleSheet( QStringLiteral( "background-color: rgba(255, 150, 0, 0.3);" ) );
124  break;
125 
127  widget()->setStyleSheet( QStringLiteral( "background-color: rgba(255, 200, 45, 0.3);" ) );
128  break;
129  }
130  }
131 }
132 
133 bool QgsEditorWidgetWrapper::setFormFeatureAttribute( const QString &attributeName, const QVariant &attributeValue )
134 {
135  return mFormFeature.setAttribute( attributeName, attributeValue );
136 }
137 
138 void QgsEditorWidgetWrapper::updateValues( const QVariant &value, const QVariantList &additionalValues )
139 {
140  // this method should be made pure virtual in QGIS 4
141  Q_UNUSED( additionalValues );
143  // avoid infinite recursive loop
144  if ( !isRunningDeprecatedSetValue )
145  setValue( value );
147 }
148 
150 {
151  return mConstraintResult;
152 }
153 
155 {
156  return mConstraintResultVisible;
157 }
158 
159 void QgsEditorWidgetWrapper::setConstraintResultVisible( bool constraintResultVisible )
160 {
161  if ( mConstraintResultVisible == constraintResultVisible )
162  return;
163 
164  mConstraintResultVisible = constraintResultVisible;
165 
167 
168  emit constraintResultVisibleChanged( mConstraintResultVisible );
169 }
170 
172 {
173  updateConstraint( layer(), mFieldIdx, ft, constraintOrigin );
174 }
175 
177 {
178  QStringList errors;
179  QStringList softErrors;
180  QStringList expressions;
181  QStringList descriptions;
182  bool toEmit( false );
183  bool hardConstraintsOk( true );
184  bool softConstraintsOk( true );
185 
186  const QgsField field = layer->fields().at( index );
187  const QString expression = field.constraints().constraintExpression();
188 
189  if ( ft.isValid() )
190  {
191  if ( ! expression.isEmpty() )
192  {
193  expressions << expression;
194  descriptions << field.constraints().constraintDescription();
195  toEmit = true;
196  }
197 
199  {
200  descriptions << tr( "Not NULL" );
201  if ( !expression.isEmpty() )
202  {
203  expressions << field.name() + QStringLiteral( " IS NOT NULL" );
204  }
205  else
206  {
207  expressions << QStringLiteral( "IS NOT NULL" );
208  }
209  toEmit = true;
210  }
211 
213  {
214  descriptions << tr( "Unique" );
215  if ( !expression.isEmpty() )
216  {
217  expressions << field.name() + QStringLiteral( " IS UNIQUE" );
218  }
219  else
220  {
221  expressions << QStringLiteral( "IS UNIQUE" );
222  }
223  toEmit = true;
224  }
225 
226  hardConstraintsOk = QgsVectorLayerUtils::validateAttribute( layer, ft, index, errors, QgsFieldConstraints::ConstraintStrengthHard, constraintOrigin );
227 
228  softConstraintsOk = QgsVectorLayerUtils::validateAttribute( layer, ft, index, softErrors, QgsFieldConstraints::ConstraintStrengthSoft, constraintOrigin );
229  errors << softErrors;
230  }
231  else // invalid feature
232  {
233  if ( ! expression.isEmpty() )
234  {
235  hardConstraintsOk = true;
236  softConstraintsOk = false;
237 
238  errors << QStringLiteral( "Invalid feature" );
239 
240  toEmit = true;
241  }
242  }
243 
244  mValidConstraint = hardConstraintsOk && softConstraintsOk;
245  mIsBlockingCommit = !hardConstraintsOk;
246 
247  mConstraintFailureReason = errors.join( QLatin1String( ", " ) );
248 
249  if ( toEmit )
250  {
251  const QString errStr = errors.isEmpty() ? tr( "Constraint checks passed" ) : mConstraintFailureReason;
252 
253  const QString description = descriptions.join( QLatin1String( ", " ) );
254  QString expressionDesc;
255  if ( expressions.size() > 1 )
256  expressionDesc = "( " + expressions.join( QLatin1String( " ) AND ( " ) ) + " )";
257  else if ( !expressions.isEmpty() )
258  expressionDesc = expressions.at( 0 );
259 
260  const ConstraintResult result = !hardConstraintsOk ? ConstraintResultFailHard
261  : ( !softConstraintsOk ? ConstraintResultFailSoft : ConstraintResultPass );
262  //set the constraint result
263  mConstraintResult = result;
265  emit constraintStatusChanged( expressionDesc, description, errStr, result );
266  }
267 }
268 
269 void QgsEditorWidgetWrapper::updateConstraint( QgsEditorWidgetWrapper::ConstraintResult constraintResult, const QString &constraintFailureReason )
270 {
271  mValidConstraint = constraintResult == ConstraintResultPass;
272  mIsBlockingCommit = constraintResult == ConstraintResultFailHard;
273  mConstraintFailureReason = constraintResult != ConstraintResultPass ? constraintFailureReason : QString();
274  mConstraintResult = constraintResult;
276 }
277 
279 {
280  return mValidConstraint;
281 }
282 
284 {
285  return mIsBlockingCommit;
286 }
287 
288 
290 {
291  return mConstraintFailureReason;
292 }
293 
294 bool QgsEditorWidgetWrapper::isInTable( const QWidget *parent )
295 {
296  if ( !parent ) return false;
297  if ( qobject_cast<const QTableView *>( parent ) ) return true;
298  return isInTable( parent->parentWidget() );
299 }
300 
301 void QgsEditorWidgetWrapper::setHint( const QString &hintText )
302 {
303  if ( QWidget *w = widget() )
304  w->setToolTip( hintText );
305 }
Manages an editor widget Widget and wrapper share the same parent.
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
virtual void updateConstraintWidgetStatus()
This should update the widget with a visual cue if a constraint status changed.
void setFormFeature(const QgsFeature &feature)
Set the feature currently being edited to feature.
virtual QVariant value() const =0
Will be used to access the widget's value.
virtual QVariantList additionalFieldValues() const
Will be used to access the widget's values for potential additional fields handled by the widget.
int fieldIdx() const
Access the field index.
virtual void parentFormValueChanged(const QString &attribute, const QVariant &value)
Is called in embedded form widgets when an attribute value in the parent form has changed.
QgsEditorWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr)
Create a new widget wrapper.
void setFeature(const QgsFeature &feature) override
Will be called when the feature changes.
virtual QStringList additionalFields() const
Returns the list of additional fields which the editor handles.
ConstraintResult constraintResult
void constraintResultVisibleChanged(bool visible)
Emit this signal when the constraint result visibility changed.
QString constraintFailureReason() const
Returns the reason why a constraint check has failed (or an empty string if constraint check was succ...
QVariant defaultValue() const
Access the default value of the field.
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
bool isValidConstraint() const
Gets the current constraint status.
void updateConstraint(const QgsFeature &featureContext, QgsFieldConstraints::ConstraintOrigin constraintOrigin=QgsFieldConstraints::ConstraintOriginNotSet)
Update constraint.
static bool isInTable(const QWidget *parent)
Check if the given widget or one of its parent is a QTableView.
void setValues(const QVariant &value, const QVariantList &additionalValues)
Is called when the value of the widget or additional field values needs to be changed.
bool setFormFeatureAttribute(const QString &attributeName, const QVariant &attributeValue)
Update the feature currently being edited by changing its attribute attributeName to attributeValue.
void emitValueChanged()
Will call the value() method to determine the emitted value.
virtual void setHint(const QString &hintText)
Add a hint text on the widget.
QgsField field() const
Access the field.
ConstraintResult
Result of constraint checks.
@ ConstraintResultFailSoft
Widget failed at least one soft (non-enforced) constraint.
@ ConstraintResultPass
Widget passed constraints successfully.
@ ConstraintResultFailHard
Widget failed at least one hard (enforced) constraint.
void constraintStatusChanged(const QString &constraint, const QString &desc, const QString &err, QgsEditorWidgetWrapper::ConstraintResult status)
Emit this signal when the constraint status changed.
virtual void setValue(const QVariant &value)
Is called when the value of the widget needs to be changed.
bool isBlockingCommit() const
Returns true if the widget is preventing the feature from being committed.
void setConstraintResultVisible(bool constraintResultVisible)
Sets whether the constraint result is visible.
static QgsEditorWidgetWrapper * fromWidget(QWidget *widget)
Will return a wrapper for a given widget.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:262
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:335
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
ConstraintOrigin
Origin of constraints.
QString constraintExpression() const
Returns the constraint expression for the field, if set.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
Q_GADGET Constraints constraints
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
QString name
Definition: qgsfield.h:62
QgsFieldConstraints constraints
Definition: qgsfield.h:65
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Manages an editor widget Widget and wrapper share the same parent.
QWidget * widget()
Access the widget managed by this wrapper.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:5741
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:5740