31 #include <QHeaderView> 34 #include <QTableWidget> 35 #include <QStringListModel> 38 #include <nlohmann/json.hpp> 54 int cbxIdx = mComboBox->currentIndex();
57 v = mComboBox->currentData();
61 const int nofColumns = columnCount();
65 QStringList selection;
66 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
68 for (
int i = 0; i < nofColumns; ++i )
70 QTableWidgetItem *item = mTableWidget->item( j, i );
73 if ( item->checkState() == Qt::Checked )
74 selection << item->data( Qt::UserRole ).toString();
81 for (
const QString &s : qgis::as_const( selection ) )
84 const QVariant::Type type { fkType() };
87 case QVariant::Type::Int:
88 vl.push_back( s.toInt() );
90 case QVariant::Type::LongLong:
91 vl.push_back( s.toLongLong() );
99 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
100 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
115 if ( item.value == mLineEdit->text() )
132 mExpression =
config().value( QStringLiteral(
"FilterExpression" ) ).toString();
134 if (
config( QStringLiteral(
"AllowMulti" ) ).toBool() )
136 return new QTableWidget( parent );
138 else if (
config( QStringLiteral(
"UseCompleter" ) ).toBool() )
143 return new QComboBox( parent );
150 mComboBox = qobject_cast<QComboBox *>( editor );
151 mTableWidget = qobject_cast<QTableWidget *>( editor );
152 mLineEdit = qobject_cast<QLineEdit *>( editor );
159 connect( mComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
162 else if ( mTableWidget )
164 mTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
165 mTableWidget->horizontalHeader()->setVisible(
false );
166 mTableWidget->verticalHeader()->setSectionResizeMode( QHeaderView::Stretch );
167 mTableWidget->verticalHeader()->setVisible(
false );
168 mTableWidget->setShowGrid(
false );
169 mTableWidget->setEditTriggers( QAbstractItemView::NoEditTriggers );
170 mTableWidget->setSelectionMode( QAbstractItemView::NoSelection );
173 else if ( mLineEdit )
175 connect( mLineEdit, &QLineEdit::textChanged,
this, &QgsValueRelationWidgetWrapper::emitValueChangedInternal, Qt::UniqueConnection );
181 return mTableWidget || mLineEdit || mComboBox;
184 void QgsValueRelationWidgetWrapper::updateValues(
const QVariant &
value,
const QVariantList & )
188 QStringList checkList;
190 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
191 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
193 checkList =
value.toStringList();
200 QTableWidgetItem *lastChangedItem =
nullptr;
202 const int nofColumns = columnCount();
206 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
208 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
209 Q_UNUSED( signalBlockedTableWidget )
211 for (
int i = 0; i < nofColumns; ++i )
213 QTableWidgetItem *item = mTableWidget->item( j, i );
216 item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
218 item->setFlags( mEnabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
219 lastChangedItem = item;
224 if ( lastChangedItem )
225 lastChangedItem->setCheckState( checkList.contains( lastChangedItem->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
228 else if ( mComboBox )
233 for (
int i = 0; i < mComboBox->count(); i++ )
235 QVariant v( mComboBox->itemData( i ) );
242 mComboBox->setCurrentIndex( idx );
244 else if ( mLineEdit )
248 if ( i.key ==
value )
250 mLineEdit->setText( i.value );
261 if ( attributeChanged )
263 QVariant oldValue(
value( ) );
271 updateValues(
value( ) );
302 && !
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
306 QTimer::singleShot( 0,
this, [
this ]
308 updateValues( mCache.at( 0 ).key );
313 int QgsValueRelationWidgetWrapper::columnCount()
const 315 return std::max( 1,
config( QStringLiteral(
"NofColumns" ) ).toInt() );
319 QVariant::Type QgsValueRelationWidgetWrapper::fkType()
const 328 return fields.
at( idx ).
type();
331 return QVariant::Type::Invalid;
334 void QgsValueRelationWidgetWrapper::populate( )
341 else if ( mCache.empty() )
349 if (
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
351 whileBlocking( mComboBox )->addItem( tr(
"(no selection)" ), QVariant(
field().type( ) ) );
356 whileBlocking( mComboBox )->addItem( element.value, element.key );
359 else if ( mTableWidget )
361 const int nofColumns = columnCount();
363 if ( ! mCache.empty() )
365 mTableWidget->setRowCount( ( mCache.size() + nofColumns - 1 ) / nofColumns );
368 mTableWidget->setRowCount( 1 );
369 mTableWidget->setColumnCount( nofColumns );
376 if ( column == nofColumns )
381 QTableWidgetItem *item =
nullptr;
382 item =
new QTableWidgetItem( element.value );
383 item->setData( Qt::UserRole, element.key );
388 else if ( mLineEdit )
391 values.reserve( mCache.size() );
396 QStringListModel *m =
new QStringListModel( values, mLineEdit );
397 QCompleter *completer =
new QCompleter( m, mLineEdit );
398 completer->setCaseSensitivity( Qt::CaseInsensitive );
399 mLineEdit->setCompleter( completer );
405 const int nofColumns = columnCount();
409 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
411 for (
int i = 0; i < nofColumns; ++i )
413 whileBlocking( mTableWidget )->item( j, i )->setCheckState( Qt::PartiallyChecked );
417 else if ( mComboBox )
421 else if ( mLineEdit )
429 if ( mEnabled == enabled )
436 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
437 Q_UNUSED( signalBlockedTableWidget )
439 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
441 for (
int i = 0; i < mTableWidget->columnCount(); ++i )
443 QTableWidgetItem *item = mTableWidget->item( j, i );
446 item->setFlags( enabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
455 void QgsValueRelationWidgetWrapper::emitValueChangedInternal(
const QString &
value )
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
#define Q_NOWARN_DEPRECATED_PUSH
Container of fields for a vector layer.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
static QString buildArray(const QVariantList &list)
Build a postgres array like formatted list in a string from a QVariantList.
#define Q_NOWARN_DEPRECATED_POP
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
static QgsProject * instance()
Returns the QgsProject singleton instance.
bool qgsVariantEqual(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether they are equal, two NULL values are always treated a...
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.