32 #include <QHeaderView>
35 #include <QTableWidget>
36 #include <QStringListModel>
40 #include <nlohmann/json.hpp>
41 using namespace nlohmann;
56 int cbxIdx = mComboBox->currentIndex();
59 v = mComboBox->currentData();
61 v = QVariant(
field().type() );
64 else if ( mTableWidget )
66 const int nofColumns = columnCount();
67 QStringList selection;
68 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
70 for (
int i = 0; i < nofColumns; ++i )
72 QTableWidgetItem *item = mTableWidget->item( j, i );
75 if ( item->checkState() == Qt::Checked )
76 selection << item->data( Qt::UserRole ).toString();
82 if ( selection.isEmpty() && !
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
84 return QVariant( QVariant::Type::List );
89 for (
const QString &s : std::as_const( selection ) )
92 const QVariant::Type type { fkType() };
95 case QVariant::Type::Int:
96 vl.push_back( s.toInt() );
98 case QVariant::Type::LongLong:
99 vl.push_back( s.toLongLong() );
107 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
108 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
118 else if ( mLineEdit )
122 if ( item.value == mLineEdit->text() )
139 mExpression =
config().value( QStringLiteral(
"FilterExpression" ) ).toString();
141 if (
config( QStringLiteral(
"AllowMulti" ) ).toBool() )
143 return new QTableWidget( parent );
145 else if (
config( QStringLiteral(
"UseCompleter" ) ).toBool() )
151 return new QComboBox( parent );
158 mComboBox = qobject_cast<QComboBox *>( editor );
159 mTableWidget = qobject_cast<QTableWidget *>( editor );
160 mLineEdit = qobject_cast<QLineEdit *>( editor );
167 mComboBox->view()->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
168 connect( mComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
171 else if ( mTableWidget )
173 mTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
174 mTableWidget->horizontalHeader()->setVisible(
false );
175 mTableWidget->verticalHeader()->setSectionResizeMode( QHeaderView::Stretch );
176 mTableWidget->verticalHeader()->setVisible(
false );
177 mTableWidget->setShowGrid(
false );
178 mTableWidget->setEditTriggers( QAbstractItemView::NoEditTriggers );
179 mTableWidget->setSelectionMode( QAbstractItemView::NoSelection );
182 else if ( mLineEdit )
184 connect( mLineEdit, &QLineEdit::textChanged,
this, &QgsValueRelationWidgetWrapper::emitValueChangedInternal, Qt::UniqueConnection );
190 return mTableWidget || mLineEdit || mComboBox;
193 void QgsValueRelationWidgetWrapper::updateValues(
const QVariant &value,
const QVariantList & )
197 QStringList checkList;
199 if (
layer()->fields().at(
fieldIdx() ).type() == QVariant::Map ||
200 layer()->fields().at(
fieldIdx() ).type() == QVariant::List )
202 checkList =
value.toStringList();
209 QTableWidgetItem *lastChangedItem =
nullptr;
211 const int nofColumns = columnCount();
215 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
217 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
218 Q_UNUSED( signalBlockedTableWidget )
220 for (
int i = 0; i < nofColumns; ++i )
222 QTableWidgetItem *item = mTableWidget->item( j, i );
225 item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
227 item->setFlags( mEnabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
228 lastChangedItem = item;
233 if ( lastChangedItem )
234 lastChangedItem->setCheckState( checkList.contains( lastChangedItem->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
237 else if ( mComboBox )
242 for (
int i = 0; i < mComboBox->count(); i++ )
244 QVariant v( mComboBox->itemData( i ) );
255 if (
value.isNull( ) )
257 mComboBox->setCurrentIndex( -1 );
261 mComboBox->addItem(
value.toString().prepend(
'(' ).append(
')' ),
value );
262 mComboBox->setCurrentIndex( mComboBox->findData(
value ) );
267 mComboBox->setCurrentIndex( idx );
270 else if ( mLineEdit )
273 bool wasFound {
false };
276 if ( i.key ==
value )
278 mLineEdit->setText( i.value );
286 mLineEdit->setText( tr(
"(no selection)" ) );
295 if ( attributeChanged )
297 QVariant oldValue(
value( ) );
305 updateValues(
value( ) );
320 QString attributeName( formFields.
names().at(
fieldIdx() ) );
342 if (
context().attributeFormMode() != QgsAttributeEditorContext::Mode::MultiEditMode
344 && ! mCache.isEmpty()
345 && !
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
349 QTimer::singleShot( 0,
this, [
this ]
351 if ( ! mCache.isEmpty() )
353 updateValues( formFeature().attribute( fieldIdx() ).isValid() ? formFeature().attribute( fieldIdx() ) : mCache.at( 0 ).key );
359 int QgsValueRelationWidgetWrapper::columnCount()
const
361 return std::max( 1,
config( QStringLiteral(
"NofColumns" ) ).toInt() );
365 QVariant::Type QgsValueRelationWidgetWrapper::fkType()
const
374 return fields.
at( idx ).
type();
377 return QVariant::Type::Invalid;
380 void QgsValueRelationWidgetWrapper::populate( )
386 if (
context().parentFormFeature().isValid() )
395 else if ( mCache.empty() )
403 if (
config( QStringLiteral(
"AllowNull" ) ).toBool( ) )
405 whileBlocking( mComboBox )->addItem( tr(
"(no selection)" ), QVariant(
field().type( ) ) );
410 whileBlocking( mComboBox )->addItem( element.value, element.key );
411 if ( !element.description.isEmpty() )
412 mComboBox->setItemData( mComboBox->count() - 1, element.description, Qt::ToolTipRole );
416 else if ( mTableWidget )
418 const int nofColumns = columnCount();
420 if ( ! mCache.empty() )
422 mTableWidget->setRowCount( ( mCache.size() + nofColumns - 1 ) / nofColumns );
425 mTableWidget->setRowCount( 1 );
426 mTableWidget->setColumnCount( nofColumns );
433 if ( column == nofColumns )
438 QTableWidgetItem *item =
nullptr;
439 item =
new QTableWidgetItem( element.value );
440 item->setData( Qt::UserRole, element.key );
446 else if ( mLineEdit )
449 values.reserve( mCache.size() );
454 QStringListModel *m =
new QStringListModel( values, mLineEdit );
455 QCompleter *completer =
new QCompleter( m, mLineEdit );
456 completer->setCaseSensitivity( Qt::CaseInsensitive );
457 mLineEdit->setCompleter( completer );
463 const int nofColumns = columnCount();
467 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
469 for (
int i = 0; i < nofColumns; ++i )
471 whileBlocking( mTableWidget )->item( j, i )->setCheckState( Qt::PartiallyChecked );
475 else if ( mComboBox )
479 else if ( mLineEdit )
487 if ( mEnabled == enabled )
494 auto signalBlockedTableWidget =
whileBlocking( mTableWidget );
495 Q_UNUSED( signalBlockedTableWidget )
497 for (
int j = 0; j < mTableWidget->rowCount(); j++ )
499 for (
int i = 0; i < mTableWidget->columnCount(); ++i )
501 QTableWidgetItem *item = mTableWidget->item( j, i );
504 item->setFlags( enabled ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled );
520 ctx.setParentFormFeature( feature );
525 && (
config( QStringLiteral(
"Value" ) ).toString() == attribute ||
526 config( QStringLiteral(
"Key" ) ).toString() == attribute ||
535 void QgsValueRelationWidgetWrapper::emitValueChangedInternal(
const QString &value )