QGIS API Documentation  2.99.0-Master (7d4f81d)
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  , mComboBox( nullptr )
33  , mListWidget( nullptr )
34  , mLineEdit( nullptr )
35  , mLayer( nullptr )
36  , mUpdating( false )
37 {
38 }
39 
40 
42 {
43  QVariant v;
44 
45  if ( mComboBox )
46  {
47  int cbxIdx = mComboBox->currentIndex();
48  if ( cbxIdx > -1 )
49  {
50  v = mComboBox->currentData();
51  }
52  }
53 
54  if ( mListWidget )
55  {
56  QStringList selection;
57  for ( int i = 0; i < mListWidget->count(); ++i )
58  {
59  QListWidgetItem *item = mListWidget->item( i );
60  if ( item->checkState() == Qt::Checked )
61  selection << item->data( Qt::UserRole ).toString();
62  }
63 
64  v = selection.join( QStringLiteral( "," ) ).prepend( '{' ).append( '}' );
65  }
66 
67  if ( mLineEdit )
68  {
69  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &item, mCache )
70  {
71  if ( item.value == mLineEdit->text() )
72  {
73  v = item.value;
74  break;
75  }
76  }
77  }
78 
79  return v;
80 }
81 
83 {
84  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
85  {
86  return new QListWidget( parent );
87  }
88  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
89  {
90  return new QgsFilterLineEdit( parent );
91  }
92  {
93  return new QComboBox( parent );
94  }
95 }
96 
98 {
100 
101  mComboBox = qobject_cast<QComboBox *>( editor );
102  mListWidget = qobject_cast<QListWidget *>( editor );
103  mLineEdit = qobject_cast<QLineEdit *>( editor );
104 
105  if ( mComboBox )
106  {
107  if ( config( QStringLiteral( "AllowNull" ) ).toBool() )
108  {
109  mComboBox->addItem( tr( "(no selection)" ), QVariant( field().type() ) );
110  }
111 
112  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
113  {
114  mComboBox->addItem( element.value, element.key );
115  }
116 
117  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
118  this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::valueChanged ) );
119  }
120  else if ( mListWidget )
121  {
122  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
123  {
124  QListWidgetItem *item = nullptr;
125  item = new QListWidgetItem( element.value );
126  item->setData( Qt::UserRole, element.key );
127 
128  mListWidget->addItem( item );
129  }
130  connect( mListWidget, &QListWidget::itemChanged, this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::valueChanged ) );
131  }
132  else if ( mLineEdit )
133  {
134  QStringList values;
135  values.reserve( mCache.size() );
136  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &i, mCache )
137  {
138  values << i.value;
139  }
140 
141  QStringListModel *m = new QStringListModel( values, mLineEdit );
142  QCompleter *completer = new QCompleter( m, mLineEdit );
143  completer->setCaseSensitivity( Qt::CaseInsensitive );
144  mLineEdit->setCompleter( completer );
145  }
146 }
147 
149 {
150  return mListWidget || mLineEdit || mComboBox;
151 }
152 
154 {
155  if ( mListWidget )
156  {
157  QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( ',' );
158 
159  for ( int i = 0; i < mListWidget->count(); ++i )
160  {
161  QListWidgetItem *item = mListWidget->item( i );
162  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
163  }
164  }
165  else if ( mComboBox )
166  {
167  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
168  }
169  else if ( mLineEdit )
170  {
172  {
173  if ( i.key == value )
174  {
175  mLineEdit->setText( i.value );
176  break;
177  }
178  }
179  }
180 }
181 
183 {
184  if ( mListWidget )
185  {
186  mListWidget->blockSignals( true );
187  for ( int i = 0; i < mListWidget->count(); ++i )
188  {
189  mListWidget->item( i )->setCheckState( Qt::PartiallyChecked );
190  }
191  mListWidget->blockSignals( false );
192  }
193  else if ( mComboBox )
194  {
195  whileBlocking( mComboBox )->setCurrentIndex( -1 );
196  }
197  else if ( mLineEdit )
198  {
199  whileBlocking( mLineEdit )->clear();
200  }
201 }
202 
204 {
205  if ( mUpdating )
206  return;
207 
208  if ( mListWidget )
209  {
210  mUpdating = true;
211  for ( int i = 0; i < mListWidget->count(); ++i )
212  {
213  QListWidgetItem *item = mListWidget->item( i );
214 
215  if ( enabled )
216  item->setFlags( item->flags() | Qt::ItemIsEnabled );
217  else
218  item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
219  }
220  mUpdating = false;
221  }
222  else
224 }
void valueChanged()
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
virtual 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:187
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)