QGIS API Documentation  3.11.0-Master (81e645902f)
qgsattributeformeditorwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsattributeformeditorwidget.cpp
3  -------------------------------
4  Date : March 2016
5  Copyright : (C) 2016 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
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 #include "qgsattributeform.h"
18 #include "qgsmultiedittoolbutton.h"
20 #include "qgseditorwidgetwrapper.h"
21 #include "qgssearchwidgetwrapper.h"
24 #include "qgsaggregatetoolbutton.h"
25 #include "qgsgui.h"
27 #include "qgsvectorlayerutils.h"
28 
29 #include <QLayout>
30 #include <QLabel>
31 #include <QStackedWidget>
32 
34  : QgsAttributeFormWidget( editorWidget, form )
35  , mWidgetType( widgetType )
36  , mEditorWidget( editorWidget )
37  , mForm( form )
38  , mMultiEditButton( new QgsMultiEditToolButton() )
39  , mBlockValueUpdate( false )
40  , mIsMixed( false )
41  , mIsChanged( false )
42 {
43  mConstraintResultLabel = new QLabel( this );
44  mConstraintResultLabel->setObjectName( QStringLiteral( "ConstraintStatus" ) );
45  mConstraintResultLabel->setSizePolicy( QSizePolicy::Fixed, mConstraintResultLabel->sizePolicy().verticalPolicy() );
46 
47  mMultiEditButton->setField( mEditorWidget->field() );
48  mAggregateButton = new QgsAggregateToolButton();
49  mAggregateButton->setType( editorWidget->field().type() );
50  connect( mAggregateButton, &QgsAggregateToolButton::aggregateChanged, this, &QgsAttributeFormEditorWidget::onAggregateChanged );
51 
52  if ( mEditorWidget->widget() )
53  {
54  mEditorWidget->widget()->setObjectName( mEditorWidget->field().name() );
55  }
56 
57  connect( mEditorWidget, &QgsEditorWidgetWrapper::valuesChanged, this, &QgsAttributeFormEditorWidget::editorWidgetValuesChanged );
58 
59  connect( mMultiEditButton, &QgsMultiEditToolButton::resetFieldValueTriggered, this, &QgsAttributeFormEditorWidget::resetValue );
60  connect( mMultiEditButton, &QgsMultiEditToolButton::setFieldValueTriggered, this, &QgsAttributeFormEditorWidget::setFieldTriggered );
61 
62  mMultiEditButton->setField( mEditorWidget->field() );
63 
64  updateWidgets();
65 }
66 
68 {
69  //there's a chance these widgets are not currently added to the layout, so have no parent set
70  delete mMultiEditButton;
71 }
72 
74 {
75  Q_ASSERT( !mWidgetType.isEmpty() );
76  const QVariantMap config = mEditorWidget->config();
77  const int fieldIdx = mEditorWidget->fieldIdx();
78 
79  QgsSearchWidgetWrapper *sww = QgsGui::editorWidgetRegistry()->createSearchWidget( mWidgetType, layer(), fieldIdx, config,
80  searchWidgetFrame(), context );
82  searchWidgetFrame()->layout()->addWidget( mAggregateButton );
85  {
86  // create secondary widget for between type searches
87  QgsSearchWidgetWrapper *sww2 = QgsGui::editorWidgetRegistry()->createSearchWidget( mWidgetType, layer(), fieldIdx, config,
88  searchWidgetFrame(), context );
90  }
91 }
92 
93 void QgsAttributeFormEditorWidget::setConstraintStatus( const QString &constraint, const QString &description, const QString &err, QgsEditorWidgetWrapper::ConstraintResult result )
94 {
95  switch ( result )
96  {
98  mConstraintResultLabel->setText( QStringLiteral( "<font color=\"#FF9800\">%1</font>" ).arg( QChar( 0x2718 ) ) );
99  mConstraintResultLabel->setToolTip( description.isEmpty() ? QStringLiteral( "<b>%1</b>: %2" ).arg( constraint, err ) : description );
100  break;
101 
103  mConstraintResultLabel->setText( QStringLiteral( "<font color=\"#FFC107\">%1</font>" ).arg( QChar( 0x2718 ) ) );
104  mConstraintResultLabel->setToolTip( description.isEmpty() ? QStringLiteral( "<b>%1</b>: %2" ).arg( constraint, err ) : description );
105  break;
106 
108  mConstraintResultLabel->setText( QStringLiteral( "<font color=\"#259B24\">%1</font>" ).arg( QChar( 0x2714 ) ) );
109  mConstraintResultLabel->setToolTip( description );
110  break;
111  }
112 }
113 
115 {
116  mConstraintResultLabel->setHidden( !editable );
117 }
118 
120 {
121  return mEditorWidget;
122 }
123 
125 {
126  if ( mEditorWidget && mixed )
127  mEditorWidget->showIndeterminateState();
128  mMultiEditButton->setIsMixed( mixed );
129  mIsMixed = mixed;
130 }
131 
133 {
134  if ( mEditorWidget )
135  {
136  mPreviousValue = mEditorWidget->value();
137  mPreviousAdditionalValues = mEditorWidget->additionalFieldValues();
138  }
139 
140  setIsMixed( false );
141  mMultiEditButton->changesCommitted();
142  mIsChanged = false;
143 }
144 
145 
146 
147 void QgsAttributeFormEditorWidget::initialize( const QVariant &initialValue, bool mixedValues, const QVariantList &additionalFieldValues )
148 {
149  if ( mEditorWidget )
150  {
151  mBlockValueUpdate = true;
152  mEditorWidget->setValues( initialValue, additionalFieldValues );
153  mBlockValueUpdate = false;
154  }
155  mPreviousValue = initialValue;
156  mPreviousAdditionalValues = additionalFieldValues;
157  setIsMixed( mixedValues );
158  mMultiEditButton->setIsChanged( false );
159  mIsChanged = false;
160  updateWidgets();
161 }
162 
164 {
165  return mEditorWidget->value();
166 }
167 
168 
169 
170 void QgsAttributeFormEditorWidget::editorWidgetValuesChanged( const QVariant &value, const QVariantList &additionalFieldValues )
171 {
172  if ( mBlockValueUpdate )
173  return;
174 
175  mIsChanged = true;
176 
177  switch ( mode() )
178  {
179  case DefaultMode:
180  case SearchMode:
181  case AggregateSearchMode:
182  break;
183  case MultiEditMode:
184  mMultiEditButton->setIsChanged( true );
185  }
186 
188  emit valueChanged( value );
190  emit valuesChanged( value, additionalFieldValues );
191 }
192 
193 void QgsAttributeFormEditorWidget::resetValue()
194 {
195  mIsChanged = false;
196  mBlockValueUpdate = true;
197  if ( mEditorWidget )
198  mEditorWidget->setValues( mPreviousValue, mPreviousAdditionalValues );
199  mBlockValueUpdate = false;
200 
201  switch ( mode() )
202  {
203  case DefaultMode:
204  case SearchMode:
205  case AggregateSearchMode:
206  break;
207  case MultiEditMode:
208  {
209  mMultiEditButton->setIsChanged( false );
210  if ( mEditorWidget && mIsMixed )
211  mEditorWidget->showIndeterminateState();
212  break;
213  }
214  }
215 }
216 
217 void QgsAttributeFormEditorWidget::setFieldTriggered()
218 {
219  mIsChanged = true;
220 }
221 
222 void QgsAttributeFormEditorWidget::onAggregateChanged()
223 {
224  for ( QgsSearchWidgetWrapper *searchWidget : searchWidgetWrappers() )
225  searchWidget->setAggregate( mAggregateButton->aggregate() );
226 }
227 
228 void QgsAttributeFormEditorWidget::updateWidgets()
229 {
230  //first update the tool buttons
231  bool hasMultiEditButton = ( editPage()->layout()->indexOf( mMultiEditButton ) >= 0 );
232 
233  const int fieldIndex = mEditorWidget->fieldIdx();
234 
235  bool fieldReadOnly = false;
236  QgsFeature feature;
237  auto it = layer()->getSelectedFeatures();
238  while ( it.nextFeature( feature ) )
239  {
240  fieldReadOnly |= !QgsVectorLayerUtils::fieldIsEditable( layer(), fieldIndex, feature );
241  }
242 
243  if ( hasMultiEditButton )
244  {
245  if ( mode() != MultiEditMode || fieldReadOnly )
246  {
247  editPage()->layout()->removeWidget( mMultiEditButton );
248  mMultiEditButton->setParent( nullptr );
249  }
250  }
251  else
252  {
253  if ( mode() == MultiEditMode && !fieldReadOnly )
254  {
255  editPage()->layout()->addWidget( mMultiEditButton );
256  }
257  }
258 
259  switch ( mode() )
260  {
261  case DefaultMode:
262  case MultiEditMode:
263  {
264  stack()->setCurrentWidget( editPage() );
265 
266  editPage()->layout()->addWidget( mConstraintResultLabel );
267 
268  break;
269  }
270 
271  case AggregateSearchMode:
272  {
273  mAggregateButton->setVisible( true );
274  stack()->setCurrentWidget( searchPage() );
275  break;
276  }
277 
278  case SearchMode:
279  {
280  mAggregateButton->setVisible( false );
281  stack()->setCurrentWidget( searchPage() );
282  break;
283  }
284  }
285 }
Shows a search widget on a filter form.
Widget failed at least one soft (non-enforced) constraint.
QVariant config(const QString &key, const QVariant &defaultVal=QVariant()) const
Use this inside your overridden classes to access the configuration.
QString name
Definition: qgsfield.h:59
void setConstraintResultVisible(bool editable)
Set the constraint result label visible or invisible according to the layer editable status...
QgsField field() const
Access the field.
Base class for all widgets shown on a QgsAttributeForm.
This class contains context information for attribute editor widgets.
Manages an editor widget Widget and wrapper share the same parent.
void setType(QVariant::Type type)
Based on the type of underlying data, some aggregates will be available or not.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:719
Supports searching for values outside of a set range.
Widget failed at least one hard (enforced) constraint.
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
A tool button widget which is displayed next to editor widgets in attribute forms, and allows for controlling how the widget behaves and interacts with the form while in multi edit mode.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QStackedWidget * stack() const
Returns a pointer to the stacked widget managing edit and search page.
Default mode, only the editor widget is shown.
QgsAttributeFormEditorWidget(QgsEditorWidgetWrapper *editorWidget, const QString &widgetType, QgsAttributeForm *form)
Constructor for QgsAttributeFormEditorWidget.
Offers a toolbutton to choose between different aggregate functions.
QList< QgsSearchWidgetWrapper *> searchWidgetWrappers()
Returns the search widget wrapper used in this widget.
QWidget * searchPage() const
Returns a pointer to the search page widget.
void setSearchWidgetWrapper(QgsSearchWidgetWrapper *wrapper)
Sets the search widget wrapper for the widget used when the form is in search mode.
void setIsMixed(bool mixed)
Sets whether the widget should be displayed in a "mixed values" mode.
void changesCommitted()
Called when field values have been changed and field now contains all the same values.
virtual void showIndeterminateState()
Sets the widget to display in an indeterminate "mixed value" state.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories...
Definition: qgsgui.cpp:72
QWidget * editPage() const
Returns a pointer to the EDIT page widget.
Mode mode() const
Returns the current mode for the widget.
void resetFieldValueTriggered()
Emitted when the "reset to original values" option is selected.
void setIsChanged(bool changed)
Sets whether the associated field has changed.
void setValues(const QVariant &value, const QVariantList &additionalValues)
Is called, when the value of the widget or additional field values needs to be changed.
QVariant currentValue() const
Returns the current value of the attached editor widget.
QgsVectorLayer * layer()
The layer for which this widget and its form is shown.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:720
Multi edit mode, both the editor widget and a QgsMultiEditToolButton is shown.
void setField(const QgsField &field)
Sets the field associated with this button.
Widget passed constraints successfully.
ConstraintResult
Result of constraint checks.
virtual QVariantList additionalFieldValues() const
Will be used to access the widget&#39;s values for potential additional fields handled by the widget...
void addAdditionalSearchWidgetWrapper(QgsSearchWidgetWrapper *wrapper)
Adds an additional search widget wrapper.
void setIsMixed(bool mixed)
Sets whether the associated field contains mixed values.
void setFieldValueTriggered()
Emitted when the "set field value for all features" option is selected.
void setConstraintStatus(const QString &constraint, const QString &description, const QString &err, QgsEditorWidgetWrapper::ConstraintResult result)
Set the constraint status for this widget.
virtual QVariant value() const =0
Will be used to access the widget&#39;s value.
QgsEditorWidgetWrapper * editorWidget() const
Returns the editor widget wrapper.
QgsSearchWidgetWrapper * createSearchWidget(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emitted when the widget&#39;s value changes.
QWidget * widget()
Access the widget managed by this wrapper.
void changesCommitted()
Called when field values have been committed;.
void aggregateChanged()
The function name of the selected aggregate has changed.
int fieldIdx() const
Access the field index.
void createSearchWidgetWrappers(const QgsAttributeEditorContext &context=QgsAttributeEditorContext()) override
Creates the search widget wrappers for the widget used when the form is in search mode...
Embedded in a search form, show additional aggregate function toolbutton.
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues)
Emitted when the widget&#39;s value changes.
void initialize(const QVariant &initialValue, bool mixedValues=false, const QVariantList &additionalFieldValues=QVariantList())
Resets the widget to an initial value.
virtual FilterFlags supportedFlags() const
Returns filter flags supported by the search widget.
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
QVariant::Type type
Definition: qgsfield.h:57
QString aggregate() const
The function name of the selected aggregate or a Null String if none is chosen.
Supports searches between two values.
QWidget * searchWidgetFrame()
Returns the widget which should be used as a parent during construction of the search widget wrapper...