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 );
338void QgsAttributesFormProperties::storeAttributeTypeDialog()
346 QgsAttributesFormData::FieldConfig cfg;
356 QgsFieldConstraints constraints;
399 const QString fieldName =
mLayer->fields().at( fieldIndex ).name();
401 QModelIndex index = mAvailableWidgetsModel->fieldModelIndex( fieldName );
402 if ( index.isValid() )
409 mFormLayoutModel->updateFieldConfigForFieldItems( fieldName, cfg );
415void QgsAttributesFormProperties::storeAttributeWidgetEdit()
424 storeAttributeWidgetEdit( index );
427void QgsAttributesFormProperties::storeAttributeWidgetEdit(
const QModelIndex &index )
432 if ( !index.isValid() )
440 QgsAttributesFormData::RelationEditorConfiguration config =
mAttributeWidgetEdit->updatedRelationConfiguration();
441 itemData.setRelationEditorConfiguration( config );
447void QgsAttributesFormProperties::loadAttributeWidgetEdit()
452 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
453 const QgsAttributesFormData::AttributeFormItemData itemData = currentIndex.data(
QgsAttributesFormModel::ItemDataRole ).value< QgsAttributesFormData::AttributeFormItemData >();
459 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
463void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
466 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
470void QgsAttributesFormProperties::storeAttributeContainerEdit()
478 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
479 storeAttributeContainerEdit( currentIndex );
482void QgsAttributesFormProperties::storeAttributeContainerEdit(
const QModelIndex &index )
487 if ( !index.isValid() )
491 QString containerName;
498void QgsAttributesFormProperties::loadAttributeContainerEdit()
503 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
504 const QgsAttributesFormData::AttributeFormItemData itemData = currentIndex.data(
QgsAttributesFormModel::ItemDataRole ).value< QgsAttributesFormData::AttributeFormItemData >();
511 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
515void QgsAttributesFormProperties::onAttributeSelectionChanged(
const QItemSelection &,
const QItemSelection & )
517 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
520 if (
mFormLayoutView->selectionModel()->selectedRows( 0 ).count() == 1 )
528 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
531void QgsAttributesFormProperties::onFormLayoutSelectionChanged(
const QItemSelection &,
const QItemSelection &deselected )
534 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
536 if ( deselected.indexes().count() == 1 )
538 index = mFormLayoutProxyModel->mapToSource( deselected.indexes().at( 0 ) );
540 else if ( deselected.indexes().count() == 0 &&
mFormLayoutView->selectionModel()->selectedIndexes().count() == 2 )
547 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
556 storeAttributeWidgetEdit( deselectedFormLayoutIndex );
557 storeAttributeContainerEdit( deselectedFormLayoutIndex );
561 storeAttributeTypeDialog();
564 clearAttributeTypeFrame();
566 if ( emitter->selectionModel()->selectedRows( 0 ).count() != 1 )
568 receiver->clearSelection();
581 loadAttributeWidgetEdit();
585 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
594 loadAttributeWidgetEdit();
596 loadAttributeTypeDialog();
601 receiver->clearSelection();
602 loadAttributeContainerEdit();
609 loadInfoWidget( action.
html() );
619 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
623 loadInfoWidget( tr(
"This configuration is available with double-click in the Form Layout panel" ) );
625 receiver->clearSelection();
630 receiver->clearSelection();
637void QgsAttributesFormProperties::clearAttributeTypeFrame()
665void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
668 for (
int i = 0; i < mFormLayoutProxyModel->rowCount(); ++i )
670 QModelIndex index = mFormLayoutProxyModel->index( i, 0 );
671 mFormLayoutView->selectionModel()->select( index, QItemSelectionModel::Toggle );
675void QgsAttributesFormProperties::toggleShowAliases(
bool checked )
678 mAvailableWidgetsModel->setShowAliases( checked );
679 mFormLayoutModel->setShowAliases( checked );
682void QgsAttributesFormProperties::addContainer()
684 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList = mFormLayoutModel->listOfContainers();
686 QModelIndex currentItem;
690 QgsAddAttributeFormContainerDialog dialog(
mLayer, existingContainerList, currentItem,
this );
692 if ( !dialog.exec() )
695 const QString name = dialog.name();
696 QModelIndex parentContainerItem = dialog.parentContainerItem();
698 mFormLayoutModel->addContainer( parentContainerItem, name, dialog.columnCount(), dialog.containerType() );
699 if ( parentContainerItem.isValid() )
703void QgsAttributesFormProperties::removeTabOrGroupButton()
709 const QModelIndexList items =
mFormLayoutView->selectionModel()->selectedRows();
713 const QModelIndex item = mFormLayoutProxyModel->mapToSource( items.at( 0 ) );
714 mFormLayoutModel->removeRow( item.row(), item.parent() );
718void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
722 if ( selection.count() > 0 )
736 mFormLayoutWidget->setVisible(
false );
737 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
738 mUiFileFrame->setVisible(
false );
739 mAddContainerButton->setVisible(
false );
740 mRemoveLayoutItemButton->setVisible(
false );
741 mInvertSelectionButton->setVisible(
false );
743 setAvailableWidgetsIndicatorProvidersEnabled(
true );
744 setFormLayoutIndicatorProvidersEnabled(
false );
748 mFormLayoutWidget->setVisible(
true );
749 mTreeViewHorizontalSpacer->changeSize( 6, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
750 mUiFileFrame->setVisible(
false );
751 mAddContainerButton->setVisible(
true );
752 mRemoveLayoutItemButton->setVisible(
true );
753 mInvertSelectionButton->setVisible(
true );
755 setAvailableWidgetsIndicatorProvidersEnabled(
false );
756 setFormLayoutIndicatorProvidersEnabled(
true );
761 mFormLayoutWidget->setVisible(
false );
762 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
763 mUiFileFrame->setVisible(
true );
764 mAddContainerButton->setVisible(
false );
765 mRemoveLayoutItemButton->setVisible(
false );
766 mInvertSelectionButton->setVisible(
false );
768 setAvailableWidgetsIndicatorProvidersEnabled(
true );
769 setFormLayoutIndicatorProvidersEnabled(
false );
774 if ( selection.count() > 0 )
780void QgsAttributesFormProperties::mTbInitCode_clicked()
782 QgsAttributesFormInitCode attributesFormInitCode;
789 if ( !attributesFormInitCode.exec() )
792 mInitCodeSource = attributesFormInitCode.
codeSource();
793 mInitCode = attributesFormInitCode.
initCode();
798void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
800 QgsSettings myQSettings;
801 const QString lastUsedDir = myQSettings.
value( u
"style/lastUIDir"_s, QDir::homePath() ).toString();
802 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
804 if ( uifilename.isNull() )
807 const QFileInfo fi( uifilename );
808 myQSettings.
setValue( u
"style/lastUIDir"_s, fi.path() );
809 mEditFormLineEdit->setText( uifilename );
814 storeAttributeWidgetEdit();
815 storeAttributeContainerEdit();
816 storeAttributeTypeDialog();
826void QgsAttributesFormProperties::applyToLayer(
QgsVectorLayer *layer )
831 const QModelIndex fieldContainer = mAvailableWidgetsModel->
fieldContainer();
834 for (
int i = 0; i < mAvailableWidgetsModel->
rowCount( fieldContainer ); i++ )
836 index = mAvailableWidgetsModel->
index( i, 0, fieldContainer );
896 for (
int t = 0; t < mFormLayoutModel->rowCount(); t++ )
898 QModelIndex index = mFormLayoutModel->index( t, 0 );
899 QgsAttributeEditorElement *editorElement { mFormLayoutModel->createAttributeEditorWidget( index,
nullptr ) };
901 editFormConfig.
addTab( editorElement );
904 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
916 const QModelIndex relationContainer = mAvailableWidgetsModel->relationContainer();
918 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( relationContainer ); i++ )
920 const QModelIndex relationIndex = mAvailableWidgetsModel->index( i, 0, relationContainer );
926 const QModelIndex layoutIndex = mFormLayoutModel->firstRecursiveMatchingModelIndex( indexType, indexId );
927 if ( layoutIndex.isValid() )
931 const QgsAttributesFormData::AttributeFormItemData tabIndexData = layoutIndex.data(
QgsAttributesFormModel::ItemDataRole ).value<QgsAttributesFormData::AttributeFormItemData>();
943void QgsAttributesFormProperties::updatedFields()
946 QMap<QString, QgsAttributesFormData::FieldConfig> fieldConfigs;
948 const QModelIndex fieldContainerBefore = mAvailableWidgetsModel->fieldContainer();
951 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerBefore ); i++ )
953 index = mAvailableWidgetsModel->index( i, 0, fieldContainerBefore );
956 fieldConfigs[fieldName] = config;
961 const QModelIndex fieldContainerAfter = mAvailableWidgetsModel->fieldContainer();
963 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerAfter ); i++ )
965 index = mAvailableWidgetsModel->index( i, 0, fieldContainerAfter );
968 if ( fieldConfigs.contains( fieldName ) )
976void QgsAttributesFormProperties::updateFilteredItems(
const QString &filterText )
978 const int availableWidgetsPreviousSelectionCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
979 const int formLayoutPreviousSelectionCount =
mFormLayoutView->selectionModel()->selectedRows().count();
981 static_cast< QgsAttributesAvailableWidgetsView *
>(
mAvailableWidgetsView )->setFilterText( filterText );
984 static_cast< QgsAttributesFormLayoutView *
>(
mFormLayoutView )->setFilterText( filterText );
989 if ( !( availableWidgetsPreviousSelectionCount == 0 && formLayoutPreviousSelectionCount == 0 ) )
991 const int selectedAvailableWidgetItemCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
992 const int selectedFormLayoutItemCount =
mFormLayoutView->selectionModel()->selectedRows().count();
994 if ( selectedAvailableWidgetItemCount == 0 && selectedFormLayoutItemCount == 0 )
997 clearAttributeTypeFrame();
1002void QgsAttributesFormProperties::onContextMenuRequested( QPoint point )
1013 const QClipboard *clipboard = QApplication::clipboard();
1014 const QMimeData *mimeData = clipboard->mimeData();
1018 const bool pasteEnabled = mimeData->hasFormat( u
"application/x-qgsattributetabledesignerelementclipboard"_s );
1019 mActionPasteWidgetConfiguration->setEnabled( pasteEnabled );
1020 mAvailableWidgetsContextMenu->popup( globalPos );
1024void QgsAttributesFormProperties::copyWidgetConfiguration()
1036 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1038 if ( fieldIndex < 0 )
1041 const QgsField field =
mLayer->fields().field( fieldIndex );
1045 QDomElement documentElement = doc.createElement( u
"FormWidgetClipboard"_s );
1046 documentElement.setAttribute( u
"name"_s, field.
name() );
1051 QDomElement editWidgetElement = doc.createElement( u
"editWidget"_s );
1052 documentElement.appendChild( editWidgetElement );
1053 editWidgetElement.setAttribute( u
"type"_s, widgetSetup.
type() );
1054 QDomElement editWidgetConfigElement = doc.createElement( u
"config"_s );
1057 editWidgetElement.appendChild( editWidgetConfigElement );
1060 QDomElement splitPolicyElement = doc.createElement( u
"splitPolicy"_s );
1062 documentElement.appendChild( splitPolicyElement );
1065 QDomElement duplicatePolicyElement = doc.createElement( u
"duplicatePolicy"_s );
1067 documentElement.appendChild( duplicatePolicyElement );
1070 QDomElement mergePolicyElement = doc.createElement( u
"mergePolicy"_s );
1072 documentElement.appendChild( mergePolicyElement );
1075 QDomElement defaultElem = doc.createElement( u
"default"_s );
1078 documentElement.appendChild( defaultElem );
1081 QDomElement constraintElem = doc.createElement( u
"constraint"_s );
1086 documentElement.appendChild( constraintElem );
1089 QDomElement constraintExpressionElem = doc.createElement( u
"constraintExpression"_s );
1092 documentElement.appendChild( constraintExpressionElem );
1097 QDomElement widgetGeneralSettingsElem = doc.createElement( u
"widgetGeneralSettings"_s );
1098 widgetGeneralSettingsElem.setAttribute( u
"editable"_s,
mAttributeTypeDialog->fieldEditable() );
1099 widgetGeneralSettingsElem.setAttribute( u
"label_on_top"_s,
mAttributeTypeDialog->labelOnTop() );
1101 documentElement.appendChild( widgetGeneralSettingsElem );
1111 const QModelIndex indexLayout =
mFormLayoutView->firstSelectedIndex();
1114 QDomElement displayElement = doc.createElement( u
"widgetDisplay"_s );
1115 displayElement.setAttribute( u
"showLabel"_s, layoutData.showLabel() );
1116 displayElement.setAttribute( u
"horizontalStretch"_s, layoutData.horizontalStretch() );
1117 displayElement.setAttribute( u
"verticalStretch"_s, layoutData.verticalStretch() );
1118 displayElement.appendChild( layoutData.labelStyle().writeXml( doc ) );
1119 documentElement.appendChild( displayElement );
1122 doc.appendChild( documentElement );
1124 QMimeData *mimeData =
new QMimeData;
1125 mimeData->setData( u
"application/x-qgsattributetabledesignerelementclipboard"_s, doc.toByteArray() );
1126 QClipboard *clipboard = QApplication::clipboard();
1127 clipboard->setMimeData( mimeData );
1130void QgsAttributesFormProperties::pasteWidgetConfiguration()
1138 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1140 if ( fieldIndex < 0 )
1147 QClipboard *clipboard = QApplication::clipboard();
1148 const QMimeData *mimeData = clipboard->mimeData();
1152 if ( doc.setContent( mimeData->data( u
"application/x-qgsattributetabledesignerelementclipboard"_s ) ) )
1154 QgsReadWriteContext context;
1155 QDomElement docElem = doc.documentElement();
1156 if ( docElem.tagName() !=
"FormWidgetClipboard"_L1 )
1165 const QDomElement fieldWidgetElement = docElem.firstChildElement( u
"editWidget"_s );
1166 if ( !fieldWidgetElement.isNull() )
1168 const QString widgetType = fieldWidgetElement.attribute( u
"type"_s );
1174 const QDomElement configElement = fieldWidgetElement.firstChildElement( u
"config"_s );
1175 if ( !configElement.isNull() )
1177 const QDomElement optionsElem = configElement.childNodes().at( 0 ).toElement();
1185 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 );
1190 const QDomElement splitPolicyElement = docElem.firstChildElement( u
"splitPolicy"_s );
1191 if ( !splitPolicyElement.isNull() )
1198 const QDomElement duplicatePolicyElement = docElem.firstChildElement( u
"duplicatePolicy"_s );
1199 if ( !duplicatePolicyElement.isNull() )
1206 const QDomElement mergePolicyElement = docElem.firstChildElement( u
"mergePolicy"_s );
1207 if ( !mergePolicyElement.isNull() )
1214 const QDomElement defaultElement = docElem.firstChildElement( u
"default"_s );
1215 if ( !defaultElement.isNull() )
1224 const QDomElement constraintElement = docElem.firstChildElement( u
"constraint"_s );
1225 if ( !constraintElement.isNull() )
1227 const int intConstraints = constraintElement.attribute( u
"constraints"_s, u
"0"_s ).toInt();
1253 const int uniqueStrength = constraintElement.attribute( u
"unique_strength"_s, u
"1"_s ).toInt();
1254 const int notNullStrength = constraintElement.attribute( u
"notnull_strength"_s, u
"1"_s ).toInt();
1255 const int expStrength = constraintElement.attribute( u
"exp_strength"_s, u
"1"_s ).toInt();
1266 const QDomElement constraintExpressionElement = docElem.firstChildElement( u
"constraintExpression"_s );
1267 if ( !constraintExpressionElement.isNull() )
1269 QString expression = constraintExpressionElement.attribute( u
"exp"_s, QString() );
1270 QString description = constraintExpressionElement.attribute( u
"desc"_s, QString() );
1276 const QDomElement widgetGeneralSettingsElement = docElem.firstChildElement( u
"widgetGeneralSettings"_s );
1277 if ( !widgetGeneralSettingsElement.isNull() )
1279 const int editable = widgetGeneralSettingsElement.attribute( u
"editable"_s, u
"0"_s ).toInt();
1281 if ( widgetGeneralSettingsElement.hasAttribute( u
"reuse_last_values"_s ) )
1290 const int labelOnTop = widgetGeneralSettingsElement.attribute( u
"label_on_top"_s, u
"0"_s ).toInt();
1297 loadAttributeTypeDialogFromConfiguration( config );
1302 const QDomElement displayElement = docElem.firstChildElement( u
"widgetDisplay"_s );
1303 if ( !displayElement.isNull() )
1305 const int showLabel = displayElement.attribute( u
"showLabel"_s, u
"0"_s ).toInt();
1306 const int horizontalStretch = displayElement.attribute( u
"horizontalStretch"_s, u
"0"_s ).toInt();
1307 const int verticalStretch = displayElement.attribute( u
"verticalStretch"_s, u
"0"_s ).toInt();
1308 QgsAttributeEditorElement::LabelStyle style;
1309 style.
readXml( displayElement );
1321void QgsAttributesFormProperties::setAvailableWidgetsIndicatorProvidersEnabled(
bool enabled )
1324 if ( enabled && !mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1327 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1329 else if ( !enabled && mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1332 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1335 if ( enabled && !mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1338 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1340 else if ( !enabled && mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1343 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1347void QgsAttributesFormProperties::setFormLayoutIndicatorProvidersEnabled(
bool enabled )
1350 if ( enabled && !mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1353 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1355 else if ( !enabled && mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1358 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1361 if ( enabled && !mConstraintIndicatorProviderFormLayout->isEnabled() )
1364 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1366 else if ( !enabled && mConstraintIndicatorProviderFormLayout->isEnabled() )
1369 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1373void QgsAttributesFormProperties::previewForm()
1375 if ( !mSourceFieldsProperties )
1384 QList<QPair<QgsField, QString>> expressionFields;
1386 for (
int i = 0; i <
mLayer->fields().size(); i++ )
1390 expressionFields << qMakePair(
mLayer->fields().at( i ),
mLayer->expressionField( i ) );
1398 std::unique_ptr<QgsVectorLayer> vlayer;
1400 for (
const QPair<QgsField, QString> &expressionField : std::as_const( expressionFields ) )
1402 vlayer->addExpressionField( expressionField.second, expressionField.first );
1405 mSourceFieldsProperties->applyToLayer( vlayer.get() );
1406 applyToLayer( vlayer.get() );
1409 QgsAttributeDialog form( vlayer.get(), &feature,
false,
this,
true );
1413 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 setFieldCustomComment(int index, const QString &customCommentString)
Sets the custom comment for the field.
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.