48 #include <QTextStream>    51 #include <QFormLayout>    52 #include <QGridLayout>    56 #include <QPushButton>    58 #include <QMessageBox>    59 #include <QToolButton>    62 int QgsAttributeForm::sFormCounter = 0;
    67   , mOwnsMessageBar( true )
    69   , mFormNr( sFormCounter++ )
    71   , mPreventFeatureRefresh( false )
    72   , mIsSettingMultiEditFeatures( false )
    73   , mUnsavedMultiEditChanges( false )
    74   , mEditCommandMessage( tr( 
"Attributes changed" ) )
    87   updateContainersVisibility();
    93   qDeleteAll( mInterfaces );
   120   mInterfaces.append( iface );
   136     if ( mUnsavedMultiEditChanges )
   139       int res = QMessageBox::question( 
this, tr( 
"Multiedit Attributes" ),
   140                                        tr( 
"Apply changes to edited features?" ), QMessageBox::Yes | QMessageBox::No );
   141       if ( res == QMessageBox::Yes )
   146     clearMultiEditMessages();
   148   mUnsavedMultiEditChanges = 
false;
   196     w->setContext( newContext );
   202     w->setVisible( relationWidgetsVisible );
   209       mSearchButtonBox->setVisible( 
false );
   213       synchronizeEnabledState();
   214       mSearchButtonBox->setVisible( 
false );
   218       resetMultiEdit( 
false );
   219       synchronizeEnabledState();
   220       mSearchButtonBox->setVisible( 
false );
   224       mSearchButtonBox->setVisible( 
true );
   229       mSearchButtonBox->setVisible( 
false );
   235       mSearchButtonBox->setVisible( 
false );
   244   const auto constMWidgets = mWidgets;
   259         QVariant mainValue = eww->
value();
   261         additionalFieldValues[index] = value;
   262         eww->
setValues( mainValue, additionalFieldValues );
   271   mIsSettingFeature = 
true;
   282       synchronizeEnabledState();
   286       mIsSettingFeature = 
false;
   287       const auto constMInterfaces = mInterfaces;
   290         iface->featureChanged();
   306   mIsSettingFeature = 
false;
   309 bool QgsAttributeForm::saveEdits()
   312   bool changedLayer = 
false;
   317     bool doUpdate = 
false;
   338         QVariantList dstVars = QVariantList() << dst.at( eww->
fieldIdx() );
   339         QVariantList srcVars = QVariantList() << eww->
value();
   340         QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
   344         for ( 
const QString &fieldName : additionalFields )
   348           dstVars << dst.at( idx );
   352         Q_ASSERT( dstVars.count() == srcVars.count() );
   354         for ( 
int i = 0; i < dstVars.count(); i++ )
   357           if ( !
qgsVariantEqual( dstVars[i], srcVars[i] ) && srcVars[i].isValid() && fieldIsEditable( fieldIndexes[i] ) )
   359             dst[fieldIndexes[i]] = srcVars[i];
   369     const auto constMInterfaces = mInterfaces;
   372       if ( !iface->acceptChanges( updatedFeature ) )
   384         bool res = mLayer->
addFeature( updatedFeature );
   403         for ( 
int i = 0; i < dst.count(); ++i )
   406                || !dst.at( i ).isValid()                 
   407                || !fieldIsEditable( i ) )                
   412           QgsDebugMsg( QStringLiteral( 
"Updating field %1" ).arg( i ) );
   413           QgsDebugMsg( QStringLiteral( 
"dst:'%1' (type:%2, isNull:%3, isValid:%4)" )
   414                        .arg( dst.at( i ).toString(), dst.at( i ).typeName() ).arg( dst.at( i ).isNull() ).arg( dst.at( i ).isValid() ) );
   415           QgsDebugMsg( QStringLiteral( 
"src:'%1' (type:%2, isNull:%3, isValid:%4)" )
   416                        .arg( src.at( i ).toString(), src.at( i ).typeName() ).arg( src.at( i ).isNull() ).arg( src.at( i ).isValid() ) );
   418           newValues[i] = dst.at( i );
   419           oldValues[i] = src.at( i );
   426         if ( success && n > 0 )
   453 bool QgsAttributeForm::updateDefaultValues( 
const int originIdx )
   457   updateDefaultValueDependencies();
   459   if ( !mDefaultValueDependencies.contains( originIdx ) )
   472         QVariantList dstVars = QVariantList() << dst.at( eww->
fieldIdx() );
   473         QVariantList srcVars = QVariantList() << eww->
value();
   474         QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
   478         for ( 
const QString &fieldName : additionalFields )
   482           dstVars << dst.at( idx );
   486         Q_ASSERT( dstVars.count() == srcVars.count() );
   488         for ( 
int i = 0; i < dstVars.count(); i++ )
   491           if ( !
qgsVariantEqual( dstVars[i], srcVars[i] ) && srcVars[i].isValid() && fieldIsEditable( fieldIndexes[i] ) )
   493             dst[fieldIndexes[i]] = srcVars[i];
   501     QList<QgsWidgetWrapper *> relevantWidgets = mDefaultValueDependencies.values( originIdx );
   514         if ( mAlreadyUpdatedFields.contains( eww->
fieldIdx() ) )
   525 void QgsAttributeForm::resetMultiEdit( 
bool promptToSave )
   530   mUnsavedMultiEditChanges = 
false;
   534 void QgsAttributeForm::multiEditMessageClicked( 
const QString &link )
   536   clearMultiEditMessages();
   537   resetMultiEdit( link == QLatin1String( 
"#apply" ) );
   540 void QgsAttributeForm::filterTriggered()
   542   QString filter = createFilterExpression();
   548 void QgsAttributeForm::searchZoomTo()
   550   QString filter = createFilterExpression();
   551   if ( filter.isEmpty() )
   557 void QgsAttributeForm::searchFlash()
   559   QString filter = createFilterExpression();
   560   if ( filter.isEmpty() )
   566 void QgsAttributeForm::filterAndTriggered()
   568   QString filter = createFilterExpression();
   569   if ( filter.isEmpty() )
   577 void QgsAttributeForm::filterOrTriggered()
   579   QString filter = createFilterExpression();
   580   if ( filter.isEmpty() )
   588 void QgsAttributeForm::pushSelectedFeaturesMessage()
   594                               tr( 
"%n matching feature(s) selected", 
"matching features", count ),
   601                               tr( 
"No matching features found" ),
   617   QString filter = createFilterExpression();
   618   if ( filter.isEmpty() )
   622   pushSelectedFeaturesMessage();
   627 void QgsAttributeForm::searchSetSelection()
   632 void QgsAttributeForm::searchAddToSelection()
   637 void QgsAttributeForm::searchRemoveFromSelection()
   642 void QgsAttributeForm::searchIntersectSelection()
   647 bool QgsAttributeForm::saveMultiEdits()
   651   QMap< int, QgsAttributeFormEditorWidget * >::const_iterator wIt = mFormEditorWidgets.constBegin();
   652   for ( ; wIt != mFormEditorWidgets.constEnd(); ++ wIt )
   659          || !fieldIsEditable( wIt.key() ) ) 
   667     newAttributeValues.insert( wIt.key(), w->
currentValue() );
   670   if ( newAttributeValues.isEmpty() )
   678   int res = QMessageBox::information( 
this, tr( 
"Multiedit Attributes" ),
   679                                       tr( 
"Edits will be applied to all selected features." ), QMessageBox::Ok | QMessageBox::Cancel );
   680   if ( res != QMessageBox::Ok )
   691   const auto constMMultiEditFeatureIds = mMultiEditFeatureIds;
   694     QgsAttributeMap::const_iterator aIt = newAttributeValues.constBegin();
   695     for ( ; aIt != newAttributeValues.constEnd(); ++aIt )
   701   clearMultiEditMessages();
   714   if ( !mButtonBox->isVisible() )
   715     mMessageBar->
pushItem( mMultiEditMessageBarItem );
   726     wrapper->notifyAboutToSave();
   764       success = saveEdits();
   768       success = saveMultiEdits();
   773   mUnsavedMultiEditChanges = 
false;
   781   mValuesInitialized = 
false;
   782   const auto constMWidgets = mWidgets;
   785     ww->setFeature( mFeature );
   787   mValuesInitialized = 
true;
   793   const auto widgets { findChildren<  QgsAttributeFormEditorWidget * >() };
   800 void QgsAttributeForm::clearMultiEditMessages()
   802   if ( mMultiEditUnsavedMessageBarItem )
   804     if ( !mButtonBox->isVisible() )
   805       mMessageBar->
popWidget( mMultiEditUnsavedMessageBarItem );
   806     mMultiEditUnsavedMessageBarItem = 
nullptr;
   808   if ( mMultiEditMessageBarItem )
   810     if ( !mButtonBox->isVisible() )
   811       mMessageBar->
popWidget( mMultiEditMessageBarItem );
   812     mMultiEditMessageBarItem = 
nullptr;
   816 QString QgsAttributeForm::createFilterExpression()
 const   821     QString filter = w->currentFilterExpression();
   822     if ( !filter.isEmpty() )
   826   if ( filters.isEmpty() )
   829   QString filter = filters.join( QStringLiteral( 
") AND (" ) ).prepend( 
'(' ).append( 
')' );
   834 void QgsAttributeForm::onAttributeChanged( 
const QVariant &value, 
const QVariantList &additionalFieldValues )
   839   bool signalEmitted = 
false;
   841   if ( mValuesInitialized )
   857       for ( 
int i = 0; i < additionalFields.count(); i++ )
   859         const QString fieldName = additionalFields.at( i );
   860         const QVariant value = additionalFieldValues.at( i );
   864       signalEmitted = 
true;
   866       updateJoinedFields( *eww );
   872       if ( !mIsSettingMultiEditFeatures )
   874         mUnsavedMultiEditChanges = 
true;
   876         QLabel *msgLabel = 
new QLabel( tr( 
"Unsaved multiedit changes: <a href=\"#apply\">apply changes</a> or <a href=\"#reset\">reset changes</a>." ), mMessageBar );
   877         msgLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
   878         msgLabel->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
   879         connect( msgLabel, &QLabel::linkActivated, 
this, &QgsAttributeForm::multiEditMessageClicked );
   880         clearMultiEditMessages();
   883         if ( !mButtonBox->isVisible() )
   884           mMessageBar->
pushItem( mMultiEditUnsavedMessageBarItem );
   894   updateConstraints( eww );
   897   mAlreadyUpdatedFields.append( eww->
fieldIdx() );
   898   updateDefaultValues( eww->
fieldIdx() );
   899   mAlreadyUpdatedFields.removeAll( eww->
fieldIdx() );
   901   if ( !signalEmitted )
   910 void QgsAttributeForm::updateAllConstraints()
   912   const auto constMWidgets = mWidgets;
   917       updateConstraints( eww );
   925   if ( currentFormFeature( ft ) )
   937     updateConstraint( ft, eww );
   940     const QList<QgsEditorWidgetWrapper *> deps = constraintDependencies( eww );
   943       updateConstraint( ft, depsEww );
   946     synchronizeEnabledState();
   953     const QVector<ContainerInformation *> infos = mContainerInformationDependency.value( eww->
field().
name() );
   954     for ( ContainerInformation *info : infos )
   956       info->apply( &mExpressionContext );
   961 void QgsAttributeForm::updateContainersVisibility()
   965   const QVector<ContainerInformation *> infos = mContainerVisibilityInformation;
   967   for ( ContainerInformation *info : infos )
   969     info->apply( &mExpressionContext );
   973   updateAllConstraints();
   987       if ( mJoinedFeatures.contains( info ) )
  1017     if ( dst.count() > eww->
fieldIdx() )
  1019       QVariantList dstVars = QVariantList() << dst.at( eww->
fieldIdx() );
  1020       QVariantList srcVars = QVariantList() << eww->
value();
  1021       QList<int> fieldIndexes = QList<int>() << eww->
fieldIdx();
  1025       for ( 
const QString &fieldName : additionalFields )
  1028         fieldIndexes << idx;
  1029         dstVars << dst.at( idx );
  1033       Q_ASSERT( dstVars.count() == srcVars.count() );
  1035       for ( 
int i = 0; i < dstVars.count(); i++ )
  1039         if ( ( !
qgsVariantEqual( dstVars[i], srcVars[i] ) || dstVars[i].isNull() != srcVars[i].isNull() ) && srcVars[i].isValid() )
  1041           dst[fieldIndexes[i]] = srcVars[i];
  1058 void QgsAttributeForm::registerContainerInformation( QgsAttributeForm::ContainerInformation *info )
  1060   mContainerVisibilityInformation.append( info );
  1062   const QSet<QString> referencedColumns = info->expression.referencedColumns();
  1064   for ( 
const QString &col : referencedColumns )
  1066     mContainerInformationDependency[ col ].append( info );
  1070 bool QgsAttributeForm::currentFormValidConstraints( QStringList &invalidFields, QStringList &descriptions )
  1094 void QgsAttributeForm::onAttributeAdded( 
int idx )
  1096   mPreventFeatureRefresh = 
false;
  1100     attrs.insert( idx, QVariant( 
layer()->fields().at( idx ).type() ) );
  1108 void QgsAttributeForm::onAttributeDeleted( 
int idx )
  1110   mPreventFeatureRefresh = 
false;
  1114     attrs.remove( idx );
  1122 void QgsAttributeForm::onUpdatedFields()
  1124   mPreventFeatureRefresh = 
false;
  1136           attrs[i].convert( 
layer()->fields().at( i ).type() );
  1141         attrs[i] = QVariant( 
layer()->fields().at( i ).type() );
  1151 void QgsAttributeForm::onConstraintStatusChanged( 
const QString &constraint,
  1159   if ( formEditorWidget )
  1165   QList<QgsEditorWidgetWrapper *> wDeps;
  1177       if ( name != ewwName )
  1184         for ( 
const QString &colName : referencedColumns )
  1186           if ( name == colName )
  1188             wDeps.append( eww );
  1209 void QgsAttributeForm::preventFeatureRefresh()
  1211   mPreventFeatureRefresh = 
true;
  1228 void QgsAttributeForm::synchronizeEnabledState()
  1230   bool isEditable = ( mFeature.
isValid()
  1246       bool enabled = isEditable && fieldIsEditable( eww->
fieldIdx() );
  1247       ww->setEnabled( enabled );
  1255     QStringList invalidFields, descriptions;
  1256     bool validConstraint = currentFormValidConstraints( invalidFields, descriptions );
  1258     isEditable = isEditable & validConstraint;
  1262   QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
  1264     okButton->setEnabled( isEditable );
  1267 void QgsAttributeForm::init()
  1269   QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
  1272   QWidget *formWidget = 
nullptr;
  1274   bool buttonBoxVisible = 
true;
  1278     buttonBoxVisible = mButtonBox->isVisible();
  1280     mButtonBox = 
nullptr;
  1283   if ( mSearchButtonBox )
  1285     delete mSearchButtonBox;
  1286     mSearchButtonBox = 
nullptr;
  1289   qDeleteAll( mWidgets );
  1292   while ( QWidget *w = this->findChild<QWidget *>() )
  1298   QVBoxLayout *vl = 
new QVBoxLayout();
  1300   vl->setContentsMargins( 0, 0, 0, 0 );
  1302   mMessageBar->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
  1303   vl->addWidget( mMessageBar );
  1308   QGridLayout *layout = 
new QGridLayout();
  1309   QWidget *container = 
new QWidget();
  1310   container->setLayout( layout );
  1311   vl->addWidget( container );
  1313   mFormEditorWidgets.clear();
  1314   mFormWidgets.clear();
  1317   setContentsMargins( 0, 0, 0, 0 );
  1326     if ( file && file->open( QFile::ReadOnly ) )
  1330       QFileInfo fi( file->fileName() );
  1331       loader.setWorkingDirectory( fi.dir() );
  1332       formWidget = loader.load( file, 
this );
  1335         formWidget->setWindowFlags( Qt::Widget );
  1336         layout->addWidget( formWidget );
  1339         mButtonBox = findChild<QDialogButtonBox *>();
  1342         formWidget->installEventFilter( 
this );
  1354     int columnCount = 1;
  1363         if ( !containerDef )
  1368           tabWidget = 
nullptr;
  1369           WidgetInfo widgetInfo = createWidgetFromDef( widgDef, formWidget, mLayer, mContext );
  1370           layout->addWidget( widgetInfo.widget, row, column, 1, 2 );
  1373             registerContainerInformation( 
new ContainerInformation( widgetInfo.widget, containerDef->
visibilityExpression().
data() ) );
  1382             layout->addWidget( tabWidget, row, column, 1, 2 );
  1386           QWidget *tabPage = 
new QWidget( tabWidget );
  1388           tabWidget->addTab( tabPage, widgDef->name() );
  1392             registerContainerInformation( 
new ContainerInformation( tabWidget, tabPage, containerDef->
visibilityExpression().
data() ) );
  1394           QGridLayout *tabPageLayout = 
new QGridLayout();
  1395           tabPage->setLayout( tabPageLayout );
  1397           WidgetInfo widgetInfo = createWidgetFromDef( widgDef, tabPage, mLayer, mContext );
  1398           tabPageLayout->addWidget( widgetInfo.widget );
  1403         tabWidget = 
nullptr;
  1404         WidgetInfo widgetInfo = createWidgetFromDef( widgDef, container, mLayer, mContext );
  1405         QLabel *label = 
new QLabel( widgetInfo.labelText );
  1406         label->setToolTip( widgetInfo.toolTip );
  1407         if ( columnCount > 1 && !widgetInfo.labelOnTop )
  1409           label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
  1412         label->setBuddy( widgetInfo.widget );
  1414         if ( !widgetInfo.showLabel )
  1416           QVBoxLayout *
c = 
new QVBoxLayout();
  1417           label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
  1418           c->addWidget( widgetInfo.widget );
  1419           layout->addLayout( c, row, column, 1, 2 );
  1422         else if ( widgetInfo.labelOnTop )
  1424           QVBoxLayout *
c = 
new QVBoxLayout();
  1425           label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
  1426           c->addWidget( label );
  1427           c->addWidget( widgetInfo.widget );
  1428           layout->addLayout( c, row, column, 1, 2 );
  1433           layout->addWidget( label, row, column++ );
  1434           layout->addWidget( widgetInfo.widget, row, column++ );
  1438       if ( column >= columnCount * 2 )
  1444     formWidget = container;
  1453     formWidget = 
new QWidget( 
this );
  1454     QGridLayout *gridLayout = 
new QGridLayout( formWidget );
  1455     formWidget->setLayout( gridLayout );
  1461       scrollArea->setWidget( formWidget );
  1462       scrollArea->setWidgetResizable( 
true );
  1463       scrollArea->setFrameShape( QFrame::NoFrame );
  1464       scrollArea->setFrameShadow( QFrame::Plain );
  1465       scrollArea->setFocusProxy( 
this );
  1466       layout->addWidget( scrollArea );
  1470       layout->addWidget( formWidget );
  1477     for ( 
const QgsField &field : fields )
  1485       QString labelText = fieldName;
  1486       labelText.replace( 
'&', QStringLiteral( 
"&&" ) ); 
  1490       if ( widgetSetup.
type() == QLatin1String( 
"Hidden" ) )
  1496       QLabel *l = 
new QLabel( labelText );
  1497       l->setToolTip( QStringLiteral( 
"<b>%1</b><p>%2</p>" ).arg( fieldName, field.comment() ) );
  1498       QSvgWidget *i = 
new QSvgWidget();
  1499       i->setFixedSize( 18, 18 );
  1503       QWidget *w = 
nullptr;
  1508         mFormEditorWidgets.insert( idx, formWidget );
  1509         mFormWidgets.append( formWidget );
  1512         l->setBuddy( eww->
widget() );
  1516         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() ) ) );
  1521         w->setObjectName( field.name() );
  1525         addWidgetWrapper( eww );
  1526         mIconMap[eww->
widget()] = i;
  1531         gridLayout->addWidget( l, row++, 0, 1, 2 );
  1532         gridLayout->addWidget( w, row++, 0, 1, 2 );
  1533         gridLayout->addWidget( i, row++, 0, 1, 2 );
  1537         gridLayout->addWidget( l, row, 0 );
  1538         gridLayout->addWidget( w, row, 1 );
  1539         gridLayout->addWidget( i, row++, 2 );
  1550       gridLayout->addWidget( formWidget, row++, 0, 1, 2 );
  1552       mWidgets.append( rww );
  1553       mFormWidgets.append( formWidget );
  1558       QSpacerItem *spacerItem = 
new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );
  1559       gridLayout->addItem( spacerItem, row, 0 );
  1560       gridLayout->setRowStretch( row, 1 );
  1565   updateDefaultValueDependencies();
  1569     mButtonBox = 
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
  1570     mButtonBox->setObjectName( QStringLiteral( 
"buttonBox" ) );
  1571     layout->addWidget( mButtonBox, layout->rowCount(), 0, 1, layout->columnCount() );
  1573   mButtonBox->setVisible( buttonBoxVisible );
  1575   if ( !mSearchButtonBox )
  1577     mSearchButtonBox = 
new QWidget();
  1578     QHBoxLayout *boxLayout = 
new QHBoxLayout();
  1579     boxLayout->setMargin( 0 );
  1580     boxLayout->setContentsMargins( 0, 0, 0, 0 );
  1581     mSearchButtonBox->setLayout( boxLayout );
  1582     mSearchButtonBox->setObjectName( QStringLiteral( 
"searchButtonBox" ) );
  1584     QPushButton *clearButton = 
new QPushButton( tr( 
"&Reset Form" ), mSearchButtonBox );
  1586     boxLayout->addWidget( clearButton );
  1587     boxLayout->addStretch( 1 );
  1589     QPushButton *flashButton = 
new QPushButton();
  1590     flashButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
  1591     flashButton->setText( tr( 
"&Flash Features" ) );
  1592     connect( flashButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchFlash );
  1593     boxLayout->addWidget( flashButton );
  1595     QPushButton *zoomButton = 
new QPushButton();
  1596     zoomButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
  1597     zoomButton->setText( tr( 
"&Zoom to Features" ) );
  1598     connect( zoomButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchZoomTo );
  1599     boxLayout->addWidget( zoomButton );
  1601     QToolButton *selectButton = 
new QToolButton();
  1602     selectButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
  1603     selectButton->setText( tr( 
"&Select Features" ) );
  1605     selectButton->setPopupMode( QToolButton::MenuButtonPopup );
  1606     selectButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
  1607     connect( selectButton, &QToolButton::clicked, 
this, &QgsAttributeForm::searchSetSelection );
  1608     QMenu *selectMenu = 
new QMenu( selectButton );
  1609     QAction *selectAction = 
new QAction( tr( 
"Select Features" ), selectMenu );
  1611     connect( selectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchSetSelection );
  1612     selectMenu->addAction( selectAction );
  1613     QAction *addSelectAction = 
new QAction( tr( 
"Add to Current Selection" ), selectMenu );
  1615     connect( addSelectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchAddToSelection );
  1616     selectMenu->addAction( addSelectAction );
  1617     QAction *deselectAction = 
new QAction( tr( 
"Remove from Current Selection" ), selectMenu );
  1619     connect( deselectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchRemoveFromSelection );
  1620     selectMenu->addAction( deselectAction );
  1621     QAction *filterSelectAction = 
new QAction( tr( 
"Filter Current Selection" ), selectMenu );
  1623     connect( filterSelectAction, &QAction::triggered, 
this, &QgsAttributeForm::searchIntersectSelection );
  1624     selectMenu->addAction( filterSelectAction );
  1625     selectButton->setMenu( selectMenu );
  1626     boxLayout->addWidget( selectButton );
  1630       QToolButton *filterButton = 
new QToolButton();
  1631       filterButton->setText( tr( 
"Filter Features" ) );
  1632       filterButton->setPopupMode( QToolButton::MenuButtonPopup );
  1633       filterButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
  1634       connect( filterButton, &QToolButton::clicked, 
this, &QgsAttributeForm::filterTriggered );
  1635       QMenu *filterMenu = 
new QMenu( filterButton );
  1636       QAction *filterAndAction = 
new QAction( tr( 
"Filter Within (\"AND\")" ), filterMenu );
  1637       connect( filterAndAction, &QAction::triggered, 
this, &QgsAttributeForm::filterAndTriggered );
  1638       filterMenu->addAction( filterAndAction );
  1639       QAction *filterOrAction = 
new QAction( tr( 
"Extend Filter (\"OR\")" ), filterMenu );
  1640       connect( filterOrAction, &QAction::triggered, 
this, &QgsAttributeForm::filterOrTriggered );
  1641       filterMenu->addAction( filterOrAction );
  1642       filterButton->setMenu( filterMenu );
  1643       boxLayout->addWidget( filterButton );
  1647       QPushButton *closeButton = 
new QPushButton( tr( 
"Close" ), mSearchButtonBox );
  1649       closeButton->setShortcut( Qt::Key_Escape );
  1650       boxLayout->addWidget( closeButton );
  1653     layout->addWidget( mSearchButtonBox );
  1671   const auto constMInterfaces = mInterfaces;
  1682   QApplication::restoreOverrideCursor();
  1685 void QgsAttributeForm::cleanPython()
  1687   if ( !mPyFormVarName.isNull() )
  1689     QString expr = QStringLiteral( 
"if '%1' in locals(): del %1\n" ).arg( mPyFormVarName );
  1694 void QgsAttributeForm::initPython()
  1711         if ( !initFilePath.isEmpty() )
  1715           if ( inputFile && inputFile->open( QFile::ReadOnly ) )
  1718             QTextStream inf( inputFile );
  1719             initCode = inf.readAll();
  1724             QgsLogger::warning( QStringLiteral( 
"The external python file path %1 could not be opened!" ).arg( initFilePath ) );
  1735         if ( initCode.isEmpty() )
  1737           QgsLogger::warning( QStringLiteral( 
"The python code provided in the dialog is empty!" ) );
  1748     if ( !initCode.isEmpty() )
  1754                                   tr( 
"Python macro could not be run due to missing permissions." ),
  1755                                   Qgis::MessageLevel::Warning,
  1763     if ( 
QgsPythonRunner::eval( QStringLiteral( 
"len(inspect.getfullargspec(%1)[0])" ).arg( initFunction ), numArgs ) )
  1765       static int sFormId = 0;
  1766       mPyFormVarName = QStringLiteral( 
"_qgis_featureform_%1_%2" ).arg( mFormNr ).arg( sFormId++ );
  1768       QString form = QStringLiteral( 
"%1 = sip.wrapinstance( %2, qgis.gui.QgsAttributeForm )" )
  1769                      .arg( mPyFormVarName )
  1770                      .arg( ( quint64 ) 
this );
  1774       QgsDebugMsg( QStringLiteral( 
"running featureForm init: %1" ).arg( mPyFormVarName ) );
  1777       if ( numArgs == QLatin1String( 
"3" ) )
  1785         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 ) );
  1788         QString expr = QString( 
"%1(%2)" )
  1789                        .arg( mLayer->editFormInit() )
  1790                        .arg( mPyFormVarName );
  1791         QgsAttributeFormInterface *iface = QgsPythonRunner::evalToSipObject<QgsAttributeFormInterface *>( expr, 
"QgsAttributeFormInterface" );
  1801       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 ) );
  1809   WidgetInfo newWidgetInfo;
  1811   switch ( widgetDef->
type() )
  1821       if ( fldIdx < fields.
count() && fldIdx >= 0 )
  1827         mFormEditorWidgets.insert( fldIdx, formWidget );
  1828         mFormWidgets.append( formWidget );
  1832         newWidgetInfo.widget = formWidget;
  1833         addWidgetWrapper( eww );
  1835         newWidgetInfo.widget->setObjectName( fields.
at( fldIdx ).
name() );
  1836         newWidgetInfo.hint = fields.
at( fldIdx ).
comment();
  1841       newWidgetInfo.labelText.replace( 
'&', QStringLiteral( 
"&&" ) ); 
  1842       newWidgetInfo.toolTip = QStringLiteral( 
"<b>%1</b><p>%2</p>" ).arg( mLayer->
attributeDisplayName( fldIdx ), newWidgetInfo.hint );
  1843       newWidgetInfo.showLabel = widgetDef->
showLabel();
  1861       mWidgets.append( rww );
  1862       mFormWidgets.append( formWidget );
  1864       newWidgetInfo.widget = formWidget;
  1865       newWidgetInfo.labelText = QString();
  1866       newWidgetInfo.labelOnTop = 
true;
  1878       if ( columnCount <= 0 )
  1882       QWidget *myContainer = 
nullptr;
  1885         QGroupBox *groupBox = 
new QGroupBox( parent );
  1886         widgetName = QStringLiteral( 
"QGroupBox" );
  1888           groupBox->setTitle( container->
name() );
  1889         myContainer = groupBox;
  1890         newWidgetInfo.widget = myContainer;
  1894         myContainer = 
new QWidget();
  1900           scrollArea->setWidget( myContainer );
  1901           scrollArea->setWidgetResizable( 
true );
  1902           scrollArea->setFrameShape( QFrame::NoFrame );
  1903           widgetName = QStringLiteral( 
"QScrollArea QWidget" );
  1905           newWidgetInfo.widget = scrollArea;
  1909           newWidgetInfo.widget = myContainer;
  1910           widgetName = QStringLiteral( 
"QWidget" );
  1916         QString style {QStringLiteral( 
"background-color: %1;" ).arg( container->
backgroundColor().name() )};
  1917         newWidgetInfo.widget->setStyleSheet( style );
  1920       QGridLayout *gbLayout = 
new QGridLayout();
  1921       myContainer->setLayout( gbLayout );
  1926       const QList<QgsAttributeEditorElement *> children = container->
children();
  1930         WidgetInfo widgetInfo = createWidgetFromDef( childDef, myContainer, vl, context );
  1937             registerContainerInformation( 
new ContainerInformation( widgetInfo.widget, containerDef->
visibilityExpression().
data() ) );
  1941         if ( widgetInfo.labelText.isNull() )
  1943           gbLayout->addWidget( widgetInfo.widget, row, column, 1, 2 );
  1948           QLabel *mypLabel = 
new QLabel( widgetInfo.labelText );
  1949           mypLabel->setToolTip( widgetInfo.toolTip );
  1950           if ( columnCount > 1 && !widgetInfo.labelOnTop )
  1952             mypLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
  1955           mypLabel->setBuddy( widgetInfo.widget );
  1957           if ( widgetInfo.labelOnTop )
  1959             QVBoxLayout *
c = 
new QVBoxLayout();
  1960             mypLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
  1961             c->layout()->addWidget( mypLabel );
  1962             c->layout()->addWidget( widgetInfo.widget );
  1963             gbLayout->addLayout( c, row, column, 1, 2 );
  1968             gbLayout->addWidget( mypLabel, row, column++ );
  1969             gbLayout->addWidget( widgetInfo.widget, row, column++ );
  1973         if ( column >= columnCount * 2 )
  1979       QWidget *spacer = 
new QWidget();
  1980       spacer->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
  1981       gbLayout->addWidget( spacer, ++row, 0 );
  1982       gbLayout->setRowStretch( row, 1 );
  1984       newWidgetInfo.labelText = QString();
  1985       newWidgetInfo.labelOnTop = 
true;
  1999       mWidgets.append( qmlWrapper );
  2001       newWidgetInfo.widget = qmlWrapper->
widget();
  2002       newWidgetInfo.labelText = elementDef->
name();
  2003       newWidgetInfo.labelOnTop = 
true;
  2004       newWidgetInfo.showLabel = widgetDef->
showLabel();
  2018       mWidgets.append( htmlWrapper );
  2020       newWidgetInfo.widget = htmlWrapper->
widget();
  2021       newWidgetInfo.labelText = elementDef->
name();
  2022       newWidgetInfo.labelOnTop = 
true;
  2023       newWidgetInfo.showLabel = widgetDef->
showLabel();
  2028       QgsDebugMsg( QStringLiteral( 
"Unknown attribute editor widget type encountered..." ) );
  2032   newWidgetInfo.showLabel = widgetDef->
showLabel();
  2034   return newWidgetInfo;
  2055   mWidgets.append( eww );
  2058 void QgsAttributeForm::createWrappers()
  2060   QList<QWidget *> myWidgets = findChildren<QWidget *>();
  2061   const QList<QgsField> fields = mLayer->
fields().
toList();
  2063   const auto constMyWidgets = myWidgets;
  2064   for ( QWidget *myWidget : constMyWidgets )
  2067     QVariant vRel = myWidget->property( 
"qgisRelation" );
  2068     if ( vRel.isValid() )
  2078         mWidgets.append( rww );
  2083       const auto constFields = fields;
  2084       for ( 
const QgsField &field : constFields )
  2086         if ( field.name() == myWidget->objectName() )
  2091           addWidgetWrapper( eww );
  2098 void QgsAttributeForm::afterWidgetInit()
  2100   bool isFirstEww = 
true;
  2102   const auto constMWidgets = mWidgets;
  2111         setFocusProxy( eww->
widget() );
  2126   if ( e->type() == QEvent::KeyPress )
  2128     QKeyEvent *keyEvent = 
dynamic_cast<QKeyEvent *
>( e );
  2129     if ( keyEvent && keyEvent->key() == Qt::Key_Escape )
  2141     QSet< int > &mixedValueFields,
  2142     QHash< int, QVariant > &fieldSharedValues )
 const  2144   mixedValueFields.clear();
  2145   fieldSharedValues.clear();
  2151     for ( 
int i = 0; i < mLayer->
fields().
count(); ++i )
  2153       if ( mixedValueFields.contains( i ) )
  2158         fieldSharedValues[i] = f.
attribute( i );
  2162         if ( fieldSharedValues.value( i ) != f.
attribute( i ) )
  2164           fieldSharedValues.remove( i );
  2165           mixedValueFields.insert( i );
  2171     if ( mixedValueFields.count() == mLayer->
fields().
count() )
  2180 void QgsAttributeForm::layerSelectionChanged()
  2192       resetMultiEdit( 
true );
  2199   mIsSettingMultiEditFeatures = 
true;
  2200   mMultiEditFeatureIds = fids;
  2202   if ( fids.isEmpty() )
  2205     QMap< int, QgsAttributeFormEditorWidget * >::const_iterator wIt = mFormEditorWidgets.constBegin();
  2206     for ( ; wIt != mFormEditorWidgets.constEnd(); ++ wIt )
  2208       wIt.value()->initialize( QVariant() );
  2210     mIsSettingMultiEditFeatures = 
false;
  2217   QSet< int > mixedValueFields;
  2218   QHash< int, QVariant > fieldSharedValues;
  2219   scanForEqualAttributes( fit, mixedValueFields, fieldSharedValues );
  2226   const auto constMixedValueFields = mixedValueFields;
  2227   for ( 
int fieldIndex : qgis::as_const( mixedValueFields ) )
  2231       const QStringList additionalFields = w->editorWidget()->
additionalFields();
  2232       QVariantList additionalFieldValues;
  2233       for ( 
const QString &additionalField : additionalFields )
  2234         additionalFieldValues << firstFeature.
attribute( additionalField );
  2235       w->initialize( firstFeature.
attribute( fieldIndex ), 
true, additionalFieldValues );
  2238   QHash< int, QVariant >::const_iterator sharedValueIt = fieldSharedValues.constBegin();
  2239   for ( ; sharedValueIt != fieldSharedValues.constEnd(); ++sharedValueIt )
  2244       const QStringList additionalFields = w->editorWidget()->
additionalFields();
  2245       for ( 
const QString &additionalField : additionalFields )
  2248         if ( constMixedValueFields.contains( index ) )
  2255       QVariantList additionalFieldValues;
  2258         for ( 
const QString &additionalField : additionalFields )
  2259           additionalFieldValues << firstFeature.
attribute( additionalField );
  2260         w->initialize( firstFeature.
attribute( sharedValueIt.key() ), 
true, additionalFieldValues );
  2264         for ( 
const QString &additionalField : additionalFields )
  2267           Q_ASSERT( fieldSharedValues.contains( index ) );
  2268           additionalFieldValues << fieldSharedValues.value( index );
  2270         w->initialize( sharedValueIt.value(), 
false, additionalFieldValues );
  2274   mIsSettingMultiEditFeatures = 
false;
  2279   if ( mOwnsMessageBar )
  2281   mOwnsMessageBar = 
false;
  2282   mMessageBar = messageBar;
  2292   QStringList filters;
  2295     QString filter = widget->currentFilterExpression();
  2296     if ( !filter.isNull() )
  2297       filters << 
'(' + filter + 
')';
  2300   return filters.join( QStringLiteral( 
" AND " ) );
  2303 int QgsAttributeForm::messageTimeout()
  2306   return settings.
value( QStringLiteral( 
"qgis/messageTimeout" ), 5 ).toInt();
  2311   bool newVisibility = expression.evaluate( expressionContext ).toBool();
  2313   if ( newVisibility != isVisible )
  2317       tabWidget->setTabVisible( widget, newVisibility );
  2321       widget->setVisible( newVisibility );
  2324     isVisible = newVisibility;
  2337   if ( infos.count() == 0 || !currentFormFeature( formFeature ) )
  2340   const QString hint = tr( 
"No feature joined" );
  2341   const auto constInfos = infos;
  2344     if ( !info->isDynamicFormEnabled() )
  2349     mJoinedFeatures[info] = joinFeature;
  2351     if ( info->hasSubset() )
  2355       const auto constSubsetNames = subsetNames;
  2356       for ( 
const QString &field : constSubsetNames )
  2358         QString prefixedName = info->prefixedFieldName( field );
  2360         QString hintText = hint;
  2374       for ( 
const QgsField &field : joinFields )
  2376         QString prefixedName = info->prefixedFieldName( field );
  2378         QString hintText = hint;
  2392 bool QgsAttributeForm::fieldIsEditable( 
int fieldIndex )
 const  2397 void QgsAttributeForm::updateDefaultValueDependencies()
  2399   mDefaultValueDependencies.clear();
  2408       for ( 
const QString &referencedColumn : referencedColumns )
  2414           for ( 
const int id : allAttributeIds )
  2416             mDefaultValueDependencies.insertMulti( 
id, eww );
  2421           mDefaultValueDependencies.insertMulti( mLayer->
fields().
lookupField( referencedColumn ), eww );
  2434   mIconMap[eww->
widget()]->hide();
  2448         const QString file = QStringLiteral( 
"/mIconJoinNotEditable.svg" );
  2449         const QString tooltip = tr( 
"Join settings do not allow editing" );
  2450         reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
  2454         const QString file = QStringLiteral( 
"mIconJoinHasNotUpsertOnEdit.svg" );
  2455         const QString tooltip = tr( 
"Join settings do not allow upsert on edit" );
  2456         reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
  2460         const QString file = QStringLiteral( 
"/mIconJoinedLayerNotEditable.svg" );
  2461         const QString tooltip = tr( 
"Joined layer is not toggled editable" );
  2462         reloadIcon( file, tooltip, mIconMap[eww->
widget()] );
  2468 void QgsAttributeForm::reloadIcon( 
const QString &file, 
const QString &tooltip, QSvgWidget *sw )
  2471   sw->setToolTip( tooltip );
 int lookupField(const QString &fieldName) const
Looks up field's index from the field name. 
 
bool isValid() const
Returns the validity of this feature. 
 
Class for parsing and evaluation of expressions (formerly called "search strings"). 
 
Wrapper for iterator of features from vector data provider or vector layer. 
 
Constraint was set by layer. 
 
An attribute editor widget that will represent arbitrary QML code. 
 
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
 
QSet< QgsFeatureId > QgsFeatureIds
 
void setAttributeFormMode(const Mode &attributeFormMode)
Set attributeFormMode for the edited form. 
 
int size() const
Returns number of items. 
 
This is an abstract base class for any elements of a drag and drop form. 
 
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field's origin (value from an enumeration) 
 
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name. 
 
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication. 
 
bool enabled() const
Check if this optional is enabled. 
 
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations. 
 
This class is a composition of two QSettings instances: 
 
Form is in aggregate search mode, show each widget in this mode. 
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key. 
 
bool exists(int i) const
Returns if a field index is valid. 
 
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context. 
 
This class contains context information for attribute editor widgets. 
 
ConstraintOrigin
Origin of constraints. 
 
static void warning(const QString &msg)
Goes to qWarning. 
 
const QgsRelation & relation() const
Gets the id of the relation which shall be embedded. 
 
int selectedFeatureCount() const
Returns the number of features that are selected in this layer. 
 
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file. 
 
Remove from current selection. 
 
#define Q_NOWARN_DEPRECATED_PUSH
 
A bar for displaying non-blocking messages to the user. 
 
Container of fields for a vector layer. 
 
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon. 
 
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes. 
 
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer...
 
This element will load a field's widget onto the form. 
 
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...
 
This element will load a relation editor onto the form. 
 
Multi edit mode, for editing fields of multiple features at once. 
 
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression. 
 
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
 
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 feat...
 
int count() const
Returns number of items. 
 
An attribute editor widget that will represent arbitrary HTML code. 
 
AttributeEditorType type() const
The type of this element. 
 
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e. 
 
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1) 
 
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 isEditable() const FINAL
Returns true if the provider is in editing mode. 
 
int indexFromName(const QString &fieldName) const
Gets the field index from the field name. 
 
bool showUnlinkButton() const
Determines if the "unlink feature" button should be shown. 
 
QgsFields fields() const FINAL
Returns the list of fields of this layer. 
 
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer. 
 
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
 
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet) ...
 
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes. 
 
bool popWidget(QgsMessageBarItem *item)
Remove the passed widget from the bar (if previously added), then display the next one in the stack i...
 
QString displayName() const
Returns the name to use when displaying this field. 
 
void beforeModifiedCheck() const
Emitted when the layer is checked for modifications. Use for last-minute additions. 
 
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories...
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
Defines left outer join from our vector layer to some other vector layer. 
 
QMap< int, QVariant > QgsAttributeMap
 
void editingStopped()
Emitted when edited changes have been successfully written to the data provider. 
 
bool showLabel() const
Controls if this element should be labeled with a title (field, relation or groupname). 
 
This class wraps a request for features to a vector layer (or directly its vector data provider)...
 
void destroyEditCommand()
Destroy active command and reverts all changes in it. 
 
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes. 
 
QgsOptionalExpression visibilityExpression() const
The visibility expression is used in the attribute form to show or hide this container based on an ex...
 
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed. 
 
QString qmlCode() const
The QML code that will be represented within this widget. 
 
QList< const QgsVectorLayerJoinInfo * > joinsWhereFieldIsId(const QgsField &field) const
Returns joins where the field of a target layer is considered as an id. 
 
Encapsulate a field in an attribute table or data source. 
 
bool isInvalidJSON()
Returns whether the text edit widget contains Invalid JSON. 
 
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::Info, int duration=5)
convenience method for pushing a message to the bar 
 
QgsRelationManager relationManager
 
QgsEditFormConfig editFormConfig
 
Add selection to current selection. 
 
void editingStarted()
Emitted when editing on this layer has started. 
 
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container. 
 
void endEditCommand()
Finish edit command and add it to undo/redo stack. 
 
static bool eval(const QString &command, QString &result)
Eval a Python statement. 
 
QString htmlCode() const
The QML code that will be represented within this widget. 
 
QgsVectorLayerJoinBuffer * joinBuffer()
Returns the join buffer object. 
 
Set selection, removing any existing selection. 
 
FormMode formMode() const
Returns the form mode. 
 
QFile * localFile(const QString &filePathOrUrl)
Returns a QFile from a local file or to a temporary file previously fetched by the registry...
 
#define Q_NOWARN_DEPRECATED_POP
 
void setValid(bool validity)
Sets the validity of the feature. 
 
Modify current selection to include only select features which match. 
 
SelectBehavior
Selection behavior. 
 
QColor backgroundColor() const
backgroundColor 
 
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer. 
 
void pushItem(QgsMessageBarItem *item)
Display a message item on the bar after hiding the currently visible one and putting it in a stack...
 
bool allowCustomUi() const
Returns true if the attribute editor should permit use of custom UI forms. 
 
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement. 
 
This class manages a set of relations between layers. 
 
int columnCount() const
Gets the number of columns in this group. 
 
Single edit mode, for editing a single feature. 
 
static QgsProject * instance()
Returns the QgsProject singleton instance. 
 
Q_INVOKABLE void selectByExpression(const QString &expression, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects matching features using an expression. 
 
T data() const
Access the payload data. 
 
QList< QgsField > toList() const
Utility function to return a list of QgsField instances. 
 
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application's network content registry used for fetching temporary files during QGIS sess...
 
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index. 
 
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink. 
 
This is a container for attribute editors, used to group them visually in the attribute form if it is...
 
QgsFeature joinedFeatureOf(const QgsVectorLayerJoinInfo *info, const QgsFeature &feature) const
Returns the joined feature corresponding to the feature. 
 
QString attributeFormModeString() const
Returns given attributeFormMode as string. 
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request. 
 
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes). 
 
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer. ...
 
virtual bool isGroupBox() const
Returns if this container is going to be rendered as a group box. 
 
bool showLinkButton() const
Determines if the "link feature" button should be shown. 
 
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
 
bool nextFeature(QgsFeature &f)
 
Form values are used for searching/filtering the layer. 
 
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...
 
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap(), bool skipDefaultValues=false)
Changes attributes' values for a feature (but does not immediately commit the changes). 
 
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id. 
 
Represents a vector layer which manages a vector based data sets. 
 
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name. 
 
QString name() const
Returns the name of this element. 
 
void updatedFields()
Emitted whenever the fields available from this layer have been changed. 
 
bool isDynamicFormEnabled() const
Returns whether the form has to be dynamically updated with joined fields when a feature is being cre...
 
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1) 
 
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
 
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else...
 
QgsDefaultValue defaultValueDefinition
 
QStringList * joinFieldNamesSubset() const
Returns the subset of fields to be used from joined layer. 
 
A form was embedded as a widget on another form. 
 
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.