QGIS API Documentation  2.99.0-Master (c4aa4d0)
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 
27 #include <QStringListModel>
28 #include <QCompleter>
29 
30 QgsValueRelationWidgetWrapper::QgsValueRelationWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent )
31  : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
32 {
33 }
34 
35 
37 {
38  QVariant v;
39 
40  if ( mComboBox )
41  {
42  int cbxIdx = mComboBox->currentIndex();
43  if ( cbxIdx > -1 )
44  {
45  v = mComboBox->currentData();
46  }
47  }
48 
49  if ( mListWidget )
50  {
51  QStringList selection;
52  for ( int i = 0; i < mListWidget->count(); ++i )
53  {
54  QListWidgetItem *item = mListWidget->item( i );
55  if ( item->checkState() == Qt::Checked )
56  selection << item->data( Qt::UserRole ).toString();
57  }
58 
59  v = selection.join( QStringLiteral( "," ) ).prepend( '{' ).append( '}' );
60  }
61 
62  if ( mLineEdit )
63  {
64  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &item, mCache )
65  {
66  if ( item.value == mLineEdit->text() )
67  {
68  v = item.key;
69  break;
70  }
71  }
72  }
73 
74  return v;
75 }
76 
78 {
79  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
80  {
81  return new QListWidget( parent );
82  }
83  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
84  {
85  return new QgsFilterLineEdit( parent );
86  }
87  {
88  return new QComboBox( parent );
89  }
90 }
91 
93 {
95 
96  mComboBox = qobject_cast<QComboBox *>( editor );
97  mListWidget = qobject_cast<QListWidget *>( editor );
98  mLineEdit = qobject_cast<QLineEdit *>( editor );
99 
100  if ( mComboBox )
101  {
102  if ( config( QStringLiteral( "AllowNull" ) ).toBool() )
103  {
104  mComboBox->addItem( tr( "(no selection)" ), QVariant( field().type() ) );
105  }
106 
107  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
108  {
109  mComboBox->addItem( element.value, element.key );
110  }
111 
112  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
113  this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::emitValueChanged ) );
114  }
115  else if ( mListWidget )
116  {
117  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
118  {
119  QListWidgetItem *item = nullptr;
120  item = new QListWidgetItem( element.value );
121  item->setData( Qt::UserRole, element.key );
122 
123  mListWidget->addItem( item );
124  }
125  connect( mListWidget, &QListWidget::itemChanged, this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::emitValueChanged ) );
126  }
127  else if ( mLineEdit )
128  {
129  QStringList values;
130  values.reserve( mCache.size() );
131  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &i, mCache )
132  {
133  values << i.value;
134  }
135 
136  QStringListModel *m = new QStringListModel( values, mLineEdit );
137  QCompleter *completer = new QCompleter( m, mLineEdit );
138  completer->setCaseSensitivity( Qt::CaseInsensitive );
139  mLineEdit->setCompleter( completer );
140 
141  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & value ) { emit valueChanged( value ); } );
142  }
143 }
144 
146 {
147  return mListWidget || mLineEdit || mComboBox;
148 }
149 
151 {
152  if ( mListWidget )
153  {
154  QStringList checkList;
155  if ( value.type() == QVariant::StringList )
156  checkList = value.toStringList();
157  else if ( value.type() == QVariant::String )
158  checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( ',' );
159 
160  for ( int i = 0; i < mListWidget->count(); ++i )
161  {
162  QListWidgetItem *item = mListWidget->item( i );
163  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
164  }
165  }
166  else if ( mComboBox )
167  {
168  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
169  }
170  else if ( mLineEdit )
171  {
173  {
174  if ( i.key == value )
175  {
176  mLineEdit->setText( i.value );
177  break;
178  }
179  }
180  }
181 }
182 
184 {
185  if ( mListWidget )
186  {
187  mListWidget->blockSignals( true );
188  for ( int i = 0; i < mListWidget->count(); ++i )
189  {
190  mListWidget->item( i )->setCheckState( Qt::PartiallyChecked );
191  }
192  mListWidget->blockSignals( false );
193  }
194  else if ( mComboBox )
195  {
196  whileBlocking( mComboBox )->setCurrentIndex( -1 );
197  }
198  else if ( mLineEdit )
199  {
200  whileBlocking( mLineEdit )->clear();
201  }
202 }
203 
205 {
206  if ( mEnabled == enabled )
207  return;
208 
209  mEnabled = enabled;
210 
211  if ( mListWidget )
212  {
213  for ( int i = 0; i < mListWidget->count(); ++i )
214  {
215  QListWidgetItem *item = mListWidget->item( i );
216 
217  if ( enabled )
218  item->setFlags( item->flags() | Qt::ItemIsEnabled );
219  else
220  item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
221  }
222  }
223  else
225 }
void emitValueChanged()
Will call the value() method to determine the emitted value.
QgsField field() const
Access the field.
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
Manages an editor widget Widget and wrapper share the same parent.
void setValue(const QVariant &value) override
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
QVariantMap config() const
Returns the whole config.
bool valid() const override
Return true if the widget has been properly initialized.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:200
void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Represents a vector layer which manages a vector based data sets.
QVariant value() const override
Will be used to access the widget&#39;s value.
QgsValueRelationWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr)