18#include "moc_qgsattributesformmodel.cpp"
35 if ( !layer || idx < 0 || idx >= layer->
fields().
count() )
53QgsAttributesFormData::FieldConfig::operator QVariant()
55 return QVariant::fromValue<QgsAttributesFormData::FieldConfig>( *
this );
58QgsAttributesFormData::RelationEditorConfiguration::operator QVariant()
60 return QVariant::fromValue<QgsAttributesFormData::RelationEditorConfiguration>( *
this );
65 return mContainerType;
70 mContainerType = type;
80 mLabelStyle = labelStyle;
90 mShowLabel = showLabel;
95 return mVisibilityExpression;
100 mVisibilityExpression = visibilityExpression;
105 return mCollapsedExpression;
110 mCollapsedExpression = collapsedExpression;
115 return mRelationEditorConfiguration;
120 mRelationEditorConfiguration = relationEditorConfiguration;
125 return mQmlElementEditorConfiguration;
130 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
136 return mHtmlElementEditorConfiguration;
141 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
146 return mSpacerElementEditorConfiguration;
151 mSpacerElementEditorConfiguration = spacerElementEditorConfiguration;
156 return mBackgroundColor;
161 mBackgroundColor = backgroundColor;
166 return mTextElementEditorConfiguration;
171 mTextElementEditorConfiguration = textElementEditorConfiguration;
177 , mDisplayName( displayName )
184 , mDisplayName( displayName )
193 return mChildren.at(
row ).get();
200 if ( !mChildren.empty() && itemId.trimmed().isEmpty() )
204 const auto it = std::find_if( mChildren.cbegin(), mChildren.cend(), [itemType, itemId](
const std::unique_ptr< QgsAttributesFormItem > &item ) {
205 return item->type() == itemType && item->id() == itemId;
208 if ( it != mChildren.cend() )
216 if ( !mChildren.empty() && itemId.trimmed().isEmpty() )
219 for (
const auto &
child : std::as_const( mChildren ) )
237 return static_cast< int >( mChildren.size() );
245 const auto it = std::find_if( mParent->mChildren.cbegin(), mParent->mChildren.cend(), [
this](
const std::unique_ptr< QgsAttributesFormItem > &item ) {
246 return item.get() == this;
249 if ( it != mParent->mChildren.cend() )
251 return static_cast< int >( std::distance( mParent->mChildren.cbegin(), it ) );
262 if ( !item->mParent )
263 item->mParent =
this;
265 mChildren.push_back( std::move( item ) );
270 if ( position < 0 || position >
static_cast< int >( mChildren.size() ) || !item )
273 if ( !item->mParent )
274 item->mParent =
this;
276 mChildren.insert( mChildren.begin() + position, std::move( item ) );
281 if ( index >= 0 && index <
static_cast< int >( mChildren.size() ) )
282 mChildren.erase( mChildren.begin() + index );
297 return QVariant::fromValue( mData );
305 return QVariant::fromValue( mFieldConfigData );
322 mName = value.toString();
327 mDisplayName = value.toString();
337 mId = value.toString();
352 : QAbstractItemModel( parent )
355 , mProject( project )
363 if (
index.isValid() )
378 return parentItem ? parentItem->
childCount() : 0;
391 for (
int i = 0; i < std::min( pathA.size(), pathB.size() ); i++ )
393 if ( pathA.at( i ) != pathB.at( i ) )
395 return pathA.at( i ) < pathB.at( i );
399 return pathA.size() < pathB.size();
414 if ( !hasIndex( row, column,
parent ) )
415 return QModelIndex();
419 return QModelIndex();
422 return createIndex( row, column, childItem );
424 return QModelIndex();
429 if ( !
index.isValid() )
430 return QModelIndex();
435 return ( parentItem !=
mRootItem.get() && parentItem !=
nullptr )
436 ? createIndex( parentItem->
row(), 0, parentItem )
443 return item ? createIndex( item->
row(), 0, item ) : QModelIndex();
449 return item ? createIndex( item->
row(), 0, item ) : QModelIndex();
469 const QModelIndex childIndex =
index( i, 0,
parent );
470 if ( hasChildren( childIndex ) )
485 if ( !
index.isValid() )
486 return Qt::NoItemFlags;
488 Qt::ItemFlags
flags = Qt::ItemIsEnabled;
493 flags =
flags | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable;
502 return orientation == Qt::Horizontal && role == Qt::DisplayRole ? tr(
"Available Widgets" ) : QVariant {};
518 for (
int i = 0; i < fields.
size(); ++i )
522 itemData.setShowLabel(
true );
526 auto item = std::make_unique< QgsAttributesFormItem >();
535 itemFields->addChild( std::move( item ) );
538 mRootItem->addChild( std::move( itemFields ) );
550 if ( polymorphicRelation.
isValid() )
552 name = QStringLiteral(
"%1 (%2)" ).arg( relation.name(), polymorphicRelation.
name() );
556 name = relation.
name();
561 auto itemRelation = std::make_unique< QgsAttributesFormItem >();
564 itemRelation->setData(
ItemIdRole, relation.id() );
566 itemRelations->addChild( std::move( itemRelation ) );
569 mRootItem->addChild( std::move( itemRelations ) );
574 mRootItem->addChild( std::move( itemActions ) );
584 itemOtherWidgets->addChild( std::move( itemQml ) );
588 auto itemHtml = std::make_unique< QgsAttributesFormItem >(
QgsAttributesFormData::HtmlWidget, itemHtmlData, QStringLiteral(
"HTML Widget" ), tr(
"HTML Widget" ) );
589 itemOtherWidgets->addChild( std::move( itemHtml ) );
593 auto itemText = std::make_unique< QgsAttributesFormItem >(
QgsAttributesFormData::TextWidget, itemTextData, QStringLiteral(
"Text Widget" ), tr(
"Text Widget" ) );
594 itemOtherWidgets->addChild( std::move( itemText ) );
599 itemOtherWidgets->addChild( std::move( itemSpacer ) );
601 mRootItem->addChild( std::move( itemOtherWidgets ) );
611 beginRemoveRows( actionsIndex, 0, itemActions->
childCount() );
616 for (
const auto &action : std::as_const( actions ) )
618 if ( action.isValid() && action.runable() && ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) || action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
626 beginInsertRows( actionsIndex, 0, count - 1 );
627 populateActionItems( actions );
632void QgsAttributesAvailableWidgetsModel::populateActionItems(
const QList<QgsAction> actions )
637 for (
const auto &action : std::as_const( actions ) )
639 if ( action.isValid() && action.runable() && ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) || action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
641 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
646 auto itemAction = std::make_unique< QgsAttributesFormItem >();
647 itemAction->setData(
ItemIdRole, action.id().toString() );
652 itemActions->
addChild( std::move( itemAction ) );
659 if ( !
index.isValid() )
668 bool invalidRelation =
false;
676 case Qt::DisplayRole:
686 case Qt::ToolTipRole:
691 if ( !cfg.mAlias.isEmpty() )
692 return tr(
"%1 (%2)" ).arg( item->
name(), cfg.mAlias );
700 return tr(
"Invalid relation" );
706 case Qt::DecorationRole:
709 case Qt::BackgroundRole:
712 return QBrush( Qt::lightGray );
717 case Qt::ForegroundRole:
723 return QBrush( QColor( Qt::lightGray ) );
729 return QBrush( QColor( 255, 0, 0 ) );
741 QFont font = QFont();
742 font.setItalic(
true );
755 return item->
data( role );
764 if ( !
index.isValid() )
768 bool result = item->
setData( role, value );
778 return Qt::CopyAction;
783 return QStringList() << QStringLiteral(
"application/x-qgsattributesformavailablewidgetsrelement" );
788 if ( indexes.count() == 0 )
792 if ( types.isEmpty() )
795 QMimeData *
data =
new QMimeData();
796 const QString format = types.at( 0 );
798 QDataStream stream( &encoded, QIODevice::WriteOnly );
801 QModelIndexList sortedIndexes = indexes;
803 std::sort( sortedIndexes.begin(), sortedIndexes.end(), [
this](
const QModelIndex &a,
const QModelIndex &b ) {
804 return indexLessThan( a, b );
807 for (
const QModelIndex &
index : std::as_const( sortedIndexes ) )
809 if (
index.isValid() )
815 stream << itemId << itemType << itemName;
819 data->setData( format, encoded );
830 return createIndex( row, 0, item );
832 return QModelIndex();
842 return createIndex( row, 0, item );
844 return QModelIndex();
854 return createIndex( row, 0, item );
856 return QModelIndex();
862 return QModelIndex();
866 return QModelIndex();
869 return item ? createIndex( item->
row(), 0, item ) : QModelIndex();
881 return orientation == Qt::Horizontal && role == Qt::DisplayRole ? tr(
"Form Layout" ) : QVariant {};
886 if ( !
index.isValid() )
887 return Qt::ItemIsDropEnabled;
889 Qt::ItemFlags
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
893 flags |= Qt::ItemIsDropEnabled;
909 loadAttributeEditorElementItem( editorElement,
mRootItem.get() );
924 auto editorItem = std::make_unique< QgsAttributesFormItem >();
926 switch ( editorElement->
type() )
931 setCommonProperties( itemData );
939 if ( fieldIndex != -1 )
951 if ( action.isValid() )
954 setCommonProperties( itemData );
956 editorItem->setData(
ItemIdRole, action.id().toString() );
957 editorItem->setData(
ItemNameRole, action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
971 setCommonProperties( itemData );
979 relationEditorConfig.
label = relationEditor->
label();
983 if ( relation.
id().isEmpty() )
1002 setCommonProperties( itemData );
1021 const QList<QgsAttributeEditorElement *> children = container->
children();
1024 loadAttributeEditorElementItem( childElement, editorItem.get() );
1033 setCommonProperties( itemData );
1049 setCommonProperties( itemData );
1065 setCommonProperties( itemData );
1068 textEdConfig.
text = textElementEditor->
text();
1081 setCommonProperties( itemData );
1096 QgsDebugError( QStringLiteral(
"Not loading invalid attribute editor type..." ) );
1101 if ( position >= 0 && position < parent->childCount() )
1103 parent->insertChild( position, std::move( editorItem ) );
1107 parent->addChild( std::move( editorItem ) );
1113 if ( !
index.isValid() )
1127 const bool invalidField = fieldIndex == -1;
1131 bool invalidRelation =
false;
1139 case Qt::DisplayRole:
1145 if ( item->
id().isEmpty() )
1147 return tr(
"Invalid relation" );
1153 return item->
name();
1159 case Qt::ToolTipRole:
1165 return tr(
"Invalid field" );
1169 return item->
name();
1175 if ( !item->
id().isEmpty() )
1178 return tr(
"Invalid relation" );
1185 case Qt::DecorationRole:
1186 return item->
icon();
1188 case Qt::BackgroundRole:
1191 return QBrush( Qt::lightGray );
1196 case Qt::ForegroundRole:
1202 return QBrush( QColor( 255, 0, 0 ) );
1206 return QBrush( QColor( Qt::lightGray ) );
1212 if ( invalidRelation )
1214 return QBrush( QColor( 255, 0, 0 ) );
1218 return QBrush( QColor( Qt::lightGray ) );
1231 QFont font = QFont();
1232 font.setItalic(
true );
1241 QFont font = QFont();
1242 font.setItalic(
true );
1255 return item->
data( role );
1264 if ( !
index.isValid() )
1271 bool result = item->
setData( role, value );
1289 beginRemoveRows(
parent, row, row + count - 1 );
1290 for (
int r = 0; r < count; ++r )
1298 beginRemoveRows(
parent, row, row );
1307 return Qt::MoveAction;
1312 return Qt::DropAction::CopyAction | Qt::DropAction::MoveAction;
1317 return QStringList() << QStringLiteral(
"application/x-qgsattributesformlayoutelement" ) << QStringLiteral(
"application/x-qgsattributesformavailablewidgetsrelement" );
1320QModelIndexList QgsAttributesFormLayoutModel::curateIndexesForMimeData(
const QModelIndexList &indexes )
const
1322 QModelIndexList containerList;
1323 for (
const auto index : indexes )
1328 containerList <<
index;
1332 if ( containerList.size() == 0 )
1335 QModelIndexList curatedIndexes;
1338 for (
const auto index : indexes )
1341 bool redundantChild =
false;
1343 while (
parent.isValid() )
1345 if ( containerList.contains(
parent ) )
1347 redundantChild =
true;
1354 if ( !redundantChild )
1355 curatedIndexes <<
index;
1358 return curatedIndexes;
1363 if ( indexes.count() == 0 )
1367 QModelIndexList curatedIndexes;
1368 if ( indexes.count() > 1 )
1370 curatedIndexes = curateIndexesForMimeData( indexes );
1374 curatedIndexes = indexes;
1378 if ( types.isEmpty() )
1381 QMimeData *
data =
new QMimeData();
1382 const QString format = types.at( 0 );
1384 QDataStream stream( &encoded, QIODevice::WriteOnly );
1387 std::sort( curatedIndexes.begin(), curatedIndexes.end(), [
this](
const QModelIndex &a,
const QModelIndex &b ) {
1388 return indexLessThan( a, b );
1391 for (
const QModelIndex &
index : std::as_const( curatedIndexes ) )
1393 if (
index.isValid() )
1397 QDomElement rootElem = doc.createElement( QStringLiteral(
"form_layout_mime" ) );
1400 rootElem.appendChild( editorElem );
1402 doc.appendChild( rootElem );
1403 stream << doc.toString( -1 );
1407 data->setData( format, encoded );
1414 bool isDropSuccessful =
false;
1420 if ( action == Qt::IgnoreAction )
1422 isDropSuccessful =
true;
1424 else if (
data->hasFormat( QStringLiteral(
"application/x-qgsattributesformavailablewidgetsrelement" ) ) )
1426 Q_ASSERT( action == Qt::CopyAction );
1427 QByteArray itemData =
data->data( QStringLiteral(
"application/x-qgsattributesformavailablewidgetsrelement" ) );
1428 QDataStream stream( &itemData, QIODevice::ReadOnly );
1430 while ( !stream.atEnd() )
1435 stream >> itemId >> itemTypeInt >> itemName;
1440 isDropSuccessful =
true;
1442 QModelIndex addedIndex =
index( row + rows, 0,
parent );
1448 else if (
data->hasFormat( QStringLiteral(
"application/x-qgsattributesformlayoutelement" ) ) )
1450 Q_ASSERT( action == Qt::MoveAction );
1451 QByteArray itemData =
data->data( QStringLiteral(
"application/x-qgsattributesformlayoutelement" ) );
1452 QDataStream stream( &itemData, QIODevice::ReadOnly );
1454 while ( !stream.atEnd() )
1460 if ( !doc.setContent( text ) )
1462 const QDomElement rootElem = doc.documentElement();
1463 if ( rootElem.tagName() != QLatin1String(
"form_layout_mime" ) || !rootElem.hasChildNodes() )
1465 const QDomElement childElem = rootElem.firstChild().toElement();
1469 beginInsertRows(
parent, row + rows, row + rows );
1473 isDropSuccessful =
true;
1475 QModelIndex addedIndex =
index( row + rows, 0,
parent );
1482 return isDropSuccessful;
1485void QgsAttributesFormLayoutModel::updateAliasForFieldItemsRecursive(
QgsAttributesFormItem *parent,
const QString &fieldName,
const QString &fieldAlias )
1487 for (
int i = 0; i <
parent->childCount(); i++ )
1493 const QModelIndex
index = createIndex( child->
row(), 0, child );
1499 updateAliasForFieldItemsRecursive( child, fieldName, fieldAlias );
1506 updateAliasForFieldItemsRecursive(
mRootItem.get(), fieldName, fieldAlias );
1509QList< QgsAddAttributeFormContainerDialog::ContainerPair > QgsAttributesFormLayoutModel::recursiveListOfContainers(
QgsAttributesFormItem *parent )
const
1511 QList< QgsAddAttributeFormContainerDialog::ContainerPair > containerList;
1512 for (
int i = 0; i <
parent->childCount(); i++ )
1522 containerList.append( recursiveListOfContainers( child ) );
1526 return containerList;
1538 switch ( indexType )
1575 bool isTopLevel = !
index.parent().isValid();
1587 QModelIndex childIndex;
1595 widgetDef = container;
1603 widgetDef = element;
1611 widgetDef = element;
1619 widgetDef = element;
1627 widgetDef = element;
1649 return recursiveListOfContainers(
mRootItem.get() );
1658 std::unique_ptr< QgsAttributesFormItem > containerItem = std::make_unique< QgsAttributesFormItem >(
QgsAttributesFormData::Container, name, QString(), parentItem );
1666 parentItem->
addChild( std::move( containerItem ) );
1676 beginInsertRows(
parent, row, row );
1677 std::unique_ptr< QgsAttributesFormItem > item = std::make_unique< QgsAttributesFormItem >();
1689 : QSortFilterProxyModel( parent )
1696 QSortFilterProxyModel::setSourceModel( mModel );
1716 if ( mFilterText.isEmpty() )
1719 QModelIndex sourceIndex = sourceModel()->index( sourceRow, 0, sourceParent );
1720 if ( !sourceIndex.isValid() )
1728 QModelIndex parent = sourceIndex.
parent();
1729 while ( parent.isValid() )
1734 parent = parent.
parent();
AttributeEditorContainerType
Attribute editor container types.
@ Action
A layer action element.
@ QmlElement
A QML element.
@ HtmlElement
A HTML element.
@ TextElement
A text element.
@ SpacerElement
A spacer element.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QgsAction action(QUuid id) const
Gets an action by its id.
Utility class that encapsulates an action based on vector attributes.
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.
A container for attribute editors, used to group them visually in the attribute form if it is set to ...
virtual void addChildElement(QgsAttributeEditorElement *element)
Add a child element to this container.
QgsOptionalExpression visibilityExpression() const
The visibility expression is used in the attribute form to show or hide this container based on an ex...
void setColumnCount(int columnCount)
Set the number of columns in this group.
void setVisibilityExpression(const QgsOptionalExpression &visibilityExpression)
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.
void setType(Qgis::AttributeEditorContainerType type)
Sets the container type.
void setCollapsedExpression(const QgsOptionalExpression &collapsedExpression)
The collapsed expression is used in the attribute form to set the collapsed status of the group box o...
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
QColor backgroundColor() const
Returns the background color of the container.
void setCollapsed(bool collapsed)
For group box containers sets if this group box is collapsed.
int columnCount() const
Gets the number of columns in this group.
void setBackgroundColor(const QColor &backgroundColor)
Sets the background color to backgroundColor.
An abstract base class for any elements of a drag and drop form.
void setHorizontalStretch(int stretch)
Sets the horizontal stretch factor for the element.
QDomElement toDomElement(QDomDocument &doc) const
Gets the XML Dom element to save this element.
LabelStyle labelStyle() const
Returns the label style.
void setLabelStyle(const LabelStyle &labelStyle)
Sets the labelStyle.
Qgis::AttributeEditorType type() const
The type of this element.
int verticalStretch() const
Returns the vertical stretch factor for the 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.
static QgsAttributeEditorElement * create(const QDomElement &element, const QString &layerId, const QgsFields &fields, const QgsReadWriteContext &context, QgsAttributeEditorElement *parent=nullptr)
Constructs the editor element from the given element.
void setVerticalStretch(int stretch)
Sets the vertical stretch factor for the element.
void setShowLabel(bool showLabel)
Controls if this element should be labeled with a title (field, relation or groupname).
int horizontalStretch() const
Returns the horizontal stretch factor for the element.
This element will load a field's widget onto the form.
An attribute editor widget that will represent arbitrary HTML code.
QString htmlCode() const
The Html code that will be represented within this widget.
void setHtmlCode(const QString &htmlCode)
Sets the HTML code that will be represented within this widget to htmlCode.
An attribute editor widget that will represent arbitrary QML code.
QString qmlCode() const
The QML code that will be represented within this widget.
void setQmlCode(const QString &qmlCode)
Sets the QML code that will be represented within this widget to qmlCode.
This element will load a relation editor onto the form.
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
void setRelationWidgetTypeId(const QString &relationWidgetTypeId)
Sets the relation widget type.
const QgsRelation & relation() const
Gets the id of the relation which shall be embedded.
QVariantMap relationEditorConfiguration() const
Returns the relation editor widget configuration.
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup.
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.
void setRelationEditorConfiguration(const QVariantMap &config)
Sets the relation editor configuration.
void setLabel(const QString &label=QString())
Sets label for this element If it's empty it takes the relation id as label.
QString label() const
Determines the label of this element.
An attribute editor widget that will represent a spacer.
void setDrawLine(bool drawLine)
Sets a flag to define if the spacer element will contain an horizontal line.
bool drawLine() const
Returns true if the spacer element will contain an horizontal line.
An attribute editor widget that will represent arbitrary text code.
void setText(const QString &text)
Sets the text that will be represented within this widget to text.
QString text() const
The Text that will be represented within this widget.
Encapsulate a field in an attribute table or data source.
Qgis::FieldDomainSplitPolicy splitPolicy() const
Returns the field's split policy, which indicates how field values should be handled during a split o...
Qgis::FieldDuplicatePolicy duplicatePolicy() const
Returns the field's duplicate policy, which indicates how field values should be handled during a dup...
Qgis::FieldDomainMergePolicy mergePolicy() const
Returns the field's merge policy, which indicates how field values should be handled during a merge o...
QgsFieldConstraints constraints
Container of fields for a vector layer.
Q_INVOKABLE int indexOf(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).
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.
QIcon iconForField(int fieldIdx, bool considerOrigin=false) const
Returns an icon corresponding to a field index, based on the field's type and source.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
An expression with an additional enabled flag.
A relation where the referenced (parent) layer is calculated based on fields from the referencing (ch...
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
A container for the context for various read/write operations on objects.
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.
Represents a relationship between two vector layers.
Represents a vector layer which manages a vector based dataset.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
QgsEditFormConfig editFormConfig
#define QgsDebugError(str)
The TabStyle struct defines color and font overrides for form fields, tabs and groups labels.