23#include "qgsattributeformcontaineredit.h"
27#include "qgsattributetypedialog.h"
28#include "qgsattributewidgetedit.h"
42#include "moc_qgsattributesformproperties.cpp"
44using namespace Qt::StringLiterals;
46#ifdef ENABLE_MODELTEST
51 =
new QgsSettingsEntryBool( u
"show-aliases"_s, sTreeAttributesForm,
false, u
"Whether to show aliases (true) or names (false) in both the Available Widgets and the Form Layout panels."_s );
56 , mSourceFieldsProperties( sourceFieldsProperties )
69 QGridLayout *availableWidgetsWidgetLayout =
new QGridLayout;
72 availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
73 mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout );
82 mAvailableWidgetsProxyModel->setAttributesFormSourceModel( mAvailableWidgetsModel );
83 mAvailableWidgetsProxyModel->setRecursiveFilteringEnabled(
true );
89#ifdef ENABLE_MODELTEST
90 new ModelTest( mAvailableWidgetsProxyModel,
this );
94 QGridLayout *formLayoutWidgetLayout =
new QGridLayout;
97 formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
98 mFormLayoutWidget->setLayout( formLayoutWidgetLayout );
106 mFormLayoutProxyModel->setAttributesFormSourceModel( mFormLayoutModel );
107 mFormLayoutProxyModel->setRecursiveFilteringEnabled(
true );
113#ifdef ENABLE_MODELTEST
114 new ModelTest( mFormLayoutProxyModel,
this );
117 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
118 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
120 connect(
mAvailableWidgetsView, &QWidget::customContextMenuRequested,
this, &QgsAttributesFormProperties::onContextMenuRequested );
122 connect( mAddContainerButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::addContainer );
123 connect( mRemoveLayoutItemButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::removeTabOrGroupButton );
124 connect( mInvertSelectionButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked );
125 connect( mShowAliasesButton, &QAbstractButton::toggled,
this, &QgsAttributesFormProperties::toggleShowAliases );
126 connect( mEditorLayoutComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged );
127 connect( pbnSelectEditForm, &QToolButton::clicked,
this, &QgsAttributesFormProperties::pbnSelectEditForm_clicked );
128 connect( mTbInitCode, &QPushButton::clicked,
this, &QgsAttributesFormProperties::mTbInitCode_clicked );
130 connect( mSearchLineEdit, &QgsFilterLineEdit::textChanged,
this, &QgsAttributesFormProperties::updateFilteredItems );
133 if ( !mBlockUpdates )
138 mAvailableWidgetsContextMenu =
new QMenu(
this );
139 mActionCopyWidgetConfiguration =
new QAction( tr(
"Copy widget configuration" ),
this );
140 mActionPasteWidgetConfiguration =
new QAction( tr(
"Paste widget configuration" ),
this );
142 connect( mActionCopyWidgetConfiguration, &QAction::triggered,
this, &QgsAttributesFormProperties::copyWidgetConfiguration );
143 connect( mActionPasteWidgetConfiguration, &QAction::triggered,
this, &QgsAttributesFormProperties::pasteWidgetConfiguration );
145 mAvailableWidgetsContextMenu->addAction( mActionCopyWidgetConfiguration );
146 mAvailableWidgetsContextMenu->addAction( mActionPasteWidgetConfiguration );
149 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
150 gridLayout->addWidget( mMessageBar, 0, 0 );
154 splitter->setSizes( { widget->minimumSizeHint().width(), 600 } );
156 if ( mSourceFieldsProperties )
158 connect( mFormPreviewButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::previewForm );
162 mFormPreviewButton->setVisible(
false );
184 mAvailableWidgetsModel->populate();
193 mFormLayoutView->setSelectionBehavior( QAbstractItemView::SelectRows );
194 mFormLayoutView->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
196 mFormLayoutView->setDragDropMode( QAbstractItemView::DragDropMode::DragDrop );
200 mFormLayoutModel->populate();
219 mFormSuppressCmbBx->setCurrentIndex( mFormSuppressCmbBx->findData( QVariant::fromValue(
mLayer->editFormConfig().suppress() ) ) );
224 mAvailableWidgetsModel->populateLayerActions( actions );
236 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( QVariant::fromValue(
mLayer->editFormConfig().layout() ) ) );
238 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
241 mEditFormLineEdit->setText( cfg.
uiForm() );
253 if ( mInitCode.isEmpty() )
255 mInitCode.append( tr(
256 "# -*- coding: utf-8 -*-\n\"\"\"\n"
257 "QGIS forms can have a Python function that is called when the form is\n"
260 "Use this function to add extra logic to your forms.\n"
262 "Enter the name of the function in the \"Python Init function\"\n"
264 "An example follows:\n"
266 "from qgis.PyQt.QtWidgets import QWidget\n\n"
267 "def my_form_open(dialog, layer, feature):\n"
268 " geom = feature.geometry()\n"
269 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n"
274void QgsAttributesFormProperties::loadAttributeTypeDialog()
285 if ( fieldIndex < 0 )
290 loadAttributeTypeDialogFromConfiguration( cfg );
293 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
337void QgsAttributesFormProperties::storeAttributeTypeDialog()
345 QgsAttributesFormData::FieldConfig cfg;
354 QgsFieldConstraints constraints;
397 const QString fieldName =
mLayer->fields().at( fieldIndex ).name();
399 QModelIndex index = mAvailableWidgetsModel->fieldModelIndex( fieldName );
400 if ( index.isValid() )
407 mFormLayoutModel->updateFieldConfigForFieldItems( fieldName, cfg );
413void QgsAttributesFormProperties::storeAttributeWidgetEdit()
422 storeAttributeWidgetEdit( index );
425void QgsAttributesFormProperties::storeAttributeWidgetEdit(
const QModelIndex &index )
430 if ( !index.isValid() )
438 QgsAttributesFormData::RelationEditorConfiguration config =
mAttributeWidgetEdit->updatedRelationConfiguration();
439 itemData.setRelationEditorConfiguration( config );
445void QgsAttributesFormProperties::loadAttributeWidgetEdit()
450 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
451 const QgsAttributesFormData::AttributeFormItemData itemData = currentIndex.data(
QgsAttributesFormModel::ItemDataRole ).value< QgsAttributesFormData::AttributeFormItemData >();
457 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
461void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
464 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
468void QgsAttributesFormProperties::storeAttributeContainerEdit()
476 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
477 storeAttributeContainerEdit( currentIndex );
480void QgsAttributesFormProperties::storeAttributeContainerEdit(
const QModelIndex &index )
485 if ( !index.isValid() )
489 QString containerName;
496void QgsAttributesFormProperties::loadAttributeContainerEdit()
501 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
502 const QgsAttributesFormData::AttributeFormItemData itemData = currentIndex.data(
QgsAttributesFormModel::ItemDataRole ).value< QgsAttributesFormData::AttributeFormItemData >();
509 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
513void QgsAttributesFormProperties::onAttributeSelectionChanged(
const QItemSelection &,
const QItemSelection & )
515 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
518 if (
mFormLayoutView->selectionModel()->selectedRows( 0 ).count() == 1 )
526 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
529void QgsAttributesFormProperties::onFormLayoutSelectionChanged(
const QItemSelection &,
const QItemSelection &deselected )
532 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
534 if ( deselected.indexes().count() == 1 )
536 index = mFormLayoutProxyModel->mapToSource( deselected.indexes().at( 0 ) );
538 else if ( deselected.indexes().count() == 0 &&
mFormLayoutView->selectionModel()->selectedIndexes().count() == 2 )
545 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
554 storeAttributeWidgetEdit( deselectedFormLayoutIndex );
555 storeAttributeContainerEdit( deselectedFormLayoutIndex );
559 storeAttributeTypeDialog();
562 clearAttributeTypeFrame();
564 if ( emitter->selectionModel()->selectedRows( 0 ).count() != 1 )
566 receiver->clearSelection();
579 loadAttributeWidgetEdit();
583 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
592 loadAttributeWidgetEdit();
594 loadAttributeTypeDialog();
599 receiver->clearSelection();
600 loadAttributeContainerEdit();
607 loadInfoWidget( action.
html() );
617 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
621 loadInfoWidget( tr(
"This configuration is available with double-click in the Form Layout panel" ) );
623 receiver->clearSelection();
628 receiver->clearSelection();
635void QgsAttributesFormProperties::clearAttributeTypeFrame()
663void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
666 for (
int i = 0; i < mFormLayoutProxyModel->rowCount(); ++i )
668 QModelIndex index = mFormLayoutProxyModel->index( i, 0 );
669 mFormLayoutView->selectionModel()->select( index, QItemSelectionModel::Toggle );
673void QgsAttributesFormProperties::toggleShowAliases(
bool checked )
676 mAvailableWidgetsModel->setShowAliases( checked );
677 mFormLayoutModel->setShowAliases( checked );
680void QgsAttributesFormProperties::addContainer()
682 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList = mFormLayoutModel->listOfContainers();
684 QModelIndex currentItem;
688 QgsAddAttributeFormContainerDialog dialog(
mLayer, existingContainerList, currentItem,
this );
690 if ( !dialog.exec() )
693 const QString name = dialog.name();
694 QModelIndex parentContainerItem = dialog.parentContainerItem();
696 mFormLayoutModel->addContainer( parentContainerItem, name, dialog.columnCount(), dialog.containerType() );
697 if ( parentContainerItem.isValid() )
701void QgsAttributesFormProperties::removeTabOrGroupButton()
707 const QModelIndexList items =
mFormLayoutView->selectionModel()->selectedRows();
711 const QModelIndex item = mFormLayoutProxyModel->mapToSource( items.at( 0 ) );
712 mFormLayoutModel->removeRow( item.row(), item.parent() );
716void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
720 if ( selection.count() > 0 )
734 mFormLayoutWidget->setVisible(
false );
735 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
736 mUiFileFrame->setVisible(
false );
737 mAddContainerButton->setVisible(
false );
738 mRemoveLayoutItemButton->setVisible(
false );
739 mInvertSelectionButton->setVisible(
false );
741 setAvailableWidgetsIndicatorProvidersEnabled(
true );
742 setFormLayoutIndicatorProvidersEnabled(
false );
746 mFormLayoutWidget->setVisible(
true );
747 mTreeViewHorizontalSpacer->changeSize( 6, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
748 mUiFileFrame->setVisible(
false );
749 mAddContainerButton->setVisible(
true );
750 mRemoveLayoutItemButton->setVisible(
true );
751 mInvertSelectionButton->setVisible(
true );
753 setAvailableWidgetsIndicatorProvidersEnabled(
false );
754 setFormLayoutIndicatorProvidersEnabled(
true );
759 mFormLayoutWidget->setVisible(
false );
760 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
761 mUiFileFrame->setVisible(
true );
762 mAddContainerButton->setVisible(
false );
763 mRemoveLayoutItemButton->setVisible(
false );
764 mInvertSelectionButton->setVisible(
false );
766 setAvailableWidgetsIndicatorProvidersEnabled(
true );
767 setFormLayoutIndicatorProvidersEnabled(
false );
772 if ( selection.count() > 0 )
778void QgsAttributesFormProperties::mTbInitCode_clicked()
780 QgsAttributesFormInitCode attributesFormInitCode;
787 if ( !attributesFormInitCode.exec() )
790 mInitCodeSource = attributesFormInitCode.
codeSource();
791 mInitCode = attributesFormInitCode.
initCode();
796void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
798 QgsSettings myQSettings;
799 const QString lastUsedDir = myQSettings.
value( u
"style/lastUIDir"_s, QDir::homePath() ).toString();
800 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
802 if ( uifilename.isNull() )
805 const QFileInfo fi( uifilename );
806 myQSettings.
setValue( u
"style/lastUIDir"_s, fi.path() );
807 mEditFormLineEdit->setText( uifilename );
812 storeAttributeWidgetEdit();
813 storeAttributeContainerEdit();
814 storeAttributeTypeDialog();
824void QgsAttributesFormProperties::applyToLayer(
QgsVectorLayer *layer )
829 const QModelIndex fieldContainer = mAvailableWidgetsModel->
fieldContainer();
832 for (
int i = 0; i < mAvailableWidgetsModel->
rowCount( fieldContainer ); i++ )
834 index = mAvailableWidgetsModel->
index( i, 0, fieldContainer );
893 for (
int t = 0; t < mFormLayoutModel->rowCount(); t++ )
895 QModelIndex index = mFormLayoutModel->index( t, 0 );
896 QgsAttributeEditorElement *editorElement { mFormLayoutModel->createAttributeEditorWidget( index,
nullptr ) };
898 editFormConfig.
addTab( editorElement );
901 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
913 const QModelIndex relationContainer = mAvailableWidgetsModel->relationContainer();
915 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( relationContainer ); i++ )
917 const QModelIndex relationIndex = mAvailableWidgetsModel->index( i, 0, relationContainer );
923 const QModelIndex layoutIndex = mFormLayoutModel->firstRecursiveMatchingModelIndex( indexType, indexId );
924 if ( layoutIndex.isValid() )
928 const QgsAttributesFormData::AttributeFormItemData tabIndexData = layoutIndex.data(
QgsAttributesFormModel::ItemDataRole ).value<QgsAttributesFormData::AttributeFormItemData>();
940void QgsAttributesFormProperties::updatedFields()
943 QMap<QString, QgsAttributesFormData::FieldConfig> fieldConfigs;
945 const QModelIndex fieldContainerBefore = mAvailableWidgetsModel->fieldContainer();
948 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerBefore ); i++ )
950 index = mAvailableWidgetsModel->index( i, 0, fieldContainerBefore );
953 fieldConfigs[fieldName] = config;
958 const QModelIndex fieldContainerAfter = mAvailableWidgetsModel->fieldContainer();
960 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerAfter ); i++ )
962 index = mAvailableWidgetsModel->index( i, 0, fieldContainerAfter );
965 if ( fieldConfigs.contains( fieldName ) )
973void QgsAttributesFormProperties::updateFilteredItems(
const QString &filterText )
975 const int availableWidgetsPreviousSelectionCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
976 const int formLayoutPreviousSelectionCount =
mFormLayoutView->selectionModel()->selectedRows().count();
978 static_cast< QgsAttributesAvailableWidgetsView *
>(
mAvailableWidgetsView )->setFilterText( filterText );
981 static_cast< QgsAttributesFormLayoutView *
>(
mFormLayoutView )->setFilterText( filterText );
986 if ( !( availableWidgetsPreviousSelectionCount == 0 && formLayoutPreviousSelectionCount == 0 ) )
988 const int selectedAvailableWidgetItemCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
989 const int selectedFormLayoutItemCount =
mFormLayoutView->selectionModel()->selectedRows().count();
991 if ( selectedAvailableWidgetItemCount == 0 && selectedFormLayoutItemCount == 0 )
994 clearAttributeTypeFrame();
999void QgsAttributesFormProperties::onContextMenuRequested( QPoint point )
1010 const QClipboard *clipboard = QApplication::clipboard();
1011 const QMimeData *mimeData = clipboard->mimeData();
1015 const bool pasteEnabled = mimeData->hasFormat( u
"application/x-qgsattributetabledesignerelementclipboard"_s );
1016 mActionPasteWidgetConfiguration->setEnabled( pasteEnabled );
1017 mAvailableWidgetsContextMenu->popup( globalPos );
1021void QgsAttributesFormProperties::copyWidgetConfiguration()
1033 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1035 if ( fieldIndex < 0 )
1038 const QgsField field =
mLayer->fields().field( fieldIndex );
1042 QDomElement documentElement = doc.createElement( u
"FormWidgetClipboard"_s );
1043 documentElement.setAttribute( u
"name"_s, field.
name() );
1048 QDomElement editWidgetElement = doc.createElement( u
"editWidget"_s );
1049 documentElement.appendChild( editWidgetElement );
1050 editWidgetElement.setAttribute( u
"type"_s, widgetSetup.
type() );
1051 QDomElement editWidgetConfigElement = doc.createElement( u
"config"_s );
1054 editWidgetElement.appendChild( editWidgetConfigElement );
1057 QDomElement splitPolicyElement = doc.createElement( u
"splitPolicy"_s );
1059 documentElement.appendChild( splitPolicyElement );
1062 QDomElement duplicatePolicyElement = doc.createElement( u
"duplicatePolicy"_s );
1064 documentElement.appendChild( duplicatePolicyElement );
1067 QDomElement mergePolicyElement = doc.createElement( u
"mergePolicy"_s );
1069 documentElement.appendChild( mergePolicyElement );
1072 QDomElement defaultElem = doc.createElement( u
"default"_s );
1075 documentElement.appendChild( defaultElem );
1078 QDomElement constraintElem = doc.createElement( u
"constraint"_s );
1083 documentElement.appendChild( constraintElem );
1086 QDomElement constraintExpressionElem = doc.createElement( u
"constraintExpression"_s );
1089 documentElement.appendChild( constraintExpressionElem );
1094 QDomElement widgetGeneralSettingsElem = doc.createElement( u
"widgetGeneralSettings"_s );
1095 widgetGeneralSettingsElem.setAttribute( u
"editable"_s,
mAttributeTypeDialog->fieldEditable() );
1096 widgetGeneralSettingsElem.setAttribute( u
"label_on_top"_s,
mAttributeTypeDialog->labelOnTop() );
1098 documentElement.appendChild( widgetGeneralSettingsElem );
1108 const QModelIndex indexLayout =
mFormLayoutView->firstSelectedIndex();
1111 QDomElement displayElement = doc.createElement( u
"widgetDisplay"_s );
1112 displayElement.setAttribute( u
"showLabel"_s, layoutData.showLabel() );
1113 displayElement.setAttribute( u
"horizontalStretch"_s, layoutData.horizontalStretch() );
1114 displayElement.setAttribute( u
"verticalStretch"_s, layoutData.verticalStretch() );
1115 displayElement.appendChild( layoutData.labelStyle().writeXml( doc ) );
1116 documentElement.appendChild( displayElement );
1119 doc.appendChild( documentElement );
1121 QMimeData *mimeData =
new QMimeData;
1122 mimeData->setData( u
"application/x-qgsattributetabledesignerelementclipboard"_s, doc.toByteArray() );
1123 QClipboard *clipboard = QApplication::clipboard();
1124 clipboard->setMimeData( mimeData );
1127void QgsAttributesFormProperties::pasteWidgetConfiguration()
1135 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1137 if ( fieldIndex < 0 )
1144 QClipboard *clipboard = QApplication::clipboard();
1145 const QMimeData *mimeData = clipboard->mimeData();
1149 if ( doc.setContent( mimeData->data( u
"application/x-qgsattributetabledesignerelementclipboard"_s ) ) )
1151 QgsReadWriteContext context;
1152 QDomElement docElem = doc.documentElement();
1153 if ( docElem.tagName() !=
"FormWidgetClipboard"_L1 )
1162 const QDomElement fieldWidgetElement = docElem.firstChildElement( u
"editWidget"_s );
1163 if ( !fieldWidgetElement.isNull() )
1165 const QString widgetType = fieldWidgetElement.attribute( u
"type"_s );
1171 const QDomElement configElement = fieldWidgetElement.firstChildElement( u
"config"_s );
1172 if ( !configElement.isNull() )
1174 const QDomElement optionsElem = configElement.childNodes().at( 0 ).toElement();
1182 mMessageBar->pushMessage( QString(), tr(
"Unable to paste widget configuration. The target field (%1) does not support the %2 widget type." ).arg( fieldName, widgetType ),
Qgis::MessageLevel::Warning );
1187 const QDomElement splitPolicyElement = docElem.firstChildElement( u
"splitPolicy"_s );
1188 if ( !splitPolicyElement.isNull() )
1195 const QDomElement duplicatePolicyElement = docElem.firstChildElement( u
"duplicatePolicy"_s );
1196 if ( !duplicatePolicyElement.isNull() )
1203 const QDomElement mergePolicyElement = docElem.firstChildElement( u
"mergePolicy"_s );
1204 if ( !mergePolicyElement.isNull() )
1211 const QDomElement defaultElement = docElem.firstChildElement( u
"default"_s );
1212 if ( !defaultElement.isNull() )
1221 const QDomElement constraintElement = docElem.firstChildElement( u
"constraint"_s );
1222 if ( !constraintElement.isNull() )
1224 const int intConstraints = constraintElement.attribute( u
"constraints"_s, u
"0"_s ).toInt();
1250 const int uniqueStrength = constraintElement.attribute( u
"unique_strength"_s, u
"1"_s ).toInt();
1251 const int notNullStrength = constraintElement.attribute( u
"notnull_strength"_s, u
"1"_s ).toInt();
1252 const int expStrength = constraintElement.attribute( u
"exp_strength"_s, u
"1"_s ).toInt();
1263 const QDomElement constraintExpressionElement = docElem.firstChildElement( u
"constraintExpression"_s );
1264 if ( !constraintExpressionElement.isNull() )
1266 QString expression = constraintExpressionElement.attribute( u
"exp"_s, QString() );
1267 QString description = constraintExpressionElement.attribute( u
"desc"_s, QString() );
1273 const QDomElement widgetGeneralSettingsElement = docElem.firstChildElement( u
"widgetGeneralSettings"_s );
1274 if ( !widgetGeneralSettingsElement.isNull() )
1276 const int editable = widgetGeneralSettingsElement.attribute( u
"editable"_s, u
"0"_s ).toInt();
1278 if ( widgetGeneralSettingsElement.hasAttribute( u
"reuse_last_values"_s ) )
1287 const int labelOnTop = widgetGeneralSettingsElement.attribute( u
"label_on_top"_s, u
"0"_s ).toInt();
1294 loadAttributeTypeDialogFromConfiguration( config );
1299 const QDomElement displayElement = docElem.firstChildElement( u
"widgetDisplay"_s );
1300 if ( !displayElement.isNull() )
1302 const int showLabel = displayElement.attribute( u
"showLabel"_s, u
"0"_s ).toInt();
1303 const int horizontalStretch = displayElement.attribute( u
"horizontalStretch"_s, u
"0"_s ).toInt();
1304 const int verticalStretch = displayElement.attribute( u
"verticalStretch"_s, u
"0"_s ).toInt();
1305 QgsAttributeEditorElement::LabelStyle style;
1306 style.
readXml( displayElement );
1318void QgsAttributesFormProperties::setAvailableWidgetsIndicatorProvidersEnabled(
bool enabled )
1321 if ( enabled && !mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1324 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1326 else if ( !enabled && mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1329 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1332 if ( enabled && !mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1335 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1337 else if ( !enabled && mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1340 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1344void QgsAttributesFormProperties::setFormLayoutIndicatorProvidersEnabled(
bool enabled )
1347 if ( enabled && !mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1350 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1352 else if ( !enabled && mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1355 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1358 if ( enabled && !mConstraintIndicatorProviderFormLayout->isEnabled() )
1361 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1363 else if ( !enabled && mConstraintIndicatorProviderFormLayout->isEnabled() )
1366 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1370void QgsAttributesFormProperties::previewForm()
1372 if ( !mSourceFieldsProperties )
1381 QList<QPair<QgsField, QString>> expressionFields;
1383 for (
int i = 0; i <
mLayer->fields().size(); i++ )
1387 expressionFields << qMakePair(
mLayer->fields().at( i ),
mLayer->expressionField( i ) );
1395 std::unique_ptr<QgsVectorLayer> vlayer;
1397 for (
const QPair<QgsField, QString> &expressionField : std::as_const( expressionFields ) )
1399 vlayer->addExpressionField( expressionField.second, expressionField.first );
1402 mSourceFieldsProperties->applyToLayer( vlayer.get() );
1403 applyToLayer( vlayer.get() );
1406 QgsAttributeDialog form( vlayer.get(), &feature,
false,
this,
true );
1410 projectDirtyBlocker.reset();
AttributeFormReuseLastValuePolicy
Attribute form policy for reusing last entered values.
@ AllowedDefaultOn
Reuse of last values allowed and enabled by default.
@ NotAllowed
Reuse of last values not allowed.
AttributeFormSuppression
Available form types for layout of the attribute form editor.
@ On
Always suppress feature form.
@ Default
Use the application-wide setting.
@ Off
Never suppress feature form.
AttributeFormLayout
Available form types for layout of the attribute form editor.
@ DragAndDrop
"Drag and drop" layout. Needs to be configured.
@ AutoGenerated
Autogenerate a simple tabular layout for the form.
@ UiFile
Load a .ui file for the layout. Needs to be configured.
FieldDomainMergePolicy
Merge policy for field domains.
@ DefaultValue
Use default field value.
@ Warning
Warning message.
FieldDomainSplitPolicy
Split policy for field domains.
@ Duplicate
Duplicate original value.
FieldDuplicatePolicy
Duplicate policy for fields.
@ Duplicate
Duplicate original value.
@ Expression
Field is calculated from an expression.
QString html() const
Returns an HTML table with the basic information about this action.
@ PreviewMode
Preview mode, for previewing attribute configurations.
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 appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Provides field constraint indicators for attribute form views.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
void setConstraintStrength(Constraint constraint, ConstraintStrength strength)
Sets the strength of a constraint.
void setConstraintExpression(const QString &expression, const QString &description=QString())
Set the constraint expression for the field.
@ ConstraintOriginProvider
Constraint was set at data provider.
@ ConstraintOriginLayer
Constraint was set by layer.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
QString constraintExpression() const
Returns the constraint expression for the field, if set.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
@ ConstraintExpression
Field has an expression constraint set. See constraintExpression().
void removeConstraint(Constraint constraint)
Removes a constraint from the field.
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
QFlags< Constraint > Constraints
Provides default value indicators for attribute form views.
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...
QgsDefaultValue defaultValueDefinition
Qgis::FieldDomainMergePolicy mergePolicy() const
Returns the field's merge policy, which indicates how field values should be handled during a merge o...
QgsFieldConstraints constraints
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, Qgis::WkbType geometryType=Qgis::WkbType::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem(), bool loadDefaultStyle=true) SIP_FACTORY
Creates a new memory layer using the specified parameters.
A bar for displaying non-blocking messages to the user.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
int count() const
Returns the number of properties contained within the collection.
A boolean settings entry.
static const QgsSettingsEntryBool * settingsDigitizingDisableEnterAttributeValuesDialog
Settings entry digitizing disable enter attribute values dialog.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
A widget which displays information about vector layer fields, and allows some configuration of them.
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
Represents a vector layer which manages a vector based dataset.
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
void setFieldMergePolicy(int index, Qgis::FieldDomainMergePolicy policy)
Sets a merge policy for the field with the specified index.
void setDefaultValueDefinition(int index, const QgsDefaultValue &definition)
Sets the definition of the expression to use when calculating the default value for a field.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Sets the editFormConfig (configuration) of the form used to represent this vector layer.
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
Sets the editor widget setup for the field at the specified index.
void setConstraintExpression(int index, const QString &expression, const QString &description=QString())
Sets the constraint expression for the specified field index.
void setFieldDuplicatePolicy(int index, Qgis::FieldDuplicatePolicy policy)
Sets a duplicate policy for the field with the specified index.
Q_INVOKABLE void setFieldAlias(int index, const QString &aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QgsEditFormConfig editFormConfig
void setFieldSplitPolicy(int index, Qgis::FieldDomainSplitPolicy policy)
Sets a split policy for the field with the specified index.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
void readXml(const QDomNode &node)
Reads configuration from node.