QGIS API Documentation  3.23.0-Master (dd0cd13a00)
qgsrelationreferencesearchwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrelationreferencesearchwidgetwrapper.cpp
3  ------------------------------------------
4  Date : 2016-05-25
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 
18 #include "qgsfields.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsproject.h"
23 #include "qgsrelationmanager.h"
24 #include "qgssettings.h"
25 #include "qgsapplication.h"
26 
27 #include <QStringListModel>
28 
30  : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
31  , mCanvas( canvas )
32 {
33 
34 }
35 
37 {
38  return true;
39 }
40 
42 {
43  return mExpression;
44 }
45 
47 {
48  if ( !mWidget )
49  return QVariant( );
50 
51  const QVariantList fkeys = mWidget->foreignKeys();
52 
53  if ( fkeys.isEmpty() )
54  {
55  return QVariant( );
56  }
57  else
58  {
59  const QList<QgsRelation::FieldPair> fieldPairs = mWidget->relation().fieldPairs();
60  Q_ASSERT( fieldPairs.count() == fkeys.count() );
61  for ( int i = 0; i < fieldPairs.count(); i++ )
62  {
63  if ( fieldPairs.at( i ).referencingField() == layer()->fields().at( fieldIndex() ).name() )
64  return fkeys.at( i );
65  }
66  return QVariant(); // should not happen
67  }
68 }
69 
70 QgsSearchWidgetWrapper::FilterFlags QgsRelationReferenceSearchWidgetWrapper::supportedFlags() const
71 {
72  return EqualTo | NotEqualTo | IsNull | IsNotNull;
73 }
74 
75 QgsSearchWidgetWrapper::FilterFlags QgsRelationReferenceSearchWidgetWrapper::defaultFlags() const
76 {
77  return EqualTo;
78 }
79 
80 QString QgsRelationReferenceSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
81 {
82  const QString fieldName = createFieldIdentifier();
83 
84  //clear any unsupported flags
85  flags &= supportedFlags();
86  if ( flags & IsNull )
87  return fieldName + " IS NULL";
88  if ( flags & IsNotNull )
89  return fieldName + " IS NOT NULL";
90 
91  const QVariant v = value();
92  if ( !v.isValid() )
93  return QString();
94 
95  switch ( v.type() )
96  {
97  case QVariant::Int:
98  case QVariant::UInt:
99  case QVariant::Double:
100  case QVariant::LongLong:
101  case QVariant::ULongLong:
102  {
103  if ( flags & EqualTo )
104  {
105  if ( v.isNull() )
106  return fieldName + " IS NULL";
107  return fieldName + '=' + v.toString();
108  }
109  else if ( flags & NotEqualTo )
110  {
111  if ( v.isNull() )
112  return fieldName + " IS NOT NULL";
113  return fieldName + "<>" + v.toString();
114  }
115  break;
116  }
117 
118  default:
119  {
120  if ( flags & EqualTo )
121  return fieldName + "='" + v.toString() + '\'';
122  else if ( flags & NotEqualTo )
123  return fieldName + "<>'" + v.toString() + '\'';
124  break;
125  }
126  }
127 
128  return QString();
129 }
130 
132 {
133  if ( mWidget )
134  {
135  mWidget->showIndeterminateState();
136  }
137 }
138 
140 {
141  if ( mWidget )
142  {
143  mWidget->setEnabled( enabled );
144  }
145 }
146 
148 {
149  return true;
150 }
151 
153 {
154  onValuesChanged( QVariantList() << value );
155 }
156 
157 void QgsRelationReferenceSearchWidgetWrapper::onValuesChanged( const QVariantList &values )
158 {
159  if ( values.isEmpty() )
160  {
161  clearExpression();
162  emit valueCleared();
163  }
164  else
165  {
166  const QgsSettings settings;
167  // TODO: adapt for composite keys
168  const QVariant value = values.at( 0 );
169  setExpression( value.isNull() ? QgsApplication::nullRepresentation() : value.toString() );
170  emit valueChanged();
171  }
173 }
174 
176 {
177  QString exp = expression;
178  const QString nullValue = QgsApplication::nullRepresentation();
179  const QString fieldName = layer()->fields().at( mFieldIdx ).name();
180 
181  QString str;
182  if ( exp == nullValue )
183  {
184  str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
185  }
186  else
187  {
188  str = QStringLiteral( "%1 = '%3'" )
189  .arg( QgsExpression::quotedColumnRef( fieldName ),
190  exp.replace( '\'', QLatin1String( "''" ) )
191  );
192  }
193  mExpression = str;
194 }
195 
197 {
198  return new QgsRelationReferenceWidget( parent );
199 }
200 
202 {
203  mWidget = qobject_cast<QgsRelationReferenceWidget *>( editor );
204  if ( !mWidget )
205  return;
206 
207  mWidget->setEditorContext( context(), mCanvas, nullptr );
208 
209  mWidget->setEmbedForm( false );
210  mWidget->setReadOnlySelector( false );
211  mWidget->setAllowMapIdentification( config( QStringLiteral( "MapIdentification" ), false ).toBool() );
212  mWidget->setOrderByValue( config( QStringLiteral( "OrderByValue" ), false ).toBool() );
213  mWidget->setAllowAddFeatures( false );
214  mWidget->setOpenFormButtonVisible( false );
215 
216  if ( config( QStringLiteral( "FilterFields" ), QVariant() ).isValid() )
217  {
218  mWidget->setFilterFields( config( QStringLiteral( "FilterFields" ) ).toStringList() );
219  mWidget->setChainFilters( config( QStringLiteral( "ChainFilters" ) ).toBool() );
220  mWidget->setFilterExpression( config( QStringLiteral( "FilterExpression" ) ).toString() );
221  }
222 
223  QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( QStringLiteral( "Relation" ) ).toString() );
224  // if no relation is given from the config, fetch one if there is only one available
225  if ( !relation.isValid() && !layer()->referencingRelations( mFieldIdx ).isEmpty() && layer()->referencingRelations( mFieldIdx ).count() == 1 )
226  relation = layer()->referencingRelations( mFieldIdx )[0];
227  mWidget->setRelation( relation, config( QStringLiteral( "AllowNULL" ) ).toBool() );
228 
229  mWidget->showIndeterminateState();
230  connect( mWidget, &QgsRelationReferenceWidget::foreignKeysChanged, this, &QgsRelationReferenceSearchWidgetWrapper::onValuesChanged );
231 }
232 
233 
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QString name
Definition: qgsfield.h:60
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsRelationManager * relationManager
Definition: qgsproject.h:111
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Q_DECL_DEPRECATED void onValueChanged(const QVariant &value)
Called when current value of search widget changes.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QString expression() const override
Will be used to access the widget's value.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes.
QgsRelationReferenceSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QgsMapCanvas *canvas, QWidget *parent=nullptr)
Constructor for QgsRelationReferenceSearchWidgetWrapper.
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
QVariant value() const
Returns a variant representing the current state of the widget.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
QgsSearchWidgetWrapper::FilterFlags defaultFlags() const override
Returns the default flags (equalTo)
bool valid() const override
Returns true if the widget has been properly initialized.
void setFilterExpression(const QString &filterExpression)
If not empty, will be used as filter expression.
void foreignKeysChanged(const QVariantList &)
Emitted when the foreign keys changed.
void setChainFilters(bool chainFilters)
Set if filters are chained.
void setEditorContext(const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar)
Sets the editor context.
void showIndeterminateState()
Sets the widget to display in an indeterminate "mixed value" state.
void setFilterFields(const QStringList &filterFields)
Sets the fields for which filter comboboxes will be created.
void setAllowMapIdentification(bool allowMapIdentification)
QgsRelation relation() const
Returns the current relation, which might be invalid.
QVariantList foreignKeys() const
returns the related feature foreign key
void setOrderByValue(bool orderByValue)
Sets if the widget will order the combobox entries by value.
void setRelation(const QgsRelation &relation, bool allowNullValue)
void setOpenFormButtonVisible(bool openFormButtonVisible)
void setAllowAddFeatures(bool allowAddFeatures)
Determines if a button for adding new features should be shown.
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
bool isValid
Definition: qgsrelation.h:50
Shows a search widget on a filter form.
@ IsNull
Supports searching for null values.
@ IsNotNull
Supports searching for non-null values.
@ EqualTo
Supports equal to.
@ NotEqualTo
Supports not equal to.
int fieldIndex() const
Returns the field index.
void valueChanged()
Emitted when a user changes the value of the search widget.
void valueCleared()
Emitted when a user changes the value of the search widget back to an empty, default state.
void expressionChanged(const QString &exp)
Emitted whenever the expression changes.
QString createFieldIdentifier() const
Gets a field name or expression to use as field comparison.
void clearExpression()
clears the expression to search for all features
static QString toString(QgsSearchWidgetWrapper::FilterFlag flag)
Returns a translated string representing a filter flag.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
QVariantMap config() const
Returns the whole config.
#define str(x)
Definition: qgis.cpp:37