QGIS API Documentation 4.3.0-Master (16eddb2670e)
Loading...
Searching...
No Matches
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
17
18#include "qgsfields.h"
20#include "qgsvectorlayer.h"
23#include "qgsvectorlayerutils.h"
24
25#include <QString>
26#include <QTableView>
27
28#include "moc_qgseditorwidgetwrapper.cpp"
29
30using namespace Qt::StringLiterals;
31
32QgsEditorWidgetWrapper::QgsEditorWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent )
33 : QgsWidgetWrapper( vl, editor, parent )
34 , mFieldIdx( fieldIdx )
35{}
36
38{
39 return mFieldIdx;
40}
41
43{
44 QgsVectorLayer *vl = layer();
45 if ( vl && mFieldIdx < vl->fields().count() )
46 return vl->fields().at( mFieldIdx );
47 else
48 return QgsField();
49}
50
52{
53 const QString defaultValueClause = layer()->dataProvider()->defaultValueClause( mFieldIdx );
54 mDefaultValue = defaultValueClause.isEmpty() ? QVariant() : defaultValueClause;
55
56 return mDefaultValue;
57}
58
59QgsEditorWidgetWrapper *QgsEditorWidgetWrapper::fromWidget( QWidget *widget ) // cppcheck-suppress duplInheritedMember
60{
61 if ( !widget )
62 return nullptr;
63
64 return qobject_cast<QgsEditorWidgetWrapper *>( widget->property( "EWV2Wrapper" ).value<QgsWidgetWrapper *>() );
65}
66
68{
69 QWidget *wdg = widget();
70 if ( wdg )
71 {
72 wdg->setEnabled( enabled );
73 }
74}
75
77{
78 setFormFeature( feature );
79 QVariantList newAdditionalFieldValues;
80 const QStringList constAdditionalFields = additionalFields();
81 for ( const QString &fieldName : constAdditionalFields )
82 newAdditionalFieldValues << feature.attribute( fieldName );
83 setValues( feature.attribute( mFieldIdx ), newAdditionalFieldValues );
84}
85
87{
88 isRunningDeprecatedSetValue = true;
89 updateValues( value, QVariantList() );
90 isRunningDeprecatedSetValue = false;
91}
92
93void QgsEditorWidgetWrapper::setValues( const QVariant &value, const QVariantList &additionalValues )
94{
95 updateValues( value, additionalValues );
96}
97
105
106void QgsEditorWidgetWrapper::parentFormValueChanged( const QString &attribute, const QVariant &value )
107{
108 Q_UNUSED( attribute )
109 Q_UNUSED( value )
110}
111
113{
114 if ( !mConstraintResultVisible )
115 {
116 widget()->setStyleSheet( QString() );
117 }
118 else
119 {
120 switch ( mConstraintResult )
121 {
123 widget()->setStyleSheet( QString() );
124 break;
125
127 widget()->setStyleSheet(
128 u"QWidget { background-color: rgba(255, 150, 0, 0.3); } QCalendarWidget QWidget#qt_calendar_calendarview, QCalendarWidget QWidget#qt_calendar_navigationbar QWidget { color: rgb(0, 0, 0); background-color: rgba(255, 150, 0, 1); }"_s
129 );
130 break;
131
133 widget()->setStyleSheet(
134 u"QWidget { background-color: rgba(255, 200, 45, 0.3); } QCalendarWidget QWidget#qt_calendar_calendarview, QCalendarWidget QWidget#qt_calendar_navigationbar QWidget { color: rgb(0, 0, 0); background-color: rgba(255, 200, 45, 1); }"_s
135 );
136 break;
137 }
138 }
139#if QT_VERSION >= QT_VERSION_CHECK( 6, 9, 0 ) && QT_VERSION < QT_VERSION_CHECK( 6, 10, 0 )
140 widget()->style()->unpolish( widget() );
141 widget()->style()->polish( widget() );
142#endif
143}
144
145bool QgsEditorWidgetWrapper::setFormFeatureAttribute( const QString &attributeName, const QVariant &attributeValue )
146{
147 return mFormFeature.setAttribute( attributeName, attributeValue );
148}
149
150void QgsEditorWidgetWrapper::updateValues( const QVariant &value, const QVariantList &additionalValues )
151{
152 // this method should be made pure virtual in QGIS 5
153 Q_UNUSED( additionalValues );
155 // avoid infinite recursive loop
156 if ( !isRunningDeprecatedSetValue )
157 setValue( value );
159}
160
165
167{
168 return mConstraintResultVisible;
169}
170
172{
173 if ( mConstraintResultVisible == constraintResultVisible )
174 return;
175
176 mConstraintResultVisible = constraintResultVisible;
177
179
180 emit constraintResultVisibleChanged( mConstraintResultVisible );
181}
182
184{
185 updateConstraint( layer(), mFieldIdx, ft, constraintOrigin );
186}
187
189{
190 QStringList errors;
191 QStringList softErrors;
192 QStringList expressions;
193 QStringList descriptions;
194 bool toEmit( false );
195 bool hardConstraintsOk( true );
196 bool softConstraintsOk( true );
197
198 const QgsField field = layer->fields().at( index );
199 const QString expression = field.constraints().constraintExpression();
200
201 if ( ft.isValid() )
202 {
203 if ( !expression.isEmpty() )
204 {
205 expressions << expression;
206 descriptions << field.constraints().constraintDescription();
207 toEmit = true;
208 }
209
210 if ( field.constraints().constraints() & QgsFieldConstraints::ConstraintNotNull )
211 {
212 descriptions << tr( "Not NULL" );
213 if ( !expression.isEmpty() )
214 {
215 expressions << field.name() + u" IS NOT NULL"_s;
216 }
217 else
218 {
219 expressions << u"IS NOT NULL"_s;
220 }
221 toEmit = true;
222 }
223
224 if ( field.constraints().constraints() & QgsFieldConstraints::ConstraintUnique )
225 {
226 descriptions << tr( "Unique" );
227 if ( !expression.isEmpty() )
228 {
229 expressions << field.name() + u" IS UNIQUE"_s;
230 }
231 else
232 {
233 expressions << u"IS UNIQUE"_s;
234 }
235 toEmit = true;
236 }
237
238 hardConstraintsOk = QgsVectorLayerUtils::validateAttribute( layer, ft, index, errors, QgsFieldConstraints::ConstraintStrengthHard, constraintOrigin );
239
240 softConstraintsOk = QgsVectorLayerUtils::validateAttribute( layer, ft, index, softErrors, QgsFieldConstraints::ConstraintStrengthSoft, constraintOrigin );
241 errors << softErrors;
242 }
243 else // invalid feature
244 {
245 if ( !expression.isEmpty() )
246 {
247 hardConstraintsOk = true;
248 softConstraintsOk = false;
249
250 errors << u"Invalid feature"_s;
251
252 toEmit = true;
253 }
254 }
255
256 mValidConstraint = hardConstraintsOk && softConstraintsOk;
257 mIsBlockingCommit = !hardConstraintsOk;
258
259 mConstraintFailureReason = errors.join( ", "_L1 );
260
261 if ( toEmit )
262 {
263 const QString errStr = errors.isEmpty() ? tr( "Constraint checks passed" ) : mConstraintFailureReason;
264
265 const QString description = descriptions.join( ", "_L1 );
266 QString expressionDesc;
267 if ( expressions.size() > 1 )
268 expressionDesc = "( " + expressions.join( " ) AND ( "_L1 ) + " )";
269 else if ( !expressions.isEmpty() )
270 expressionDesc = expressions.at( 0 );
271
272 const ConstraintResult result = !hardConstraintsOk ? ConstraintResultFailHard : ( !softConstraintsOk ? ConstraintResultFailSoft : ConstraintResultPass );
273 //set the constraint result
274 mConstraintResult = result;
276 emit constraintStatusChanged( expressionDesc, description, errStr, result );
277 }
278}
279
288
290{
291 return mValidConstraint;
292}
293
295{
296 return mIsBlockingCommit;
297}
298
299
301{
302 return mConstraintFailureReason;
303}
304
305bool QgsEditorWidgetWrapper::isInTable( const QWidget *parent )
306{
307 if ( !parent )
308 return false;
309 if ( qobject_cast<const QTableView *>( parent ) )
310 return true;
311 return isInTable( parent->parentWidget() );
312}
313
314void QgsEditorWidgetWrapper::setHint( const QString &hintText )
315{
316 if ( QWidget *w = widget() )
317 w->setToolTip( hintText );
318}
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.
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:60
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
@ 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.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
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 dataset.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
QWidget * widget()
Access the widget managed by this wrapper.
QgsWidgetWrapper(QgsVectorLayer *vl, QWidget *editor=nullptr, QWidget *parent=nullptr)
Create a new widget wrapper.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:8379
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:8378