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()->setResizeMode( QHeaderView::Stretch );
165 mTableWidget->horizontalHeader()->setVisible(
false );
166 mTableWidget->verticalHeader()->setResizeMode( 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, [ = ](
const QString &
value )
181 }, Qt::UniqueConnection );
187 return mTableWidget || mLineEdit || mComboBox;
190 void QgsValueRelationWidgetWrapper::updateValues(
const QVariant &
value,
const QVariantList & )
194 QStringList checkList;
196 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
197 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
199 checkList =
value.toStringList();
206 QTableWidgetItem *lastChangedItem =
nullptr;
208 const int nofColumns = columnCount();
212 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
214 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
215 Q_UNUSED( signalBlockedTableWidget )
217 for (
int i = 0; i < nofColumns; ++i )
219 QTableWidgetItem *item = mTableWidget->item( j, i );
222 item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
224 item->setFlags( mEnabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
225 lastChangedItem = item;
230 if ( lastChangedItem )
231 lastChangedItem->setCheckState( checkList.contains( lastChangedItem->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
234 else if ( mComboBox )
239 for (
int i = 0; i < mComboBox->count(); i++ )
241 QVariant v( mComboBox->itemData( i ) );
248 mComboBox->setCurrentIndex( idx );
250 else if ( mLineEdit )
254 if ( i.key ==
value )
256 mLineEdit->setText( i.value );
267 if ( attributeChanged )
269 QVariant oldValue(
value( ) );
277 updateValues(
value( ) );
308 && !
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
312 QTimer::singleShot( 0,
this, [
this ]
314 updateValues( mCache.at( 0 ).key );
319 int QgsValueRelationWidgetWrapper::columnCount()
const 321 return std::max( 1,
config( QStringLiteral(
"NofColumns" ) ).toInt() );
325 QVariant::Type QgsValueRelationWidgetWrapper::fkType()
const 334 return fields.
at( idx ).
type();
337 return QVariant::Type::Invalid;
340 void QgsValueRelationWidgetWrapper::populate( )
347 else if ( mCache.empty() )
355 if (
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
357 whileBlocking( mComboBox )->addItem( tr(
"(no selection)" ), QVariant(
field().type( ) ) );
362 whileBlocking( mComboBox )->addItem( element.value, element.key );
365 else if ( mTableWidget )
367 const int nofColumns = columnCount();
369 if ( ! mCache.empty() )
371 mTableWidget->setRowCount( ( mCache.size() + nofColumns - 1 ) / nofColumns );
374 mTableWidget->setRowCount( 1 );
375 mTableWidget->setColumnCount( nofColumns );
382 if ( column == nofColumns )
387 QTableWidgetItem *item =
nullptr;
388 item =
new QTableWidgetItem( element.value );
389 item->setData( Qt::UserRole, element.key );
394 else if ( mLineEdit )
397 values.reserve( mCache.size() );
402 QStringListModel *m =
new QStringListModel( values, mLineEdit );
403 QCompleter *completer =
new QCompleter( m, mLineEdit );
404 completer->setCaseSensitivity( Qt::CaseInsensitive );
405 mLineEdit->setCompleter( completer );
411 const int nofColumns = columnCount();
415 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
417 for (
int i = 0; i < nofColumns; ++i )
419 whileBlocking( mTableWidget )->item( j, i )->setCheckState( Qt::PartiallyChecked );
423 else if ( mComboBox )
427 else if ( mLineEdit )
435 if ( mEnabled == enabled )
442 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
443 Q_UNUSED( signalBlockedTableWidget )
445 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
447 for (
int i = 0; i < mTableWidget->columnCount(); ++i )
449 QTableWidgetItem *item = mTableWidget->item( j, i );
452 item->setFlags( enabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
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.