31 #include <QHeaderView>
34 #include <QTableWidget>
35 #include <QStringListModel>
38 #include <nlohmann/json.hpp>
39 using namespace nlohmann;
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() )
144 return new QComboBox( parent );
151 mComboBox = qobject_cast<QComboBox *>( editor );
152 mTableWidget = qobject_cast<QTableWidget *>( editor );
153 mLineEdit = qobject_cast<QLineEdit *>( editor );
160 connect( mComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
163 else if ( mTableWidget )
165 mTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
166 mTableWidget->horizontalHeader()->setVisible(
false );
167 mTableWidget->verticalHeader()->setSectionResizeMode( QHeaderView::Stretch );
168 mTableWidget->verticalHeader()->setVisible(
false );
169 mTableWidget->setShowGrid(
false );
170 mTableWidget->setEditTriggers( QAbstractItemView::NoEditTriggers );
171 mTableWidget->setSelectionMode( QAbstractItemView::NoSelection );
174 else if ( mLineEdit )
176 connect( mLineEdit, &QLineEdit::textChanged,
this, &QgsValueRelationWidgetWrapper::emitValueChangedInternal, Qt::UniqueConnection );
182 return mTableWidget || mLineEdit || mComboBox;
185 void QgsValueRelationWidgetWrapper::updateValues(
const QVariant &value,
const QVariantList & )
189 QStringList checkList;
191 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
192 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
194 checkList =
value.toStringList();
201 QTableWidgetItem *lastChangedItem =
nullptr;
203 const int nofColumns = columnCount();
207 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
209 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
210 Q_UNUSED( signalBlockedTableWidget )
212 for (
int i = 0; i < nofColumns; ++i )
214 QTableWidgetItem *item = mTableWidget->item( j, i );
217 item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
219 item->setFlags( mEnabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
220 lastChangedItem = item;
225 if ( lastChangedItem )
226 lastChangedItem->setCheckState( checkList.contains( lastChangedItem->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
229 else if ( mComboBox )
234 for (
int i = 0; i < mComboBox->count(); i++ )
236 QVariant v( mComboBox->itemData( i ) );
243 mComboBox->setCurrentIndex( idx );
245 else if ( mLineEdit )
248 bool wasFound {
false };
251 if ( i.key ==
value )
253 mLineEdit->setText( i.value );
261 mLineEdit->setText( tr(
"(no selection)" ) );
270 if ( attributeChanged )
272 QVariant oldValue(
value( ) );
280 updateValues(
value( ) );
310 && ! mCache.isEmpty()
311 && !
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
315 QTimer::singleShot( 0,
this, [
this ]
317 if ( ! mCache.isEmpty() )
319 updateValues( mCache.at( 0 ).key );
325 int QgsValueRelationWidgetWrapper::columnCount()
const
327 return std::max( 1,
config( QStringLiteral(
"NofColumns" ) ).toInt() );
331 QVariant::Type QgsValueRelationWidgetWrapper::fkType()
const
340 return fields.
at( idx ).
type();
343 return QVariant::Type::Invalid;
346 void QgsValueRelationWidgetWrapper::populate( )
352 if (
context().parentFormFeature().isValid() )
361 else if ( mCache.empty() )
369 if (
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
371 whileBlocking( mComboBox )->addItem( tr(
"(no selection)" ), QVariant(
field().type( ) ) );
376 whileBlocking( mComboBox )->addItem( element.value, element.key );
377 if ( !element.description.isEmpty() )
378 mComboBox->setItemData( mComboBox->count() - 1, element.description, Qt::ToolTipRole );
382 else if ( mTableWidget )
384 const int nofColumns = columnCount();
386 if ( ! mCache.empty() )
388 mTableWidget->setRowCount( ( mCache.size() + nofColumns - 1 ) / nofColumns );
391 mTableWidget->setRowCount( 1 );
392 mTableWidget->setColumnCount( nofColumns );
399 if ( column == nofColumns )
404 QTableWidgetItem *item =
nullptr;
405 item =
new QTableWidgetItem( element.value );
406 item->setData( Qt::UserRole, element.key );
412 else if ( mLineEdit )
415 values.reserve( mCache.size() );
420 QStringListModel *m =
new QStringListModel( values, mLineEdit );
421 QCompleter *completer =
new QCompleter( m, mLineEdit );
422 completer->setCaseSensitivity( Qt::CaseInsensitive );
423 mLineEdit->setCompleter( completer );
429 const int nofColumns = columnCount();
433 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
435 for (
int i = 0; i < nofColumns; ++i )
437 whileBlocking( mTableWidget )->item( j, i )->setCheckState( Qt::PartiallyChecked );
441 else if ( mComboBox )
445 else if ( mLineEdit )
453 if ( mEnabled == enabled )
460 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
461 Q_UNUSED( signalBlockedTableWidget )
463 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
465 for (
int i = 0; i < mTableWidget->columnCount(); ++i )
467 QTableWidgetItem *item = mTableWidget->item( j, i );
470 item->setFlags( enabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
486 ctx.setParentFormFeature( feature );
491 && (
config( QStringLiteral(
"Value" ) ).toString() == attribute ||
492 config( QStringLiteral(
"Key" ) ).toString() == attribute ||
501 void QgsValueRelationWidgetWrapper::emitValueChangedInternal(
const QString &value )