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
47#include <QAbstractItemModelTester>
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 QAbstractItemModelTester( mAvailableWidgetsProxyModel, QAbstractItemModelTester::FailureReportingMode::Fatal,
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 QAbstractItemModelTester( mFormLayoutProxyModel, QAbstractItemModelTester::FailureReportingMode::Fatal,
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 )
467 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
471void QgsAttributesFormProperties::storeAttributeContainerEdit()
479 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
480 storeAttributeContainerEdit( currentIndex );
483void QgsAttributesFormProperties::storeAttributeContainerEdit(
const QModelIndex &index )
488 if ( !index.isValid() )
492 QString containerName;
499void QgsAttributesFormProperties::loadAttributeContainerEdit()
504 const QModelIndex currentIndex =
mFormLayoutView->firstSelectedIndex();
505 const QgsAttributesFormData::AttributeFormItemData itemData = currentIndex.data(
QgsAttributesFormModel::ItemDataRole ).value< QgsAttributesFormData::AttributeFormItemData >();
512 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
516void QgsAttributesFormProperties::onAttributeSelectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
518 if ( selected.isEmpty() && deselected.isEmpty() )
526 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
527 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
530 if (
mFormLayoutView->selectionModel()->selectedRows( 0 ).count() == 1 )
538 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
539 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
542void QgsAttributesFormProperties::onFormLayoutSelectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
544 if ( selected.isEmpty() && deselected.isEmpty() )
552 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
553 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
556 if ( deselected.indexes().count() == 1 )
558 index = mFormLayoutProxyModel->mapToSource( deselected.indexes().at( 0 ) );
560 else if ( deselected.indexes().count() == 0 &&
mFormLayoutView->selectionModel()->selectedIndexes().count() == 2 )
567 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
568 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
577 storeAttributeWidgetEdit( deselectedFormLayoutIndex );
578 storeAttributeContainerEdit( deselectedFormLayoutIndex );
582 storeAttributeTypeDialog();
585 clearAttributeTypeFrame();
587 if ( emitter->selectionModel()->selectedRows( 0 ).count() != 1 )
589 receiver->clearSelection();
602 loadAttributeWidgetEdit();
606 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
615 loadAttributeWidgetEdit();
617 loadAttributeTypeDialog();
622 receiver->clearSelection();
623 loadAttributeContainerEdit();
630 loadInfoWidget( action.
html() );
640 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
644 loadInfoWidget( tr(
"This configuration is available with double-click in the Form Layout panel" ) );
646 receiver->clearSelection();
651 receiver->clearSelection();
658void QgsAttributesFormProperties::clearAttributeTypeFrame()
686void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
689 for (
int i = 0; i < mFormLayoutProxyModel->rowCount(); ++i )
691 QModelIndex index = mFormLayoutProxyModel->index( i, 0 );
692 mFormLayoutView->selectionModel()->select( index, QItemSelectionModel::Toggle );
696void QgsAttributesFormProperties::toggleShowAliases(
bool checked )
699 mAvailableWidgetsModel->setShowAliases( checked );
700 mFormLayoutModel->setShowAliases( checked );
703void QgsAttributesFormProperties::addContainer()
705 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList = mFormLayoutModel->listOfContainers();
707 QModelIndex currentItem;
711 QgsAddAttributeFormContainerDialog dialog(
mLayer, existingContainerList, currentItem,
this );
713 if ( !dialog.exec() )
716 const QString name = dialog.name();
717 QModelIndex parentContainerItem = dialog.parentContainerItem();
719 mFormLayoutModel->addContainer( parentContainerItem, name, dialog.columnCount(), dialog.containerType() );
720 if ( parentContainerItem.isValid() )
724void QgsAttributesFormProperties::removeTabOrGroupButton()
728 const QModelIndexList selectedRows =
mFormLayoutView->selectionModel()->selectedRows();
730 QList< QPersistentModelIndex > sourceIndexes;
731 sourceIndexes.reserve( selectedRows.size() );
732 for (
const QModelIndex &proxyIndex : selectedRows )
733 sourceIndexes << QPersistentModelIndex( mFormLayoutProxyModel->mapToSource( proxyIndex ) );
738 for (
const QPersistentModelIndex &sourceIndex : std::as_const( sourceIndexes ) )
740 if ( sourceIndex.isValid() )
741 mFormLayoutModel->removeRow( sourceIndex.row(), sourceIndex.parent() );
745void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
749 if ( selection.count() > 0 )
763 mFormLayoutWidget->setVisible(
false );
764 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
765 mUiFileFrame->setVisible(
false );
766 mAddContainerButton->setVisible(
false );
767 mRemoveLayoutItemButton->setVisible(
false );
768 mInvertSelectionButton->setVisible(
false );
770 setAvailableWidgetsIndicatorProvidersEnabled(
true );
771 setFormLayoutIndicatorProvidersEnabled(
false );
775 mFormLayoutWidget->setVisible(
true );
776 mTreeViewHorizontalSpacer->changeSize( 6, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
777 mUiFileFrame->setVisible(
false );
778 mAddContainerButton->setVisible(
true );
779 mRemoveLayoutItemButton->setVisible(
true );
780 mInvertSelectionButton->setVisible(
true );
782 setAvailableWidgetsIndicatorProvidersEnabled(
false );
783 setFormLayoutIndicatorProvidersEnabled(
true );
788 mFormLayoutWidget->setVisible(
false );
789 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
790 mUiFileFrame->setVisible(
true );
791 mAddContainerButton->setVisible(
false );
792 mRemoveLayoutItemButton->setVisible(
false );
793 mInvertSelectionButton->setVisible(
false );
795 setAvailableWidgetsIndicatorProvidersEnabled(
true );
796 setFormLayoutIndicatorProvidersEnabled(
false );
801 if ( selection.count() > 0 )
807void QgsAttributesFormProperties::mTbInitCode_clicked()
809 QgsAttributesFormInitCode attributesFormInitCode;
816 if ( !attributesFormInitCode.exec() )
819 mInitCodeSource = attributesFormInitCode.
codeSource();
820 mInitCode = attributesFormInitCode.
initCode();
825void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
827 QgsSettings myQSettings;
828 const QString lastUsedDir = myQSettings.
value( u
"style/lastUIDir"_s, QDir::homePath() ).toString();
829 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
831 if ( uifilename.isNull() )
834 const QFileInfo fi( uifilename );
835 myQSettings.
setValue( u
"style/lastUIDir"_s, fi.path() );
836 mEditFormLineEdit->setText( uifilename );
841 storeAttributeWidgetEdit();
842 storeAttributeContainerEdit();
843 storeAttributeTypeDialog();
853void QgsAttributesFormProperties::applyToLayer(
QgsVectorLayer *layer )
858 const QModelIndex fieldContainer = mAvailableWidgetsModel->
fieldContainer();
861 for (
int i = 0; i < mAvailableWidgetsModel->
rowCount( fieldContainer ); i++ )
863 index = mAvailableWidgetsModel->
index( i, 0, fieldContainer );
923 for (
int t = 0; t < mFormLayoutModel->rowCount(); t++ )
925 QModelIndex index = mFormLayoutModel->index( t, 0 );
926 QgsAttributeEditorElement *editorElement { mFormLayoutModel->createAttributeEditorWidget( index,
nullptr ) };
928 editFormConfig.
addTab( editorElement );
931 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
943 const QModelIndex relationContainer = mAvailableWidgetsModel->relationContainer();
945 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( relationContainer ); i++ )
947 const QModelIndex relationIndex = mAvailableWidgetsModel->index( i, 0, relationContainer );
953 const QModelIndex layoutIndex = mFormLayoutModel->firstRecursiveMatchingModelIndex( indexType, indexId );
954 if ( layoutIndex.isValid() )
958 const QgsAttributesFormData::AttributeFormItemData tabIndexData = layoutIndex.data(
QgsAttributesFormModel::ItemDataRole ).value<QgsAttributesFormData::AttributeFormItemData>();
970void QgsAttributesFormProperties::updatedFields()
973 QMap<QString, QgsAttributesFormData::FieldConfig> fieldConfigs;
975 const QModelIndex fieldContainerBefore = mAvailableWidgetsModel->fieldContainer();
978 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerBefore ); i++ )
980 index = mAvailableWidgetsModel->index( i, 0, fieldContainerBefore );
983 fieldConfigs[fieldName] = config;
988 const QModelIndex fieldContainerAfter = mAvailableWidgetsModel->fieldContainer();
990 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerAfter ); i++ )
992 index = mAvailableWidgetsModel->index( i, 0, fieldContainerAfter );
995 if ( fieldConfigs.contains( fieldName ) )
1003void QgsAttributesFormProperties::updateFilteredItems(
const QString &filterText )
1005 const int availableWidgetsPreviousSelectionCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
1006 const int formLayoutPreviousSelectionCount =
mFormLayoutView->selectionModel()->selectedRows().count();
1008 static_cast< QgsAttributesAvailableWidgetsView *
>(
mAvailableWidgetsView )->setFilterText( filterText );
1011 static_cast< QgsAttributesFormLayoutView *
>(
mFormLayoutView )->setFilterText( filterText );
1016 if ( !( availableWidgetsPreviousSelectionCount == 0 && formLayoutPreviousSelectionCount == 0 ) )
1018 const int selectedAvailableWidgetItemCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
1019 const int selectedFormLayoutItemCount =
mFormLayoutView->selectionModel()->selectedRows().count();
1021 if ( selectedAvailableWidgetItemCount == 0 && selectedFormLayoutItemCount == 0 )
1024 clearAttributeTypeFrame();
1029void QgsAttributesFormProperties::onContextMenuRequested( QPoint point )
1040 const QClipboard *clipboard = QApplication::clipboard();
1041 const QMimeData *mimeData = clipboard->mimeData();
1045 const bool pasteEnabled = mimeData->hasFormat( u
"application/x-qgsattributetabledesignerelementclipboard"_s );
1046 mActionPasteWidgetConfiguration->setEnabled( pasteEnabled );
1047 mAvailableWidgetsContextMenu->popup( globalPos );
1051void QgsAttributesFormProperties::copyWidgetConfiguration()
1063 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1065 if ( fieldIndex < 0 )
1068 const QgsField field =
mLayer->fields().field( fieldIndex );
1072 QDomElement documentElement = doc.createElement( u
"FormWidgetClipboard"_s );
1073 documentElement.setAttribute( u
"name"_s, field.
name() );
1078 QDomElement editWidgetElement = doc.createElement( u
"editWidget"_s );
1079 documentElement.appendChild( editWidgetElement );
1080 editWidgetElement.setAttribute( u
"type"_s, widgetSetup.
type() );
1081 QDomElement editWidgetConfigElement = doc.createElement( u
"config"_s );
1084 editWidgetElement.appendChild( editWidgetConfigElement );
1087 QDomElement splitPolicyElement = doc.createElement( u
"splitPolicy"_s );
1089 documentElement.appendChild( splitPolicyElement );
1092 QDomElement duplicatePolicyElement = doc.createElement( u
"duplicatePolicy"_s );
1094 documentElement.appendChild( duplicatePolicyElement );
1097 QDomElement mergePolicyElement = doc.createElement( u
"mergePolicy"_s );
1099 documentElement.appendChild( mergePolicyElement );
1102 QDomElement defaultElem = doc.createElement( u
"default"_s );
1105 documentElement.appendChild( defaultElem );
1108 QDomElement constraintElem = doc.createElement( u
"constraint"_s );
1113 documentElement.appendChild( constraintElem );
1116 QDomElement constraintExpressionElem = doc.createElement( u
"constraintExpression"_s );
1119 documentElement.appendChild( constraintExpressionElem );
1124 QDomElement widgetGeneralSettingsElem = doc.createElement( u
"widgetGeneralSettings"_s );
1125 widgetGeneralSettingsElem.setAttribute( u
"editable"_s,
mAttributeTypeDialog->fieldEditable() );
1126 widgetGeneralSettingsElem.setAttribute( u
"label_on_top"_s,
mAttributeTypeDialog->labelOnTop() );
1128 documentElement.appendChild( widgetGeneralSettingsElem );
1138 const QModelIndex indexLayout =
mFormLayoutView->firstSelectedIndex();
1141 QDomElement displayElement = doc.createElement( u
"widgetDisplay"_s );
1142 displayElement.setAttribute( u
"showLabel"_s, layoutData.showLabel() );
1143 displayElement.setAttribute( u
"horizontalStretch"_s, layoutData.horizontalStretch() );
1144 displayElement.setAttribute( u
"verticalStretch"_s, layoutData.verticalStretch() );
1145 displayElement.appendChild( layoutData.labelStyle().writeXml( doc ) );
1146 documentElement.appendChild( displayElement );
1149 doc.appendChild( documentElement );
1151 QMimeData *mimeData =
new QMimeData;
1152 mimeData->setData( u
"application/x-qgsattributetabledesignerelementclipboard"_s, doc.toByteArray() );
1153 QClipboard *clipboard = QApplication::clipboard();
1154 clipboard->setMimeData( mimeData );
1157void QgsAttributesFormProperties::pasteWidgetConfiguration()
1165 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1167 if ( fieldIndex < 0 )
1174 QClipboard *clipboard = QApplication::clipboard();
1175 const QMimeData *mimeData = clipboard->mimeData();
1179 if ( doc.setContent( mimeData->data( u
"application/x-qgsattributetabledesignerelementclipboard"_s ) ) )
1181 QgsReadWriteContext context;
1182 QDomElement docElem = doc.documentElement();
1183 if ( docElem.tagName() !=
"FormWidgetClipboard"_L1 )
1192 const QDomElement fieldWidgetElement = docElem.firstChildElement( u
"editWidget"_s );
1193 if ( !fieldWidgetElement.isNull() )
1195 const QString widgetType = fieldWidgetElement.attribute( u
"type"_s );
1201 const QDomElement configElement = fieldWidgetElement.firstChildElement( u
"config"_s );
1202 if ( !configElement.isNull() )
1204 const QDomElement optionsElem = configElement.childNodes().at( 0 ).toElement();
1212 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 );
1217 const QDomElement splitPolicyElement = docElem.firstChildElement( u
"splitPolicy"_s );
1218 if ( !splitPolicyElement.isNull() )
1225 const QDomElement duplicatePolicyElement = docElem.firstChildElement( u
"duplicatePolicy"_s );
1226 if ( !duplicatePolicyElement.isNull() )
1233 const QDomElement mergePolicyElement = docElem.firstChildElement( u
"mergePolicy"_s );
1234 if ( !mergePolicyElement.isNull() )
1241 const QDomElement defaultElement = docElem.firstChildElement( u
"default"_s );
1242 if ( !defaultElement.isNull() )
1251 const QDomElement constraintElement = docElem.firstChildElement( u
"constraint"_s );
1252 if ( !constraintElement.isNull() )
1254 const int intConstraints = constraintElement.attribute( u
"constraints"_s, u
"0"_s ).toInt();
1280 const int uniqueStrength = constraintElement.attribute( u
"unique_strength"_s, u
"1"_s ).toInt();
1281 const int notNullStrength = constraintElement.attribute( u
"notnull_strength"_s, u
"1"_s ).toInt();
1282 const int expStrength = constraintElement.attribute( u
"exp_strength"_s, u
"1"_s ).toInt();
1293 const QDomElement constraintExpressionElement = docElem.firstChildElement( u
"constraintExpression"_s );
1294 if ( !constraintExpressionElement.isNull() )
1296 QString expression = constraintExpressionElement.attribute( u
"exp"_s, QString() );
1297 QString description = constraintExpressionElement.attribute( u
"desc"_s, QString() );
1303 const QDomElement widgetGeneralSettingsElement = docElem.firstChildElement( u
"widgetGeneralSettings"_s );
1304 if ( !widgetGeneralSettingsElement.isNull() )
1306 const int editable = widgetGeneralSettingsElement.attribute( u
"editable"_s, u
"0"_s ).toInt();
1308 if ( widgetGeneralSettingsElement.hasAttribute( u
"reuse_last_values"_s ) )
1317 const int labelOnTop = widgetGeneralSettingsElement.attribute( u
"label_on_top"_s, u
"0"_s ).toInt();
1324 loadAttributeTypeDialogFromConfiguration( config );
1329 const QDomElement displayElement = docElem.firstChildElement( u
"widgetDisplay"_s );
1330 if ( !displayElement.isNull() )
1332 const int showLabel = displayElement.attribute( u
"showLabel"_s, u
"0"_s ).toInt();
1333 const int horizontalStretch = displayElement.attribute( u
"horizontalStretch"_s, u
"0"_s ).toInt();
1334 const int verticalStretch = displayElement.attribute( u
"verticalStretch"_s, u
"0"_s ).toInt();
1335 QgsAttributeEditorElement::LabelStyle style;
1336 style.
readXml( displayElement );
1348void QgsAttributesFormProperties::setAvailableWidgetsIndicatorProvidersEnabled(
bool enabled )
1351 if ( enabled && !mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1354 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1356 else if ( !enabled && mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1359 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1362 if ( enabled && !mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1365 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1367 else if ( !enabled && mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1370 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1374void QgsAttributesFormProperties::setFormLayoutIndicatorProvidersEnabled(
bool enabled )
1377 if ( enabled && !mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1380 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1382 else if ( !enabled && mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1385 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1388 if ( enabled && !mConstraintIndicatorProviderFormLayout->isEnabled() )
1391 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1393 else if ( !enabled && mConstraintIndicatorProviderFormLayout->isEnabled() )
1396 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1400void QgsAttributesFormProperties::previewForm()
1402 if ( !mSourceFieldsProperties )
1411 QList<QPair<QgsField, QString>> expressionFields;
1413 for (
int i = 0; i <
mLayer->fields().size(); i++ )
1417 expressionFields << qMakePair(
mLayer->fields().at( i ),
mLayer->expressionField( i ) );
1425 std::unique_ptr<QgsVectorLayer> vlayer;
1427 for (
const QPair<QgsField, QString> &expressionField : std::as_const( expressionFields ) )
1429 vlayer->addExpressionField( expressionField.second, expressionField.first );
1432 mSourceFieldsProperties->applyToLayer( vlayer.get() );
1433 applyToLayer( vlayer.get() );
1436 QgsAttributeDialog form( vlayer.get(), &feature,
false,
this,
true );
1440 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 std::vector< std::unique_ptr< 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.
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.