QGIS API Documentation  2.99.0-Master (5169e0d)
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 {
37 }
38 
39 
41 {
42  QVariant v;
43 
44  if ( mComboBox )
45  {
46  int cbxIdx = mComboBox->currentIndex();
47  if ( cbxIdx > -1 )
48  {
49  v = mComboBox->currentData();
50  }
51  }
52 
53  if ( mListWidget )
54  {
55  QStringList selection;
56  for ( int i = 0; i < mListWidget->count(); ++i )
57  {
58  QListWidgetItem *item = mListWidget->item( i );
59  if ( item->checkState() == Qt::Checked )
60  selection << item->data( Qt::UserRole ).toString();
61  }
62 
63  v = selection.join( QStringLiteral( "," ) ).prepend( '{' ).append( '}' );
64  }
65 
66  if ( mLineEdit )
67  {
68  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &item, mCache )
69  {
70  if ( item.value == mLineEdit->text() )
71  {
72  v = item.value;
73  break;
74  }
75  }
76  }
77 
78  return v;
79 }
80 
82 {
83  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
84  {
85  return new QListWidget( parent );
86  }
87  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
88  {
89  return new QgsFilterLineEdit( parent );
90  }
91  {
92  return new QComboBox( parent );
93  }
94 }
95 
97 {
99 
100  mComboBox = qobject_cast<QComboBox *>( editor );
101  mListWidget = qobject_cast<QListWidget *>( editor );
102  mLineEdit = qobject_cast<QLineEdit *>( editor );
103 
104  if ( mComboBox )
105  {
106  if ( config( QStringLiteral( "AllowNull" ) ).toBool() )
107  {
108  mComboBox->addItem( tr( "(no selection)" ), QVariant( field().type() ) );
109  }
110 
111  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
112  {
113  mComboBox->addItem( element.value, element.key );
114  }
115 
116  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
117  this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::valueChanged ) );
118  }
119  else if ( mListWidget )
120  {
121  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
122  {
123  QListWidgetItem *item = nullptr;
124  item = new QListWidgetItem( element.value );
125  item->setData( Qt::UserRole, element.key );
126 
127  mListWidget->addItem( item );
128  }
129  connect( mListWidget, &QListWidget::itemChanged, this, static_cast<void ( QgsEditorWidgetWrapper::* )()>( &QgsEditorWidgetWrapper::valueChanged ) );
130  }
131  else if ( mLineEdit )
132  {
133  QStringList values;
134  values.reserve( mCache.size() );
135  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &i, mCache )
136  {
137  values << i.value;
138  }
139 
140  QStringListModel *m = new QStringListModel( values, mLineEdit );
141  QCompleter *completer = new QCompleter( m, mLineEdit );
142  completer->setCaseSensitivity( Qt::CaseInsensitive );
143  mLineEdit->setCompleter( completer );
144  }
145 }
146 
148 {
149  return mListWidget || mLineEdit || mComboBox;
150 }
151 
153 {
154  if ( mListWidget )
155  {
156  QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( ',' );
157 
158  for ( int i = 0; i < mListWidget->count(); ++i )
159  {
160  QListWidgetItem *item = mListWidget->item( i );
161  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
162  }
163  }
164  else if ( mComboBox )
165  {
166  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
167  }
168  else if ( mLineEdit )
169  {
171  {
172  if ( i.key == value )
173  {
174  mLineEdit->setText( i.value );
175  break;
176  }
177  }
178  }
179 }
180 
182 {
183  if ( mListWidget )
184  {
185  mListWidget->blockSignals( true );
186  for ( int i = 0; i < mListWidget->count(); ++i )
187  {
188  mListWidget->item( i )->setCheckState( Qt::PartiallyChecked );
189  }
190  mListWidget->blockSignals( false );
191  }
192  else if ( mComboBox )
193  {
194  whileBlocking( mComboBox )->setCurrentIndex( -1 );
195  }
196  else if ( mLineEdit )
197  {
198  whileBlocking( mLineEdit )->clear();
199  }
200 }
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
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.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:178
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)