75int QgsAttributeForm::sFormCounter = 0;
 
   80  , mOwnsMessageBar( true )
 
   82  , mFormNr( sFormCounter++ )
 
   84  , mPreventFeatureRefresh( false )
 
   85  , mIsSettingMultiEditFeatures( false )
 
   86  , mUnsavedMultiEditChanges( false )
 
   87  , mEditCommandMessage( tr( 
"Attributes changed" ) )
 
  100  updateContainersVisibility();
 
  102  updateEditableState();
 
 
  109  qDeleteAll( mInterfaces );
 
 
  136  mInterfaces.append( iface );
 
 
  152    if ( mUnsavedMultiEditChanges )
 
  155      int res = QMessageBox::question( 
this, tr( 
"Multiedit Attributes" ),
 
  156                                       tr( 
"Apply changes to edited features?" ), QMessageBox::Yes | QMessageBox::No );
 
  157      if ( res == QMessageBox::Yes )
 
  162    clearMultiEditMessages();
 
  164  mUnsavedMultiEditChanges = 
false;
 
  216    w->setContext( newContext );
 
  222    w->setVisible( relationWidgetsVisible );
 
  229      mSearchButtonBox->setVisible( 
false );
 
  234      mSearchButtonBox->setVisible( 
false );
 
  239      mSearchButtonBox->setVisible( 
false );
 
  243      resetMultiEdit( 
false );
 
  245      mSearchButtonBox->setVisible( 
false );
 
  249      mSearchButtonBox->setVisible( 
true );
 
  255      mSearchButtonBox->setVisible( 
false );
 
  263      mSearchButtonBox->setVisible( 
false );
 
 
  272  const auto constMWidgets = mWidgets;
 
  287        QVariant mainValue = eww->
value();
 
  289        additionalFieldValues[index] = value;
 
  290        eww->
setValues( mainValue, additionalFieldValues );
 
 
  304  mIsSettingFeature = 
true;
 
  321      mIsSettingFeature = 
false;
 
  322      const auto constMInterfaces = mInterfaces;
 
  325        iface->featureChanged();
 
  341  mIsSettingFeature = 
false;
 
 
  344bool QgsAttributeForm::saveEdits( QString *error )
 
  347  bool changedLayer = 
false;
 
  352    bool doUpdate = 
false;
 
  374            *error = tr( 
"JSON value for %1 is invalid and has not been saved" ).arg( eww->
field().
name() );
 
  377        QVariantList dstVars = QVariantList() << dst.at( eww->
fieldIdx() );
 
  378        QVariantList srcVars = QVariantList() << eww->
value();
 
  379        QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
 
  383        for ( 
const QString &fieldName : additionalFields )
 
  387          dstVars << dst.at( idx );
 
  391        Q_ASSERT( dstVars.count() == srcVars.count() );
 
  393        for ( 
int i = 0; i < dstVars.count(); i++ )
 
  396          if ( !
qgsVariantEqual( dstVars[i], srcVars[i] ) && srcVars[i].isValid() )
 
  398            dst[fieldIndexes[i]] = srcVars[i];
 
  408    const auto constMInterfaces = mInterfaces;
 
  411      if ( !iface->acceptChanges( updatedFeature ) )
 
  421        mFeature = updatedFeature;
 
  427        bool res = mLayer->
addFeature( updatedFeature );
 
  446        for ( 
int i = 0; i < dst.count(); ++i )
 
  449               || !dst.at( i ).isValid()                 
 
  450               || !fieldIsEditable( i ) )                
 
  456          QgsDebugMsgLevel( QStringLiteral( 
"dst:'%1' (type:%2, isNull:%3, isValid:%4)" )
 
  457                            .arg( dst.at( i ).toString(), dst.at( i ).typeName() ).arg( 
QgsVariantUtils::isNull( dst.at( i ) ) ).arg( dst.at( i ).isValid() ), 2 );
 
  458          QgsDebugMsgLevel( QStringLiteral( 
"src:'%1' (type:%2, isNull:%3, isValid:%4)" )
 
  459                            .arg( src.at( i ).toString(), src.at( i ).typeName() ).arg( 
QgsVariantUtils::isNull( src.at( i ) ) ).arg( src.at( i ).isValid() ), 2 );
 
  461          newValues[i] = dst.at( i );
 
  462          oldValues[i] = src.at( i );
 
  467        std::unique_ptr<QgsVectorLayerToolsContext> context = std::make_unique<QgsVectorLayerToolsContext>();
 
  469        context->setExpressionContext( &expressionContext );
 
  472        if ( success && n > 0 )
 
  499QgsFeature QgsAttributeForm::getUpdatedFeature()
 const 
  511    QVariantList dstVars = QVariantList() << featureAttributes.at( eww->
fieldIdx() );
 
  512    QVariantList srcVars = QVariantList() << eww->
value();
 
  513    QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
 
  517    for ( 
const QString &fieldName : additionalFields )
 
  521      dstVars << featureAttributes.at( idx );
 
  525    Q_ASSERT( dstVars.count() == srcVars.count() );
 
  527    for ( 
int i = 0; i < dstVars.count(); i++ )
 
  529      if ( !
qgsVariantEqual( dstVars[i], srcVars[i] ) && srcVars[i].isValid() )
 
  530        featureAttributes[fieldIndexes[i]] = srcVars[i];
 
  535  return updatedFeature;
 
  538void QgsAttributeForm::updateValuesDependencies( 
const int originIdx )
 
  540  updateValuesDependenciesDefaultValues( originIdx );
 
  541  updateValuesDependenciesVirtualFields( originIdx );
 
  544void QgsAttributeForm::updateValuesDependenciesDefaultValues( 
const int originIdx )
 
  546  if ( !mDefaultValueDependencies.contains( originIdx ) )
 
  554  QgsFeature updatedFeature = getUpdatedFeature();
 
  557  QList<QgsWidgetWrapper *> relevantWidgets = mDefaultValueDependencies.values( originIdx );
 
  574      if ( mAlreadyUpdatedFields.contains( eww->
fieldIdx() ) )
 
  586void QgsAttributeForm::updateValuesDependenciesVirtualFields( 
const int originIdx )
 
  588  if ( !mVirtualFieldsDependencies.contains( originIdx ) )
 
  595  QgsFeature updatedFeature = getUpdatedFeature();
 
  598  const QList<QgsWidgetWrapper *> relevantWidgets = mVirtualFieldsDependencies.values( originIdx );
 
  606    if ( mAlreadyUpdatedFields.contains( eww->
fieldIdx() ) )
 
  612    const QVariant value = exp.evaluate( &context );
 
  618void QgsAttributeForm::updateRelatedLayerFields()
 
  621  updateRelatedLayerFieldsDependencies();
 
  623  if ( mRelatedLayerFieldsDependencies.isEmpty() )
 
  630  QgsFeature updatedFeature = getUpdatedFeature();
 
  633  const QSet<QgsEditorWidgetWrapper *> relevantWidgets = mRelatedLayerFieldsDependencies;
 
  637    if ( mAlreadyUpdatedFields.contains( eww->
fieldIdx() ) )
 
  643    QVariant value = exp.evaluate( &context );
 
  648void QgsAttributeForm::resetMultiEdit( 
bool promptToSave )
 
  653  mUnsavedMultiEditChanges = 
false;
 
  657void QgsAttributeForm::multiEditMessageClicked( 
const QString &link )
 
  659  clearMultiEditMessages();
 
  660  resetMultiEdit( link == QLatin1String( 
"#apply" ) );
 
  663void QgsAttributeForm::filterTriggered()
 
  665  QString filter = createFilterExpression();
 
  671void QgsAttributeForm::searchZoomTo()
 
  673  QString filter = createFilterExpression();
 
  674  if ( filter.isEmpty() )
 
  680void QgsAttributeForm::searchFlash()
 
  682  QString filter = createFilterExpression();
 
  683  if ( filter.isEmpty() )
 
  689void QgsAttributeForm::filterAndTriggered()
 
  691  QString filter = createFilterExpression();
 
  692  if ( filter.isEmpty() )
 
  700void QgsAttributeForm::filterOrTriggered()
 
  702  QString filter = createFilterExpression();
 
  703  if ( filter.isEmpty() )
 
  711void QgsAttributeForm::pushSelectedFeaturesMessage()
 
  717                              tr( 
"%n matching feature(s) selected", 
"matching features", count ),
 
  723                              tr( 
"No matching features found" ),
 
  737  QString filter = createFilterExpression();
 
  738  if ( filter.isEmpty() )
 
  742  pushSelectedFeaturesMessage();
 
  747void QgsAttributeForm::searchSetSelection()
 
  752void QgsAttributeForm::searchAddToSelection()
 
  757void QgsAttributeForm::searchRemoveFromSelection()
 
  762void QgsAttributeForm::searchIntersectSelection()
 
  767bool QgsAttributeForm::saveMultiEdits()
 
  771  const QList<int> fieldIndexes = mFormEditorWidgets.uniqueKeys();
 
  772  mFormEditorWidgets.constBegin();
 
  773  for ( 
int fieldIndex : fieldIndexes )
 
  775    const QList<QgsAttributeFormEditorWidget *> widgets = mFormEditorWidgets.values( fieldIndex );
 
  776    if ( !widgets.first()->hasChanged() )
 
  779    if ( !widgets.first()->currentValue().isValid() 
 
  780         || !fieldIsEditable( fieldIndex ) ) 
 
  787      widget->changesCommitted();
 
  789    newAttributeValues.insert( fieldIndex, widgets.first()->currentValue() );
 
  792  if ( newAttributeValues.isEmpty() )
 
  800  int res = QMessageBox::information( 
this, tr( 
"Multiedit Attributes" ),
 
  801                                      tr( 
"Edits will be applied to all selected features." ), QMessageBox::Ok | QMessageBox::Cancel );
 
  802  if ( res != QMessageBox::Ok )
 
  813  const auto constMultiEditFeatureIds = mMultiEditFeatureIds;
 
  816    QgsAttributeMap::const_iterator aIt = newAttributeValues.constBegin();
 
  817    for ( ; aIt != newAttributeValues.constEnd(); ++aIt )
 
  823  clearMultiEditMessages();
 
  836  if ( !mButtonBox->isVisible() )
 
  837    mMessageBar->
pushItem( mMultiEditMessageBarItem );
 
  863    wrapper->notifyAboutToSave();
 
  903      success = saveEdits( error );
 
  907      success = saveMultiEdits();
 
  912  mUnsavedMultiEditChanges = 
false;
 
 
  921  mValuesInitialized = 
false;
 
  922  const auto constMWidgets = mWidgets;
 
  925    ww->setFeature( mFeature );
 
  936    mAlreadyUpdatedFields.append( eww->
fieldIdx() );
 
  937    updateValuesDependenciesVirtualFields( eww->
fieldIdx() );
 
  938    mAlreadyUpdatedFields.removeAll( eww->
fieldIdx() );
 
  941  mValuesInitialized = 
true;
 
 
  947  const auto widgets { findChildren<  QgsAttributeFormEditorWidget * >() };
 
 
  954void QgsAttributeForm::clearMultiEditMessages()
 
  956  if ( mMultiEditUnsavedMessageBarItem )
 
  958    if ( !mButtonBox->isVisible() )
 
  959      mMessageBar->
popWidget( mMultiEditUnsavedMessageBarItem );
 
  960    mMultiEditUnsavedMessageBarItem = 
nullptr;
 
  962  if ( mMultiEditMessageBarItem )
 
  964    if ( !mButtonBox->isVisible() )
 
  965      mMessageBar->
popWidget( mMultiEditMessageBarItem );
 
  966    mMultiEditMessageBarItem = 
nullptr;
 
  970QString QgsAttributeForm::createFilterExpression()
 const 
  975    QString filter = w->currentFilterExpression();
 
  976    if ( !filter.isEmpty() )
 
  980  if ( filters.isEmpty() )
 
  983  QString filter = filters.join( QLatin1String( 
") AND (" ) ).prepend( 
'(' ).append( 
')' );
 
  992  if ( mExtraContextScope )
 
 1005void QgsAttributeForm::onAttributeChanged( 
const QVariant &value, 
const QVariantList &additionalFieldValues )
 
 1010  bool signalEmitted = 
false;
 
 1012  if ( mValuesInitialized )
 
 1031      for ( 
int i = 0; i < additionalFields.count(); i++ )
 
 1033        const QString fieldName = additionalFields.at( i );
 
 1034        const QVariant value = additionalFieldValues.at( i );
 
 1038      signalEmitted = 
true;
 
 1040      if ( mValuesInitialized )
 
 1041        updateJoinedFields( *eww );
 
 1047      if ( !mIsSettingMultiEditFeatures )
 
 1049        mUnsavedMultiEditChanges = 
true;
 
 1051        QLabel *msgLabel = 
new QLabel( tr( 
"Unsaved multiedit changes: <a href=\"#apply\">apply changes</a> or <a href=\"#reset\">reset changes</a>." ), mMessageBar );
 
 1052        msgLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
 
 1053        msgLabel->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
 
 1054        connect( msgLabel, &QLabel::linkActivated, 
this, &QgsAttributeForm::multiEditMessageClicked );
 
 1055        clearMultiEditMessages();
 
 1058        if ( !mButtonBox->isVisible() )
 
 1059          mMessageBar->
pushItem( mMultiEditUnsavedMessageBarItem );
 
 1062        signalEmitted = 
true;
 
 1074  const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( eww->
fieldIdx() );
 
 1077    if ( formEditorWidget->editorWidget() == eww )
 
 1082    whileBlocking( formEditorWidget->editorWidget() )->setValue( value );
 
 1085  updateConstraints( eww );
 
 1088  if ( mValuesInitialized )
 
 1091    mAlreadyUpdatedFields.append( eww->
fieldIdx() );
 
 1092    updateValuesDependencies( eww->
fieldIdx() );
 
 1093    mAlreadyUpdatedFields.removeAll( eww->
fieldIdx() );
 
 1098  updateEditableState();
 
 1100  if ( !signalEmitted )
 
 1105    bool attributeHasChanged = !mIsSettingFeature;
 
 1107      attributeHasChanged &= !mIsSettingMultiEditFeatures;
 
 1113void QgsAttributeForm::updateAllConstraints()
 
 1115  const auto constMWidgets = mWidgets;
 
 1120      updateConstraints( eww );
 
 1128  if ( currentFormValuesFeature( ft ) )
 
 1140    updateConstraint( ft, eww );
 
 1143    const QList<QgsEditorWidgetWrapper *> deps = constraintDependencies( eww );
 
 1146      updateConstraint( ft, depsEww );
 
 1154    const QVector<ContainerInformation *> infos = mContainerInformationDependency.value( eww->
field().
name() );
 
 1155    for ( ContainerInformation *info : infos )
 
 1157      info->apply( &context );
 
 1162void QgsAttributeForm::updateContainersVisibility()
 
 1166  const QVector<ContainerInformation *> infos = mContainerVisibilityCollapsedInformation;
 
 1168  for ( ContainerInformation *info : infos )
 
 1170    info->apply( &context );
 
 1180    updateAllConstraints();
 
 1196      if ( mJoinedFeatures.contains( info ) )
 
 1213void QgsAttributeForm::updateLabels()
 
 1215  if ( ! mLabelDataDefinedProperties.isEmpty() )
 
 1218    if ( currentFormValuesFeature( currentFeature ) )
 
 1222      for ( 
auto it = mLabelDataDefinedProperties.constBegin() ; it != mLabelDataDefinedProperties.constEnd(); ++it )
 
 1224        QLabel *label { it.key() };
 
 1226        const QString value { it->valueAsString( context, QString(), &ok ) };
 
 1227        if ( ok && ! value.isEmpty() )
 
 1229          label->setText( value );
 
 1236void QgsAttributeForm::updateEditableState()
 
 1238  if ( ! mEditableDataDefinedProperties.isEmpty() )
 
 1241    if ( currentFormValuesFeature( currentFeature ) )
 
 1245      for ( 
auto it = mEditableDataDefinedProperties.constBegin() ; it != mEditableDataDefinedProperties.constEnd(); ++it )
 
 1247        QWidget *w { it.key() };
 
 1249        const bool isEditable { it->valueAsBool( context, 
true, &ok ) && mLayer && mLayer->
isEditable() };  
 
 1259            w->setEnabled( isEditable );
 
 1267bool QgsAttributeForm::currentFormValuesFeature( 
QgsFeature &feature )
 
 1280    if ( dst.count() > eww->
fieldIdx() )
 
 1282      QVariantList dstVars = QVariantList() << dst.at( eww->
fieldIdx() );
 
 1283      QVariantList srcVars = QVariantList() << eww->
value();
 
 1284      QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
 
 1288      for ( 
const QString &fieldName : additionalFields )
 
 1291        fieldIndexes << idx;
 
 1292        dstVars << dst.at( idx );
 
 1296      Q_ASSERT( dstVars.count() == srcVars.count() );
 
 1298      for ( 
int i = 0; i < dstVars.count(); i++ )
 
 1304          dst[fieldIndexes[i]] = srcVars[i];
 
 1321void QgsAttributeForm::registerContainerInformation( QgsAttributeForm::ContainerInformation *info )
 
 1323  mContainerVisibilityCollapsedInformation.append( info );
 
 1325  const QSet<QString> referencedColumns = info->expression.referencedColumns().unite( info->collapsedExpression.referencedColumns() );
 
 1327  for ( 
const QString &col : referencedColumns )
 
 1329    mContainerInformationDependency[ col ].append( info );
 
 1333bool QgsAttributeForm::currentFormValidConstraints( QStringList &invalidFields, QStringList &descriptions )
 const 
 1357bool QgsAttributeForm::currentFormValidHardConstraints( QStringList &invalidFields, QStringList &descriptions )
 const 
 1378void QgsAttributeForm::onAttributeAdded( 
int idx )
 
 1380  mPreventFeatureRefresh = 
false;
 
 1392void QgsAttributeForm::onAttributeDeleted( 
int idx )
 
 1394  mPreventFeatureRefresh = 
false;
 
 1398    attrs.remove( idx );
 
 1406void QgsAttributeForm::onRelatedFeaturesChanged()
 
 1408  updateRelatedLayerFields();
 
 1411void QgsAttributeForm::onUpdatedFields()
 
 1413  mPreventFeatureRefresh = 
false;
 
 1440void QgsAttributeForm::onConstraintStatusChanged( 
const QString &constraint,
 
 1446  const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( eww->
fieldIdx() );
 
 1450    formEditorWidget->setConstraintStatus( constraint, description, err, result );
 
 1451    if ( formEditorWidget->editorWidget() != eww )
 
 1453      formEditorWidget->editorWidget()->updateConstraint( result, err );
 
 1460  QList<QgsEditorWidgetWrapper *> wDeps;
 
 1472      if ( name != ewwName )
 
 1479        for ( 
const QString &colName : referencedColumns )
 
 1481          if ( name == colName )
 
 1483            wDeps.append( eww );
 
 1496  return setupRelationWidgetWrapper( QString(), rel, context );
 
 1509void QgsAttributeForm::preventFeatureRefresh()
 
 1511  mPreventFeatureRefresh = 
true;
 
 1542  return mNeedsGeometry;
 
 
 1545void QgsAttributeForm::synchronizeState()
 
 1547  bool isEditable = ( mFeature.
isValid()
 
 1557      const QList<QgsAttributeFormEditorWidget *> formWidgets = mFormEditorWidgets.values( eww->
fieldIdx() );
 
 1560        formWidget->setConstraintResultVisible( isEditable );
 
 1564      bool enabled = isEditable && fieldIsEditable( eww->
fieldIdx() );
 
 1565      ww->setEnabled( enabled );
 
 1571      ww->setEnabled( isEditable );
 
 1582      if ( mConstraintsFailMessageBarItem )
 
 1584        mMessageBar->
popWidget( mConstraintsFailMessageBarItem );
 
 1587      mMessageBar->
pushItem( mConstraintsFailMessageBarItem );
 
 1591      QStringList invalidFields, descriptions;
 
 1592      mValidConstraints = currentFormValidHardConstraints( invalidFields, descriptions );
 
 1596        if ( !mValidConstraints && !mConstraintsFailMessageBarItem )
 
 1598          mConstraintsFailMessageBarItem = 
new QgsMessageBarItem( tr( 
"Changes to this form will not be saved. %n field(s) don't meet their constraints.", 
"invalid fields", invalidFields.size() ), 
Qgis::MessageLevel::Warning, -1 );
 
 1599          mMessageBar->
pushItem( mConstraintsFailMessageBarItem );
 
 1601        else if ( mValidConstraints && mConstraintsFailMessageBarItem )
 
 1603          mMessageBar->
popWidget( mConstraintsFailMessageBarItem );
 
 1604          mConstraintsFailMessageBarItem = 
nullptr;
 
 1607      else if ( mConstraintsFailMessageBarItem )
 
 1609        mMessageBar->
popWidget( mConstraintsFailMessageBarItem );
 
 1610        mConstraintsFailMessageBarItem = 
nullptr;
 
 1613      isEditable = isEditable & mValidConstraints;
 
 1618  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
 
 1620    okButton->setEnabled( isEditable );
 
 1623void QgsAttributeForm::init()
 
 1625  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
 
 1628  QWidget *formWidget = 
nullptr;
 
 1629  mNeedsGeometry = 
false;
 
 1631  bool buttonBoxVisible = 
true;
 
 1635    buttonBoxVisible = mButtonBox->isVisible();
 
 1637    mButtonBox = 
nullptr;
 
 1640  if ( mSearchButtonBox )
 
 1642    delete mSearchButtonBox;
 
 1643    mSearchButtonBox = 
nullptr;
 
 1646  qDeleteAll( mWidgets );
 
 1649  while ( QWidget *w = this->findChild<QWidget *>() )
 
 1655  QVBoxLayout *vl = 
new QVBoxLayout();
 
 1656  vl->setContentsMargins( 0, 0, 0, 0 );
 
 1658  mMessageBar->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
 
 1659  vl->addWidget( mMessageBar );
 
 1664  QGridLayout *layout = 
new QGridLayout();
 
 1665  QWidget *container = 
new QWidget();
 
 1666  container->setLayout( layout );
 
 1667  vl->addWidget( container );
 
 1669  mFormEditorWidgets.clear();
 
 1670  mFormWidgets.clear();
 
 1673  setContentsMargins( 0, 0, 0, 0 );
 
 1682    if ( file && file->open( QFile::ReadOnly ) )
 
 1686      QFileInfo fi( file->fileName() );
 
 1687      loader.setWorkingDirectory( fi.dir() );
 
 1688      formWidget = loader.load( file, 
this );
 
 1691        formWidget->setWindowFlags( Qt::Widget );
 
 1692        layout->addWidget( formWidget );
 
 1695        mButtonBox = findChild<QDialogButtonBox *>();
 
 1698        formWidget->installEventFilter( 
this );
 
 1710    int columnCount = 1;
 
 1711    bool hasRootFields = 
false;
 
 1712    bool addSpacer = 
true;
 
 1721        if ( !containerDef )
 
 1724        switch ( containerDef->
type() )
 
 1728            tabWidget = 
nullptr;
 
 1729            WidgetInfo widgetInfo = createWidgetFromDef( widgDef, formWidget, mLayer, mContext );
 
 1730            if ( widgetInfo.labelStyle.overrideColor )
 
 1732              if ( widgetInfo.labelStyle.color.isValid() )
 
 1734                widgetInfo.widget->setStyleSheet( QStringLiteral( 
"QGroupBox::title { color: %1; }" ).arg( widgetInfo.labelStyle.color.name( QColor::HexArgb ) ) );
 
 1737            if ( widgetInfo.labelStyle.overrideFont )
 
 1739              widgetInfo.widget->setFont( widgetInfo.labelStyle.font );
 
 1742            layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
 
 1743            if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
 
 1745              layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
 
 1747            if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1749              layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1763            tabWidget = 
nullptr;
 
 1764            WidgetInfo widgetInfo = createWidgetFromDef( widgDef, formWidget, mLayer, mContext );
 
 1765            layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
 
 1766            if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1768              layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1771            if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
 
 1773              layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
 
 1789              layout->addWidget( tabWidget, row, column, 1, 2 );
 
 1793            QWidget *tabPage = 
new QWidget( tabWidget );
 
 1795            tabWidget->addTab( tabPage, widgDef->name() );
 
 1796            tabWidget->
setTabStyle( tabWidget->tabBar()->count() - 1, widgDef->labelStyle() );
 
 1800              registerContainerInformation( 
new ContainerInformation( tabWidget, tabPage, containerDef->
visibilityExpression().
data() ) );
 
 1802            QGridLayout *tabPageLayout = 
new QGridLayout();
 
 1803            tabPage->setLayout( tabPageLayout );
 
 1805            WidgetInfo widgetInfo = createWidgetFromDef( widgDef, tabPage, mLayer, mContext );
 
 1806            tabPageLayout->addWidget( widgetInfo.widget );
 
 1813        hasRootFields = 
true;
 
 1814        tabWidget = 
nullptr;
 
 1815        WidgetInfo widgetInfo = createWidgetFromDef( widgDef, container, mLayer, mContext );
 
 1818        if ( widgetInfo.showLabel )
 
 1820          if ( widgetInfo.labelStyle.overrideColor && widgetInfo.labelStyle.color.isValid() )
 
 1822            collapsibleGroupBox->
setStyleSheet( QStringLiteral( 
"QGroupBox::title { color: %1; }" ).arg( widgetInfo.labelStyle.color.name( QColor::HexArgb ) ) );
 
 1825          if ( widgetInfo.labelStyle.overrideFont )
 
 1827            collapsibleGroupBox->setFont( widgetInfo.labelStyle.font );
 
 1830          collapsibleGroupBox->setTitle( widgetInfo.labelText );
 
 1833        QVBoxLayout *collapsibleGroupBoxLayout = 
new QVBoxLayout();
 
 1834        collapsibleGroupBoxLayout->addWidget( widgetInfo.widget );
 
 1835        collapsibleGroupBox->setLayout( collapsibleGroupBoxLayout );
 
 1837        QVBoxLayout *
c = 
new QVBoxLayout();
 
 1838        c->addWidget( collapsibleGroupBox );
 
 1839        layout->addLayout( 
c, row, column, 1, 2 );
 
 1841        if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1842          layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1843        if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
 
 1844          layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
 
 1853        hasRootFields = 
true;
 
 1854        tabWidget = 
nullptr;
 
 1855        WidgetInfo widgetInfo = createWidgetFromDef( widgDef, container, mLayer, mContext );
 
 1856        QLabel *label = 
new QLabel( widgetInfo.labelText );
 
 1858        if ( widgetInfo.labelStyle.overrideColor )
 
 1860          if ( widgetInfo.labelStyle.color.isValid() )
 
 1862            label->setStyleSheet( QStringLiteral( 
"QLabel { color: %1; }" ).arg( widgetInfo.labelStyle.color.name( QColor::HexArgb ) ) );
 
 1866        if ( widgetInfo.labelStyle.overrideFont )
 
 1868          label->setFont( widgetInfo.labelStyle.font );
 
 1871        label->setToolTip( widgetInfo.toolTip );
 
 1872        if ( columnCount > 1 && !widgetInfo.labelOnTop )
 
 1874          label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
 
 1877        label->setBuddy( widgetInfo.widget );
 
 1880        if ( widgetInfo.widget
 
 1881             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Fixed
 
 1882             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Maximum
 
 1883             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Preferred )
 
 1886        if ( !widgetInfo.showLabel )
 
 1888          QVBoxLayout *
c = 
new QVBoxLayout();
 
 1889          label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
 
 1890          c->addWidget( widgetInfo.widget );
 
 1891          layout->addLayout( 
c, row, column, 1, 2 );
 
 1893          if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1895            layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1898          if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
 
 1900            layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
 
 1905        else if ( widgetInfo.labelOnTop )
 
 1907          QVBoxLayout *
c = 
new QVBoxLayout();
 
 1908          label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
 
 1909          c->addWidget( label );
 
 1910          c->addWidget( widgetInfo.widget );
 
 1911          layout->addLayout( 
c, row, column, 1, 2 );
 
 1913          if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1915            layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1918          if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( column + 1 ) )
 
 1920            layout->setColumnStretch( column + 1, widgDef->horizontalStretch() );
 
 1927          const int widgetColumn = column + 1;
 
 1928          layout->addWidget( label, row, column++ );
 
 1929          layout->addWidget( widgetInfo.widget, row, column++ );
 
 1931          if ( widgDef->verticalStretch() > 0 && widgDef->verticalStretch() > layout->rowStretch( row ) )
 
 1933            layout->setRowStretch( row, widgDef->verticalStretch() );
 
 1936          if ( widgDef->horizontalStretch() > 0 && widgDef->horizontalStretch() > layout->columnStretch( widgetColumn ) )
 
 1938            layout->setColumnStretch( widgetColumn, widgDef->horizontalStretch() );
 
 1946          const int fieldIdx = fieldElement->
idx();
 
 1947          if ( fieldIdx >= 0 && fieldIdx < mLayer->fields().count() )
 
 1949            const QString fieldName { mLayer->
fields().
at( fieldIdx ).
name() };
 
 1953              if ( property.isActive() )
 
 1955                mLabelDataDefinedProperties[ label ] = property;
 
 1961              if ( property.isActive() )
 
 1963                mEditableDataDefinedProperties[ widgetInfo.widget ] = property;
 
 1970      if ( column >= columnCount * 2 )
 
 1977    if ( hasRootFields && addSpacer )
 
 1979      QSpacerItem *spacerItem = 
new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );
 
 1980      layout->addItem( spacerItem, row, 0 );
 
 1981      layout->setRowStretch( row, 1 );
 
 1984    formWidget = container;
 
 1993    formWidget = 
new QWidget( 
this );
 
 1994    QGridLayout *gridLayout = 
new QGridLayout( formWidget );
 
 1995    formWidget->setLayout( gridLayout );
 
 2001      scrollArea->setWidget( formWidget );
 
 2002      scrollArea->setWidgetResizable( 
true );
 
 2003      scrollArea->setFrameShape( QFrame::NoFrame );
 
 2004      scrollArea->setFrameShadow( QFrame::Plain );
 
 2005      scrollArea->setFocusProxy( 
this );
 
 2006      layout->addWidget( scrollArea );
 
 2010      layout->addWidget( formWidget );
 
 2017    for ( 
const QgsField &field : fields )
 
 2025      QString labelText = fieldName;
 
 2026      labelText.replace( 
'&', QLatin1String( 
"&&" ) ); 
 
 2030      if ( widgetSetup.
type() == QLatin1String( 
"Hidden" ) )
 
 2036      QLabel *label = 
new QLabel( labelText );
 
 2038      QSvgWidget *i = 
new QSvgWidget();
 
 2039      i->setFixedSize( 18, 18 );
 
 2044        if ( property.isActive() )
 
 2046          mLabelDataDefinedProperties[ label ] = property;
 
 2052      QWidget *w = 
nullptr;
 
 2057        mFormEditorWidgets.insert( idx, formWidget );
 
 2058        mFormWidgets.append( formWidget );
 
 2061        label->setBuddy( eww->
widget() );
 
 2066          if ( property.isActive() )
 
 2068            mEditableDataDefinedProperties[ formWidget ] = property;
 
 2074        w = 
new QLabel( QStringLiteral( 
"<p style=\"color: red; font-style: italic;\">%1</p>" ).arg( tr( 
"Failed to create widget with type '%1'" ).arg( widgetSetup.
type() ) ) );
 
 2079        w->setObjectName( field.name() );
 
 2083        mWidgets.append( eww );
 
 2084        mIconMap[eww->
widget()] = i;
 
 2089        gridLayout->addWidget( label, row++, 0, 1, 2 );
 
 2090        gridLayout->addWidget( w, row++, 0, 1, 2 );
 
 2091        gridLayout->addWidget( i, row++, 0, 1, 2 );
 
 2095        gridLayout->addWidget( label, row, 0 );
 
 2096        gridLayout->addWidget( w, row, 1 );
 
 2097        gridLayout->addWidget( i, row++, 2 );
 
 2111      QVBoxLayout *collapsibleGroupBoxLayout = 
new QVBoxLayout();
 
 2112      collapsibleGroupBoxLayout->addWidget( formWidget );
 
 2113      collapsibleGroupBox->setLayout( collapsibleGroupBoxLayout );
 
 2115      gridLayout->addWidget( collapsibleGroupBox, row++, 0, 1, 2 );
 
 2117      mWidgets.append( rww );
 
 2118      mFormWidgets.append( formWidget );
 
 2123      QSpacerItem *spacerItem = 
new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );
 
 2124      gridLayout->addItem( spacerItem, row, 0 );
 
 2125      gridLayout->setRowStretch( row, 1 );
 
 2131  updateFieldDependencies();
 
 2135    mButtonBox = 
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
 
 2136    mButtonBox->setObjectName( QStringLiteral( 
"buttonBox" ) );
 
 2137    layout->addWidget( mButtonBox, layout->rowCount(), 0, 1, layout->columnCount() );
 
 2139  mButtonBox->setVisible( buttonBoxVisible );
 
 2141  if ( !mSearchButtonBox )
 
 2143    mSearchButtonBox = 
new QWidget();
 
 2144    QHBoxLayout *boxLayout = 
new QHBoxLayout();
 
 2145    boxLayout->setContentsMargins( 0, 0, 0, 0 );
 
 2146    mSearchButtonBox->setLayout( boxLayout );
 
 2147    mSearchButtonBox->setObjectName( QStringLiteral( 
"searchButtonBox" ) );
 
 2149    QPushButton *clearButton = 
new QPushButton( tr( 
"&Reset Form" ), mSearchButtonBox );
 
 2151    boxLayout->addWidget( clearButton );
 
 2152    boxLayout->addStretch( 1 );
 
 2154    QPushButton *flashButton = 
new QPushButton();
 
 2155    flashButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
 
 2156    flashButton->setText( tr( 
"&Flash Features" ) );
 
 2157    connect( flashButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchFlash );
 
 2158    boxLayout->addWidget( flashButton );
 
 2160    QPushButton *openAttributeTableButton = 
new QPushButton();
 
 2161    openAttributeTableButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
 
 2162    openAttributeTableButton->setText( tr( 
"Show in &Table" ) );
 
 2163    openAttributeTableButton->setToolTip( tr( 
"Open the attribute table editor with the filtered features" ) );
 
 2164    connect( openAttributeTableButton, &QToolButton::clicked, 
this, [ = ]
 
 2168    boxLayout->addWidget( openAttributeTableButton );
 
 2170    QPushButton *zoomButton = 
new QPushButton();
 
 2171    zoomButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
 
 2172    zoomButton->setText( tr( 
"&Zoom to Features" ) );
 
 2173    connect( zoomButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchZoomTo );
 
 2174    boxLayout->addWidget( zoomButton );
 
 2176    QToolButton *selectButton = 
new QToolButton();
 
 2177    selectButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
 
 2178    selectButton->setText( tr( 
"&Select Features" ) );
 
 2180    selectButton->setPopupMode( QToolButton::MenuButtonPopup );
 
 2181    selectButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
 
 2182    connect( selectButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchSetSelection );
 
 2183    QMenu *selectMenu = 
new QMenu( selectButton );
 
 2184    QAction *selectAction = 
new QAction( tr( 
"Select Features" ), selectMenu );
 
 2186    connect( selectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchSetSelection );
 
 2187    selectMenu->addAction( selectAction );
 
 2188    QAction *addSelectAction = 
new QAction( tr( 
"Add to Current Selection" ), selectMenu );
 
 2190    connect( addSelectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchAddToSelection );
 
 2191    selectMenu->addAction( addSelectAction );
 
 2192    QAction *deselectAction = 
new QAction( tr( 
"Remove from Current Selection" ), selectMenu );
 
 2194    connect( deselectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchRemoveFromSelection );
 
 2195    selectMenu->addAction( deselectAction );
 
 2196    QAction *filterSelectAction = 
new QAction( tr( 
"Filter Current Selection" ), selectMenu );
 
 2198    connect( filterSelectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchIntersectSelection );
 
 2199    selectMenu->addAction( filterSelectAction );
 
 2200    selectButton->setMenu( selectMenu );
 
 2201    boxLayout->addWidget( selectButton );
 
 2205      QToolButton *filterButton = 
new QToolButton();
 
 2206      filterButton->setText( tr( 
"Filter Features" ) );
 
 2207      filterButton->setPopupMode( QToolButton::MenuButtonPopup );
 
 2208      filterButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
 
 2209      connect( filterButton, &QToolButton::clicked, 
this, &QgsAttributeForm::filterTriggered );
 
 2210      QMenu *filterMenu = 
new QMenu( filterButton );
 
 2211      QAction *filterAndAction = 
new QAction( tr( 
"Filter Within (\"AND\")" ), filterMenu );
 
 2212      connect( filterAndAction, &QAction::triggered, 
this, &QgsAttributeForm::filterAndTriggered );
 
 2213      filterMenu->addAction( filterAndAction );
 
 2214      QAction *filterOrAction = 
new QAction( tr( 
"Extend Filter (\"OR\")" ), filterMenu );
 
 2215      connect( filterOrAction, &QAction::triggered, 
this, &QgsAttributeForm::filterOrTriggered );
 
 2216      filterMenu->addAction( filterOrAction );
 
 2217      filterButton->setMenu( filterMenu );
 
 2218      boxLayout->addWidget( filterButton );
 
 2222      QPushButton *closeButton = 
new QPushButton( tr( 
"Close" ), mSearchButtonBox );
 
 2224      closeButton->setShortcut( Qt::Key_Escape );
 
 2225      boxLayout->addWidget( closeButton );
 
 2228    layout->addWidget( mSearchButtonBox, layout->rowCount(), 0, 1, layout->columnCount() );
 
 2246  const auto constMInterfaces = mInterfaces;
 
 2257  QApplication::restoreOverrideCursor();
 
 2260void QgsAttributeForm::cleanPython()
 
 2262  if ( !mPyFormVarName.isNull() )
 
 2264    QString expr = QStringLiteral( 
"if '%1' in locals(): del %1\n" ).arg( mPyFormVarName );
 
 2269void QgsAttributeForm::initPython()
 
 2286        if ( !initFilePath.isEmpty() )
 
 2290          if ( inputFile && inputFile->open( QFile::ReadOnly ) )
 
 2293            QTextStream inf( inputFile );
 
 2294#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 2295            inf.setCodec( 
"UTF-8" );
 
 2297            initCode = inf.readAll();
 
 2302            QgsLogger::warning( QStringLiteral( 
"The external python file path %1 could not be opened!" ).arg( initFilePath ) );
 
 2313        if ( initCode.isEmpty() )
 
 2315          QgsLogger::warning( QStringLiteral( 
"The python code provided in the dialog is empty!" ) );
 
 2326    if ( !initCode.isEmpty() )
 
 2332                                  tr( 
"Python macro could not be run due to missing permissions." ),
 
 2340    if ( 
QgsPythonRunner::eval( QStringLiteral( 
"len(inspect.getfullargspec(%1)[0])" ).arg( initFunction ), numArgs ) )
 
 2342      static int sFormId = 0;
 
 2343      mPyFormVarName = QStringLiteral( 
"_qgis_featureform_%1_%2" ).arg( mFormNr ).arg( sFormId++ );
 
 2345      QString form = QStringLiteral( 
"%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
 
 2346                     .arg( mPyFormVarName )
 
 2347                     .arg( ( quint64 ) 
this );
 
 2351      QgsDebugMsgLevel( QStringLiteral( 
"running featureForm init: %1" ).arg( mPyFormVarName ), 2 );
 
 2354      if ( numArgs == QLatin1String( 
"3" ) )
 
 2362        msgBox.setText( tr( 
"The python init function (<code>%1</code>) does not accept three arguments as expected!<br>Please check the function name in the <b>Fields</b> tab of the layer properties." ).arg( initFunction ) );
 
 2365        QString expr = QString( 
"%1(%2)" )
 
 2366                       .arg( mLayer->editFormInit() )
 
 2367                       .arg( mPyFormVarName );
 
 2368        QgsAttributeFormInterface *iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface *>( expr, 
"QgsAttributeFormInterface" );
 
 2378      msgBox.setText( tr( 
"The python init function (<code>%1</code>) could not be found!<br>Please check the function name in the <b>Fields</b> tab of the layer properties." ).arg( initFunction ) );
 
 2386  WidgetInfo newWidgetInfo;
 
 2388  newWidgetInfo.labelStyle = widgetDef->
labelStyle();
 
 2390  switch ( widgetDef->
type() )
 
 2402      mWidgets.append( actionWrapper );
 
 2403      newWidgetInfo.widget = actionWrapper->
widget();
 
 2404      newWidgetInfo.showLabel = 
false;
 
 2417      if ( fldIdx < fields.
count() && fldIdx >= 0 )
 
 2423        mFormEditorWidgets.insert( fldIdx, formWidget );
 
 2424        mFormWidgets.append( formWidget );
 
 2428        newWidgetInfo.widget = formWidget;
 
 2429        mWidgets.append( eww );
 
 2431        newWidgetInfo.widget->setObjectName( fields.
at( fldIdx ).
name() );
 
 2432        newWidgetInfo.hint = fields.
at( fldIdx ).
comment();
 
 2437      newWidgetInfo.labelText.replace( 
'&', QLatin1String( 
"&&" ) ); 
 
 2438      newWidgetInfo.toolTip = QStringLiteral( 
"<b>%1</b><p>%2</p>" ).arg( mLayer->
attributeDisplayName( fldIdx ), newWidgetInfo.hint );
 
 2439      newWidgetInfo.showLabel = widgetDef->
showLabel();
 
 2460      mWidgets.append( rww );
 
 2461      mFormWidgets.append( formWidget );
 
 2463      newWidgetInfo.widget = formWidget;
 
 2464      newWidgetInfo.showLabel = relDef->
showLabel();
 
 2465      newWidgetInfo.labelText = relDef->
label();
 
 2466      if ( newWidgetInfo.labelText.isEmpty() )
 
 2468      newWidgetInfo.labelOnTop = 
true;
 
 2480      if ( columnCount <= 0 )
 
 2484      QWidget *myContainer = 
nullptr;
 
 2485      bool removeLayoutMargin = 
false;
 
 2486      switch ( container->
type() )
 
 2491          widgetName = QStringLiteral( 
"QGroupBox" );
 
 2494            groupBox->setTitle( container->
name() );
 
 2495            if ( newWidgetInfo.labelStyle.overrideColor )
 
 2497              if ( newWidgetInfo.labelStyle.color.isValid() )
 
 2499                groupBox->
setStyleSheet( QStringLiteral( 
"QGroupBox::title { color: %1; }" ).arg( newWidgetInfo.labelStyle.color.name( QColor::HexArgb ) ) );
 
 2502            if ( newWidgetInfo.labelStyle.overrideFont )
 
 2504              groupBox->setFont( newWidgetInfo.labelStyle.font );
 
 2507          myContainer = groupBox;
 
 2508          newWidgetInfo.widget = myContainer;
 
 2515          QWidget *rowWidget = 
new QWidget();
 
 2516          widgetName = QStringLiteral( 
"Row" );
 
 2517          myContainer = rowWidget;
 
 2518          newWidgetInfo.widget = myContainer;
 
 2519          removeLayoutMargin = 
true;
 
 2520          columnCount = container->
children().size();
 
 2526          myContainer = 
new QWidget();
 
 2530          scrollArea->setWidget( myContainer );
 
 2531          scrollArea->setWidgetResizable( 
true );
 
 2532          scrollArea->setFrameShape( QFrame::NoFrame );
 
 2533          widgetName = QStringLiteral( 
"QScrollArea QWidget" );
 
 2535          newWidgetInfo.widget = scrollArea;
 
 2542        QString style {QStringLiteral( 
"background-color: %1;" ).arg( container->
backgroundColor().name() )};
 
 2543        newWidgetInfo.widget->setStyleSheet( style );
 
 2546      QGridLayout *gbLayout = 
new QGridLayout();
 
 2547      if ( removeLayoutMargin )
 
 2548        gbLayout->setContentsMargins( 0, 0, 0, 0 );
 
 2549      myContainer->setLayout( gbLayout );
 
 2553      bool addSpacer = 
true;
 
 2555      const QList<QgsAttributeEditorElement *> children = container->
children();
 
 2559        WidgetInfo widgetInfo = createWidgetFromDef( childDef, myContainer, vl, context );
 
 2571        int widgetColumn = column;
 
 2573        if ( widgetInfo.labelText.isNull() || ! widgetInfo.showLabel )
 
 2575          gbLayout->addWidget( widgetInfo.widget, row, column, 1, 2 );
 
 2576          widgetColumn = column + 1;
 
 2581          QLabel *mypLabel = 
new QLabel( widgetInfo.labelText );
 
 2583          if ( widgetInfo.labelStyle.overrideColor )
 
 2585            if ( widgetInfo.labelStyle.color.isValid() )
 
 2587              mypLabel->setStyleSheet( QStringLiteral( 
"QLabel { color: %1; }" ).arg( widgetInfo.labelStyle.color.name( QColor::HexArgb ) ) );
 
 2591          if ( widgetInfo.labelStyle.overrideFont )
 
 2593            mypLabel->setFont( widgetInfo.labelStyle.font );
 
 2601            const int fldIdx = fieldDef->
idx();
 
 2602            if ( fldIdx < fields.
count() && fldIdx >= 0 )
 
 2604              const QString fieldName { fields.
at( fldIdx ).
name() };
 
 2608                if ( property.isActive() )
 
 2610                  mLabelDataDefinedProperties[ mypLabel ] = property;
 
 2616                if ( property.isActive() )
 
 2618                  mEditableDataDefinedProperties[ widgetInfo.widget ] = property;
 
 2624          mypLabel->setToolTip( widgetInfo.toolTip );
 
 2625          if ( columnCount > 1 && !widgetInfo.labelOnTop )
 
 2627            mypLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
 
 2630          mypLabel->setBuddy( widgetInfo.widget );
 
 2632          if ( widgetInfo.labelOnTop )
 
 2634            widgetColumn = column + 1;
 
 2635            QVBoxLayout *
c = 
new QVBoxLayout();
 
 2636            mypLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
 
 2637            c->layout()->addWidget( mypLabel );
 
 2638            c->layout()->addWidget( widgetInfo.widget );
 
 2639            gbLayout->addLayout( 
c, row, column, 1, 2 );
 
 2644            widgetColumn = column + 1;
 
 2645            gbLayout->addWidget( mypLabel, row, column++ );
 
 2646            gbLayout->addWidget( widgetInfo.widget, row, column++ );
 
 2650        const int childHorizontalStretch = childDef->horizontalStretch();
 
 2651        const int existingColumnStretch = gbLayout->columnStretch( widgetColumn );
 
 2652        if ( childHorizontalStretch > 0 && childHorizontalStretch > existingColumnStretch )
 
 2654          gbLayout->setColumnStretch( widgetColumn, childHorizontalStretch );
 
 2657        if ( childDef->verticalStretch() > 0  && childDef->verticalStretch() > gbLayout->rowStretch( row ) )
 
 2659          gbLayout->setRowStretch( row, childDef->verticalStretch() );
 
 2662        if ( column >= columnCount * 2 )
 
 2668        if ( widgetInfo.widget
 
 2669             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Fixed
 
 2670             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Maximum
 
 2671             && widgetInfo.widget->sizePolicy().verticalPolicy() != QSizePolicy::Preferred )
 
 2675        if ( qobject_cast<QgsAttributeFormRelationEditorWidget *>( widgetInfo.widget ) )
 
 2681        QWidget *spacer = 
new QWidget();
 
 2682        spacer->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
 
 2683        gbLayout->addWidget( spacer, ++row, 0 );
 
 2684        gbLayout->setRowStretch( row, 1 );
 
 2687      newWidgetInfo.labelText = QString();
 
 2688      newWidgetInfo.labelOnTop = 
true;
 
 2689      newWidgetInfo.showLabel = widgetDef->
showLabel();
 
 2702      mWidgets.append( qmlWrapper );
 
 2704      newWidgetInfo.widget = qmlWrapper->
widget();
 
 2705      newWidgetInfo.labelText = elementDef->
name();
 
 2706      newWidgetInfo.labelOnTop = 
true;
 
 2707      newWidgetInfo.showLabel = widgetDef->
showLabel();
 
 2719      mWidgets.append( htmlWrapper );
 
 2721      newWidgetInfo.widget = htmlWrapper->
widget();
 
 2722      newWidgetInfo.labelText = elementDef->
name();
 
 2723      newWidgetInfo.labelOnTop = 
true;
 
 2724      newWidgetInfo.showLabel = widgetDef->
showLabel();
 
 2737      mWidgets.append( textWrapper );
 
 2739      newWidgetInfo.widget = textWrapper->
widget();
 
 2740      newWidgetInfo.labelText = elementDef->
name();
 
 2741      newWidgetInfo.labelOnTop = 
false;
 
 2742      newWidgetInfo.showLabel = widgetDef->
showLabel();
 
 2753      mWidgets.append( spacerWrapper );
 
 2755      newWidgetInfo.widget = spacerWrapper->
widget();
 
 2756      newWidgetInfo.labelOnTop = 
false;
 
 2757      newWidgetInfo.showLabel = 
false;
 
 2762      QgsDebugError( QStringLiteral( 
"Unknown attribute editor widget type encountered..." ) );
 
 2766  return newWidgetInfo;
 
 2769void QgsAttributeForm::createWrappers()
 
 2771  QList<QWidget *> myWidgets = findChildren<QWidget *>();
 
 2772  const QList<QgsField> fields = mLayer->
fields().
toList();
 
 2774  const auto constMyWidgets = myWidgets;
 
 2775  for ( QWidget *myWidget : constMyWidgets )
 
 2778    QVariant vRel = myWidget->property( 
"qgisRelation" );
 
 2779    if ( vRel.isValid() )
 
 2789        mWidgets.append( rww );
 
 2794      const auto constFields = fields;
 
 2795      for ( 
const QgsField &field : constFields )
 
 2797        if ( field.name() == myWidget->objectName() )
 
 2802          mWidgets.append( eww );
 
 2809void QgsAttributeForm::afterWidgetInit()
 
 2811  bool isFirstEww = 
true;
 
 2813  const auto constMWidgets = mWidgets;
 
 2822        setFocusProxy( eww->
widget() );
 
 2832      if ( relationWidgetWrapper )
 
 2845  if ( e->type() == QEvent::KeyPress )
 
 2847    QKeyEvent *keyEvent = 
dynamic_cast<QKeyEvent *
>( e );
 
 2848    if ( keyEvent && keyEvent->key() == Qt::Key_Escape )
 
 
 2860    QSet< int > &mixedValueFields,
 
 2861    QHash< int, QVariant > &fieldSharedValues )
 const 
 2863  mixedValueFields.clear();
 
 2864  fieldSharedValues.clear();
 
 2870    for ( 
int i = 0; i < mLayer->
fields().count(); ++i )
 
 2872      if ( mixedValueFields.contains( i ) )
 
 2877        fieldSharedValues[i] = f.
attribute( i );
 
 2881        if ( fieldSharedValues.value( i ) != f.
attribute( i ) )
 
 2883          fieldSharedValues.remove( i );
 
 2884          mixedValueFields.insert( i );
 
 2890    if ( mixedValueFields.count() == mLayer->
fields().
count() )
 
 2899void QgsAttributeForm::layerSelectionChanged()
 
 2912      resetMultiEdit( 
true );
 
 2919  mIsSettingMultiEditFeatures = 
true;
 
 2920  mMultiEditFeatureIds = fids;
 
 2922  if ( fids.isEmpty() )
 
 2925    QMultiMap< int, QgsAttributeFormEditorWidget * >::const_iterator wIt = mFormEditorWidgets.constBegin();
 
 2926    for ( ; wIt != mFormEditorWidgets.constEnd(); ++ wIt )
 
 2928      wIt.value()->initialize( QVariant() );
 
 2930    mIsSettingMultiEditFeatures = 
false;
 
 2937  QSet< int > mixedValueFields;
 
 2938  QHash< int, QVariant > fieldSharedValues;
 
 2939  scanForEqualAttributes( fit, mixedValueFields, fieldSharedValues );
 
 2948  if ( mCurrentFormFeature.
id() != firstFeature.
id( ) )
 
 2953  const auto constMixedValueFields = mixedValueFields;
 
 2954  for ( 
int fieldIndex : std::as_const( mixedValueFields ) )
 
 2956    const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( fieldIndex );
 
 2957    if ( formEditorWidgets.isEmpty() )
 
 2960    const QStringList additionalFields = formEditorWidgets.first()->editorWidget()->additionalFields();
 
 2961    QVariantList additionalFieldValues;
 
 2962    for ( 
const QString &additionalField : additionalFields )
 
 2963      additionalFieldValues << firstFeature.
attribute( additionalField );
 
 2966      w->initialize( firstFeature.
attribute( fieldIndex ), 
true, additionalFieldValues );
 
 2968  QHash< int, QVariant >::const_iterator sharedValueIt = fieldSharedValues.constBegin();
 
 2969  for ( ; sharedValueIt != fieldSharedValues.constEnd(); ++sharedValueIt )
 
 2971    const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( sharedValueIt.key() );
 
 2972    if ( formEditorWidgets.isEmpty() )
 
 2976    const QStringList additionalFields = formEditorWidgets.first()->editorWidget()->additionalFields();
 
 2977    for ( 
const QString &additionalField : additionalFields )
 
 2980      if ( constMixedValueFields.contains( index ) )
 
 2987    QVariantList additionalFieldValues;
 
 2990      for ( 
const QString &additionalField : additionalFields )
 
 2991        additionalFieldValues << firstFeature.
attribute( additionalField );
 
 2993        w->initialize( firstFeature.
attribute( sharedValueIt.key() ), 
true, additionalFieldValues );
 
 2997      for ( 
const QString &additionalField : additionalFields )
 
 3000        Q_ASSERT( fieldSharedValues.contains( index ) );
 
 3001        additionalFieldValues << fieldSharedValues.value( index );
 
 3004        w->initialize( sharedValueIt.value(), 
false, additionalFieldValues );
 
 3008  setMultiEditFeatureIdsRelations( fids );
 
 3010  mIsSettingMultiEditFeatures = 
false;
 
 
 3015  if ( mOwnsMessageBar )
 
 3017  mOwnsMessageBar = 
false;
 
 3018  mMessageBar = messageBar;
 
 
 3028  QStringList filters;
 
 3031    QString filter = widget->currentFilterExpression();
 
 3032    if ( !filter.isNull() )
 
 3033      filters << 
'(' + filter + 
')';
 
 3036  return filters.join( QLatin1String( 
" AND " ) );
 
 
 3041  mExtraContextScope.reset( extraScope );
 
 
 3047  const bool newVisibility = expression.evaluate( expressionContext ).toBool();
 
 3049  if ( expression.isValid() && ! expression.hasEvalError() && newVisibility != isVisible )
 
 3057      widget->setVisible( newVisibility );
 
 3060    isVisible = newVisibility;
 
 3063  const bool newCollapsedState = collapsedExpression.evaluate( expressionContext ).toBool();
 
 3065  if ( collapsedExpression.isValid() && ! collapsedExpression.hasEvalError() && newCollapsedState != isCollapsed )
 
 3070      collapsibleGroupBox->
setCollapsed( newCollapsedState );
 
 3071      isCollapsed = newCollapsedState;
 
 3085  if ( infos.count() == 0 || !currentFormValuesFeature( formFeature ) )
 
 3088  const QString hint = tr( 
"No feature joined" );
 
 3089  const auto constInfos = infos;
 
 3092    if ( !info->isDynamicFormEnabled() )
 
 3097    mJoinedFeatures[info] = joinFeature;
 
 3099    if ( info->hasSubset() )
 
 3103      const auto constSubsetNames = subsetNames;
 
 3104      for ( 
const QString &field : constSubsetNames )
 
 3106        QString prefixedName = info->prefixedFieldName( field );
 
 3108        QString hintText = hint;
 
 3122      for ( 
const QgsField &field : joinFields )
 
 3124        QString prefixedName = info->prefixedFieldName( field );
 
 3126        QString hintText = hint;
 
 3140bool QgsAttributeForm::fieldIsEditable( 
int fieldIndex )
 const 
 3145void QgsAttributeForm::updateFieldDependencies()
 
 3147  mDefaultValueDependencies.clear();
 
 3148  mVirtualFieldsDependencies.clear();
 
 3149  mRelatedLayerFieldsDependencies.clear();
 
 3158    updateFieldDependenciesDefaultValue( eww );
 
 3159    updateFieldDependenciesVirtualFields( eww );
 
 3160    updateRelatedLayerFieldsDependencies( eww );
 
 3168  if ( exp.needsGeometry() )
 
 3169    mNeedsGeometry = 
true;
 
 3176    for ( 
const int id : allAttributeIds )
 
 3178      mDefaultValueDependencies.insertMulti( 
id, eww );
 
 3184    const QSet<QString> referencedColumns = exp.referencedColumns();
 
 3185    for ( 
const QString &referencedColumn : referencedColumns )
 
 3187      mDefaultValueDependencies.insertMulti( mLayer->
fields().
lookupField( referencedColumn ), eww );
 
 3195  if ( expressionField.isEmpty() )
 
 3200  if ( exp.needsGeometry() )
 
 3201    mNeedsGeometry = 
true;
 
 3208    for ( 
const int id : allAttributeIds )
 
 3210      mVirtualFieldsDependencies.insertMulti( 
id, eww );
 
 3216    const QSet<QString> referencedColumns = exp.referencedColumns();
 
 3217    for ( 
const QString &referencedColumn : referencedColumns )
 
 3219      mVirtualFieldsDependencies.insertMulti( mLayer->
fields().
lookupField( referencedColumn ), eww );
 
 3229    if ( expressionField.contains( QStringLiteral( 
"relation_aggregate" ) )
 
 3230         || expressionField.contains( QStringLiteral( 
"get_features" ) ) )
 
 3231      mRelatedLayerFieldsDependencies.insert( eww );
 
 3235    mRelatedLayerFieldsDependencies.clear();
 
 3240      if ( ! editorWidgetWrapper )
 
 3243      updateRelatedLayerFieldsDependencies( editorWidgetWrapper );
 
 3248void QgsAttributeForm::setMultiEditFeatureIdsRelations( 
const QgsFeatureIds &fids )
 
 3253    if ( !relationEditorWidget )
 
 3266  mIconMap[eww->
widget()]->hide();
 
 3280        const QString file = QStringLiteral( 
"/mIconJoinNotEditable.svg" );
 
 3281        const QString tooltip = tr( 
"Join settings do not allow editing" );
 
 3282        reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
 
 3286        const QString file = QStringLiteral( 
"mIconJoinHasNotUpsertOnEdit.svg" );
 
 3287        const QString tooltip = tr( 
"Join settings do not allow upsert on edit" );
 
 3288        reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
 
 3292        const QString file = QStringLiteral( 
"/mIconJoinedLayerNotEditable.svg" );
 
 3293        const QString tooltip = tr( 
"Joined layer is not toggled editable" );
 
 3294        reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
 
 3300void QgsAttributeForm::reloadIcon( 
const QString &file, 
const QString &tooltip, QSvgWidget *sw )
 
 3303  sw->setToolTip( tooltip );
 
@ Row
A row of editors (horizontal layout)
 
@ File
Load the Python code from an external file.
 
@ Environment
Use the Python code available in the Python environment.
 
@ NoSource
Do not use Python code at all.
 
@ Dialog
Use the Python code provided in the dialog.
 
@ DragAndDrop
"Drag and drop" layout. Needs to be configured.
 
@ UiFile
Load a .ui file for the layout. Needs to be configured.
 
@ Warning
Warning message.
 
@ Info
Information message.
 
@ Success
Used for reporting a successful operation.
 
@ Join
Field originates from a joined layer.
 
@ Action
A layer action element (since QGIS 3.22)
 
@ QmlElement
A QML element.
 
@ HtmlElement
A HTML element.
 
@ TextElement
A text element (since QGIS 3.30)
 
@ SpacerElement
A spacer element (since QGIS 3.30)
 
SelectBehavior
Specifies how a selection should be applied.
 
@ SetSelection
Set selection, removing any existing selection.
 
@ AddToSelection
Add selection to current selection.
 
@ IntersectSelection
Modify current selection to include only select features which match.
 
@ RemoveFromSelection
Remove from current selection.
 
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application's network content registry used for fetching temporary files during QGIS sess...
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
 
This element will load a layer action onto the form.
 
const QgsAction & action(const QgsVectorLayer *layer) const
Returns the (possibly lazy loaded) action for the given layer.
 
This is a container for attribute editors, used to group them visually in the attribute form if it is...
 
QgsOptionalExpression visibilityExpression() const
The visibility expression is used in the attribute form to show or hide this container based on an ex...
 
QgsOptionalExpression collapsedExpression() const
The collapsed expression is used in the attribute form to set the collapsed status of the group box c...
 
bool collapsed() const
For group box containers returns true if this group box is collapsed.
 
Qgis::AttributeEditorContainerType type() const
Returns the container type.
 
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
 
QColor backgroundColor() const
Returns the background color of the container.
 
int columnCount() const
Gets the number of columns in this group.
 
This class contains context information for attribute editor widgets.
 
FormMode formMode() const
Returns the form mode.
 
QString attributeFormModeString() const
Returns given attributeFormMode as string.
 
QgsFeature parentFormFeature() const
Returns the feature of the currently edited parent form in its actual state.
 
@ Embed
A form was embedded as a widget on another form.
 
bool allowCustomUi() const
Returns true if the attribute editor should permit use of custom UI forms.
 
@ SearchMode
Form values are used for searching/filtering the layer.
 
@ FixAttributeMode
Fix feature mode, for modifying the feature attributes without saving. The updated feature is availab...
 
@ IdentifyMode
Identify the feature.
 
@ SingleEditMode
Single edit mode, for editing a single feature.
 
@ AggregateSearchMode
Form is in aggregate search mode, show each widget in this mode.
 
@ MultiEditMode
Multi edit mode, for editing fields of multiple features at once.
 
void setAttributeFormMode(const Mode &attributeFormMode)
Set attributeFormMode for the edited form.
 
This is an abstract base class for any elements of a drag and drop form.
 
LabelStyle labelStyle() const
Returns the label style.
 
Qgis::AttributeEditorType type() const
The type of this element.
 
bool showLabel() const
Controls if this element should be labeled with a title (field, relation or groupname).
 
QString name() const
Returns the name of this element.
 
This element will load a field's widget onto the form.
 
int idx() const
Returns the index of the field.
 
An attribute editor widget that will represent arbitrary HTML code.
 
QString htmlCode() const
The Html code that will be represented within this widget.
 
An attribute editor widget that will represent arbitrary QML code.
 
QString qmlCode() const
The QML code that will be represented within this widget.
 
This element will load a relation editor onto the form.
 
const QgsRelation & relation() const
Gets the id of the relation which shall be embedded.
 
QVariantMap relationEditorConfiguration() const
Returns the relation editor widget configuration.
 
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
 
bool forceSuppressFormPopup() const
Determines the force suppress form popup status.
 
QString relationWidgetTypeId() const
Returns the current relation widget type id.
 
QString label() const
Determines the label of this element.
 
An attribute editor widget that will represent a spacer.
 
bool drawLine() const
Returns true if the spacer element will contain an horizontal line.
 
An attribute editor widget that will represent arbitrary text code.
 
QString text() const
The Text that will be represented within this widget.
 
A groupbox that collapses/expands when toggled.
 
void setStyleSheet(const QString &style)
Overridden to prepare base call and avoid crash due to specific QT versions.
 
void setCollapsed(bool collapse)
Collapse or uncollapse this groupbox.
 
A groupbox that collapses/expands when toggled and can save its collapsed and checked states.
 
Single scope for storing variables and functions for use within a QgsExpressionContext.
 
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
 
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
 
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
 
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
 
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
 
Class for parsing and evaluation of expressions (formerly called "search strings").
 
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
 
Wrapper for iterator of features from vector data provider or vector layer.
 
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
 
This class wraps a request for features to a vector layer (or directly its vector data provider).
 
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
 
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
 
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
 
void setValid(bool validity)
Sets the validity of the feature.
 
bool isValid() const
Returns the validity of this feature.
 
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
 
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
 
ConstraintOrigin
Origin of constraints.
 
@ ConstraintOriginNotSet
Constraint is not set.
 
@ ConstraintOriginLayer
Constraint was set by layer.
 
QString constraintExpression() const
Returns the constraint expression for the field, if set.
 
static QString fieldToolTipExtended(const QgsField &field, const QgsVectorLayer *layer)
Returns a HTML formatted tooltip string for a field, containing details like the field name,...
 
Encapsulate a field in an attribute table or data source.
 
QString displayName() const
Returns the name to use when displaying this field.
 
QgsDefaultValue defaultValueDefinition
 
QgsFieldConstraints constraints
 
Container of fields for a vector layer.
 
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
 
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
 
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
 
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
 
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
 
Q_INVOKABLE bool exists(int i) const
Returns if a field index is valid.
 
int size() const
Returns number of items.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
A geometry is the spatial representation of a feature.
 
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
 
static bool pythonMacroAllowed(void(*lambda)()=nullptr, QgsMessageBar *messageBar=nullptr)
Returns true if python macros are currently allowed to be run If the global option is to ask user,...
 
static void warning(const QString &msg)
Goes to qWarning.
 
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
 
void editingStarted()
Emitted when editing on this layer has started.
 
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
 
Represents an item shown within a QgsMessageBar widget.
 
A bar for displaying non-blocking messages to the user.
 
bool popWidget(QgsMessageBarItem *item)
Remove the specified item from the bar, and display the next most recent one in the stack.
 
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
 
void pushItem(QgsMessageBarItem *item)
Display a message item on the bar, after hiding the currently visible one and putting it in a stack.
 
QFile * localFile(const QString &filePathOrUrl)
Returns a QFile from a local file or to a temporary file previously fetched by the registry.
 
bool enabled() const
Check if this optional is enabled.
 
T data() const
Access the payload data.
 
QgsRelationManager * relationManager
 
static QgsProject * instance()
Returns the QgsProject singleton instance.
 
bool hasProperty(int key) const final
Returns true if the collection contains a property with the specified key.
 
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
 
A store for object properties.
 
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement.
 
static bool eval(const QString &command, QString &result)
Eval a Python statement.
 
This class manages a set of relations between layers.
 
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
 
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
 
bool isInvalidJSON()
Returns whether the text edit widget contains Invalid JSON.
 
Wraps a label widget to display text.
 
bool needsGeometry() const
Returns true if the widget needs feature geometry.
 
void setText(const QString &text)
Sets the text code to htmlCode.
 
void reinitWidget()
Clears the content and makes new initialization.
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
 
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
 
QList< const QgsVectorLayerJoinInfo * > joinsWhereFieldIsId(const QgsField &field) const
Returns joins where the field of a target layer is considered as an id.
 
QgsFeature joinedFeatureOf(const QgsVectorLayerJoinInfo *info, const QgsFeature &feature) const
Returns the joined feature corresponding to the feature.
 
Defines left outer join from our vector layer to some other vector layer.
 
QStringList * joinFieldNamesSubset() const
Returns the subset of fields to be used from joined layer.
 
bool isDynamicFormEnabled() const
Returns whether the form has to be dynamically updated with joined fields when a feature is being cre...
 
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
 
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
 
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet)
 
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Tests whether a field is editable for a particular feature.
 
Represents a vector layer which manages a vector based data sets.
 
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
 
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer.
 
Q_INVOKABLE bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes an attribute value for a feature (but does not immediately commit the changes).
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
QString expressionField(int index) const
Returns the expression used for a given expression field.
 
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
 
Q_INVOKABLE void selectByExpression(const QString &expression, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection, QgsExpressionContext *context=nullptr)
Selects matching features using an expression.
 
void endEditCommand()
Finish edit command and add it to undo/redo stack.
 
void destroyEditCommand()
Destroy active command and reverts all changes in it.
 
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
 
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
 
QgsVectorLayerJoinBuffer * joinBuffer()
Returns the join buffer object.
 
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
 
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
 
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer.
 
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
 
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
 
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
 
QgsEditFormConfig editFormConfig
 
void beforeModifiedCheck() const
Emitted when the layer is checked for modifications. Use for last-minute additions.
 
Q_INVOKABLE bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes attributes' values for a feature (but does not immediately commit the changes).
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
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...
 
#define Q_NOWARN_DEPRECATED_POP
 
#define Q_NOWARN_DEPRECATED_PUSH
 
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
 
QMap< int, QVariant > QgsAttributeMap
 
QSet< QgsFeatureId > QgsFeatureIds
 
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)