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 &selected,
const QItemSelection &deselected )
517 if ( selected.isEmpty() && deselected.isEmpty() )
525 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
526 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
529 if (
mFormLayoutView->selectionModel()->selectedRows( 0 ).count() == 1 )
537 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
538 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
541void QgsAttributesFormProperties::onFormLayoutSelectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
543 if ( selected.isEmpty() && deselected.isEmpty() )
551 disconnect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
552 disconnect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
555 if ( deselected.indexes().count() == 1 )
557 index = mFormLayoutProxyModel->mapToSource( deselected.indexes().at( 0 ) );
559 else if ( deselected.indexes().count() == 0 &&
mFormLayoutView->selectionModel()->selectedIndexes().count() == 2 )
566 connect(
mFormLayoutView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
567 connect(
mAvailableWidgetsView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
576 storeAttributeWidgetEdit( deselectedFormLayoutIndex );
577 storeAttributeContainerEdit( deselectedFormLayoutIndex );
581 storeAttributeTypeDialog();
584 clearAttributeTypeFrame();
586 if ( emitter->selectionModel()->selectedRows( 0 ).count() != 1 )
588 receiver->clearSelection();
601 loadAttributeWidgetEdit();
605 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
614 loadAttributeWidgetEdit();
616 loadAttributeTypeDialog();
621 receiver->clearSelection();
622 loadAttributeContainerEdit();
629 loadInfoWidget( action.
html() );
639 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
643 loadInfoWidget( tr(
"This configuration is available with double-click in the Form Layout panel" ) );
645 receiver->clearSelection();
650 receiver->clearSelection();
657void QgsAttributesFormProperties::clearAttributeTypeFrame()
685void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
688 for (
int i = 0; i < mFormLayoutProxyModel->rowCount(); ++i )
690 QModelIndex index = mFormLayoutProxyModel->index( i, 0 );
691 mFormLayoutView->selectionModel()->select( index, QItemSelectionModel::Toggle );
695void QgsAttributesFormProperties::toggleShowAliases(
bool checked )
698 mAvailableWidgetsModel->setShowAliases( checked );
699 mFormLayoutModel->setShowAliases( checked );
702void QgsAttributesFormProperties::addContainer()
704 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList = mFormLayoutModel->listOfContainers();
706 QModelIndex currentItem;
710 QgsAddAttributeFormContainerDialog dialog(
mLayer, existingContainerList, currentItem,
this );
712 if ( !dialog.exec() )
715 const QString name = dialog.name();
716 QModelIndex parentContainerItem = dialog.parentContainerItem();
718 mFormLayoutModel->addContainer( parentContainerItem, name, dialog.columnCount(), dialog.containerType() );
719 if ( parentContainerItem.isValid() )
723void QgsAttributesFormProperties::removeTabOrGroupButton()
727 const QModelIndexList selectedRows =
mFormLayoutView->selectionModel()->selectedRows();
729 QList< QPersistentModelIndex > sourceIndexes;
730 sourceIndexes.reserve( selectedRows.size() );
731 for (
const QModelIndex &proxyIndex : selectedRows )
732 sourceIndexes << QPersistentModelIndex( mFormLayoutProxyModel->mapToSource( proxyIndex ) );
737 for (
const QPersistentModelIndex &sourceIndex : std::as_const( sourceIndexes ) )
739 if ( sourceIndex.isValid() )
740 mFormLayoutModel->removeRow( sourceIndex.row(), sourceIndex.parent() );
744void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
748 if ( selection.count() > 0 )
762 mFormLayoutWidget->setVisible(
false );
763 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
764 mUiFileFrame->setVisible(
false );
765 mAddContainerButton->setVisible(
false );
766 mRemoveLayoutItemButton->setVisible(
false );
767 mInvertSelectionButton->setVisible(
false );
769 setAvailableWidgetsIndicatorProvidersEnabled(
true );
770 setFormLayoutIndicatorProvidersEnabled(
false );
774 mFormLayoutWidget->setVisible(
true );
775 mTreeViewHorizontalSpacer->changeSize( 6, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
776 mUiFileFrame->setVisible(
false );
777 mAddContainerButton->setVisible(
true );
778 mRemoveLayoutItemButton->setVisible(
true );
779 mInvertSelectionButton->setVisible(
true );
781 setAvailableWidgetsIndicatorProvidersEnabled(
false );
782 setFormLayoutIndicatorProvidersEnabled(
true );
787 mFormLayoutWidget->setVisible(
false );
788 mTreeViewHorizontalSpacer->changeSize( 0, 20, QSizePolicy::Fixed, QSizePolicy::Fixed );
789 mUiFileFrame->setVisible(
true );
790 mAddContainerButton->setVisible(
false );
791 mRemoveLayoutItemButton->setVisible(
false );
792 mInvertSelectionButton->setVisible(
false );
794 setAvailableWidgetsIndicatorProvidersEnabled(
true );
795 setFormLayoutIndicatorProvidersEnabled(
false );
800 if ( selection.count() > 0 )
806void QgsAttributesFormProperties::mTbInitCode_clicked()
808 QgsAttributesFormInitCode attributesFormInitCode;
815 if ( !attributesFormInitCode.exec() )
818 mInitCodeSource = attributesFormInitCode.
codeSource();
819 mInitCode = attributesFormInitCode.
initCode();
824void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
826 QgsSettings myQSettings;
827 const QString lastUsedDir = myQSettings.
value( u
"style/lastUIDir"_s, QDir::homePath() ).toString();
828 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
830 if ( uifilename.isNull() )
833 const QFileInfo fi( uifilename );
834 myQSettings.
setValue( u
"style/lastUIDir"_s, fi.path() );
835 mEditFormLineEdit->setText( uifilename );
840 storeAttributeWidgetEdit();
841 storeAttributeContainerEdit();
842 storeAttributeTypeDialog();
852void QgsAttributesFormProperties::applyToLayer(
QgsVectorLayer *layer )
857 const QModelIndex fieldContainer = mAvailableWidgetsModel->
fieldContainer();
860 for (
int i = 0; i < mAvailableWidgetsModel->
rowCount( fieldContainer ); i++ )
862 index = mAvailableWidgetsModel->
index( i, 0, fieldContainer );
922 for (
int t = 0; t < mFormLayoutModel->rowCount(); t++ )
924 QModelIndex index = mFormLayoutModel->index( t, 0 );
925 QgsAttributeEditorElement *editorElement { mFormLayoutModel->createAttributeEditorWidget( index,
nullptr ) };
927 editFormConfig.
addTab( editorElement );
930 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
942 const QModelIndex relationContainer = mAvailableWidgetsModel->relationContainer();
944 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( relationContainer ); i++ )
946 const QModelIndex relationIndex = mAvailableWidgetsModel->index( i, 0, relationContainer );
952 const QModelIndex layoutIndex = mFormLayoutModel->firstRecursiveMatchingModelIndex( indexType, indexId );
953 if ( layoutIndex.isValid() )
957 const QgsAttributesFormData::AttributeFormItemData tabIndexData = layoutIndex.data(
QgsAttributesFormModel::ItemDataRole ).value<QgsAttributesFormData::AttributeFormItemData>();
969void QgsAttributesFormProperties::updatedFields()
972 QMap<QString, QgsAttributesFormData::FieldConfig> fieldConfigs;
974 const QModelIndex fieldContainerBefore = mAvailableWidgetsModel->fieldContainer();
977 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerBefore ); i++ )
979 index = mAvailableWidgetsModel->index( i, 0, fieldContainerBefore );
982 fieldConfigs[fieldName] = config;
987 const QModelIndex fieldContainerAfter = mAvailableWidgetsModel->fieldContainer();
989 for (
int i = 0; i < mAvailableWidgetsModel->rowCount( fieldContainerAfter ); i++ )
991 index = mAvailableWidgetsModel->index( i, 0, fieldContainerAfter );
994 if ( fieldConfigs.contains( fieldName ) )
1002void QgsAttributesFormProperties::updateFilteredItems(
const QString &filterText )
1004 const int availableWidgetsPreviousSelectionCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
1005 const int formLayoutPreviousSelectionCount =
mFormLayoutView->selectionModel()->selectedRows().count();
1007 static_cast< QgsAttributesAvailableWidgetsView *
>(
mAvailableWidgetsView )->setFilterText( filterText );
1010 static_cast< QgsAttributesFormLayoutView *
>(
mFormLayoutView )->setFilterText( filterText );
1015 if ( !( availableWidgetsPreviousSelectionCount == 0 && formLayoutPreviousSelectionCount == 0 ) )
1017 const int selectedAvailableWidgetItemCount =
mAvailableWidgetsView->selectionModel()->selectedRows().count();
1018 const int selectedFormLayoutItemCount =
mFormLayoutView->selectionModel()->selectedRows().count();
1020 if ( selectedAvailableWidgetItemCount == 0 && selectedFormLayoutItemCount == 0 )
1023 clearAttributeTypeFrame();
1028void QgsAttributesFormProperties::onContextMenuRequested( QPoint point )
1039 const QClipboard *clipboard = QApplication::clipboard();
1040 const QMimeData *mimeData = clipboard->mimeData();
1044 const bool pasteEnabled = mimeData->hasFormat( u
"application/x-qgsattributetabledesignerelementclipboard"_s );
1045 mActionPasteWidgetConfiguration->setEnabled( pasteEnabled );
1046 mAvailableWidgetsContextMenu->popup( globalPos );
1050void QgsAttributesFormProperties::copyWidgetConfiguration()
1062 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1064 if ( fieldIndex < 0 )
1067 const QgsField field =
mLayer->fields().field( fieldIndex );
1071 QDomElement documentElement = doc.createElement( u
"FormWidgetClipboard"_s );
1072 documentElement.setAttribute( u
"name"_s, field.
name() );
1077 QDomElement editWidgetElement = doc.createElement( u
"editWidget"_s );
1078 documentElement.appendChild( editWidgetElement );
1079 editWidgetElement.setAttribute( u
"type"_s, widgetSetup.
type() );
1080 QDomElement editWidgetConfigElement = doc.createElement( u
"config"_s );
1083 editWidgetElement.appendChild( editWidgetConfigElement );
1086 QDomElement splitPolicyElement = doc.createElement( u
"splitPolicy"_s );
1088 documentElement.appendChild( splitPolicyElement );
1091 QDomElement duplicatePolicyElement = doc.createElement( u
"duplicatePolicy"_s );
1093 documentElement.appendChild( duplicatePolicyElement );
1096 QDomElement mergePolicyElement = doc.createElement( u
"mergePolicy"_s );
1098 documentElement.appendChild( mergePolicyElement );
1101 QDomElement defaultElem = doc.createElement( u
"default"_s );
1104 documentElement.appendChild( defaultElem );
1107 QDomElement constraintElem = doc.createElement( u
"constraint"_s );
1112 documentElement.appendChild( constraintElem );
1115 QDomElement constraintExpressionElem = doc.createElement( u
"constraintExpression"_s );
1118 documentElement.appendChild( constraintExpressionElem );
1123 QDomElement widgetGeneralSettingsElem = doc.createElement( u
"widgetGeneralSettings"_s );
1124 widgetGeneralSettingsElem.setAttribute( u
"editable"_s,
mAttributeTypeDialog->fieldEditable() );
1125 widgetGeneralSettingsElem.setAttribute( u
"label_on_top"_s,
mAttributeTypeDialog->labelOnTop() );
1127 documentElement.appendChild( widgetGeneralSettingsElem );
1137 const QModelIndex indexLayout =
mFormLayoutView->firstSelectedIndex();
1140 QDomElement displayElement = doc.createElement( u
"widgetDisplay"_s );
1141 displayElement.setAttribute( u
"showLabel"_s, layoutData.showLabel() );
1142 displayElement.setAttribute( u
"horizontalStretch"_s, layoutData.horizontalStretch() );
1143 displayElement.setAttribute( u
"verticalStretch"_s, layoutData.verticalStretch() );
1144 displayElement.appendChild( layoutData.labelStyle().writeXml( doc ) );
1145 documentElement.appendChild( displayElement );
1148 doc.appendChild( documentElement );
1150 QMimeData *mimeData =
new QMimeData;
1151 mimeData->setData( u
"application/x-qgsattributetabledesignerelementclipboard"_s, doc.toByteArray() );
1152 QClipboard *clipboard = QApplication::clipboard();
1153 clipboard->setMimeData( mimeData );
1156void QgsAttributesFormProperties::pasteWidgetConfiguration()
1164 const int fieldIndex =
mLayer->fields().indexOf( fieldName );
1166 if ( fieldIndex < 0 )
1173 QClipboard *clipboard = QApplication::clipboard();
1174 const QMimeData *mimeData = clipboard->mimeData();
1178 if ( doc.setContent( mimeData->data( u
"application/x-qgsattributetabledesignerelementclipboard"_s ) ) )
1180 QgsReadWriteContext context;
1181 QDomElement docElem = doc.documentElement();
1182 if ( docElem.tagName() !=
"FormWidgetClipboard"_L1 )
1191 const QDomElement fieldWidgetElement = docElem.firstChildElement( u
"editWidget"_s );
1192 if ( !fieldWidgetElement.isNull() )
1194 const QString widgetType = fieldWidgetElement.attribute( u
"type"_s );
1200 const QDomElement configElement = fieldWidgetElement.firstChildElement( u
"config"_s );
1201 if ( !configElement.isNull() )
1203 const QDomElement optionsElem = configElement.childNodes().at( 0 ).toElement();
1211 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 );
1216 const QDomElement splitPolicyElement = docElem.firstChildElement( u
"splitPolicy"_s );
1217 if ( !splitPolicyElement.isNull() )
1224 const QDomElement duplicatePolicyElement = docElem.firstChildElement( u
"duplicatePolicy"_s );
1225 if ( !duplicatePolicyElement.isNull() )
1232 const QDomElement mergePolicyElement = docElem.firstChildElement( u
"mergePolicy"_s );
1233 if ( !mergePolicyElement.isNull() )
1240 const QDomElement defaultElement = docElem.firstChildElement( u
"default"_s );
1241 if ( !defaultElement.isNull() )
1250 const QDomElement constraintElement = docElem.firstChildElement( u
"constraint"_s );
1251 if ( !constraintElement.isNull() )
1253 const int intConstraints = constraintElement.attribute( u
"constraints"_s, u
"0"_s ).toInt();
1279 const int uniqueStrength = constraintElement.attribute( u
"unique_strength"_s, u
"1"_s ).toInt();
1280 const int notNullStrength = constraintElement.attribute( u
"notnull_strength"_s, u
"1"_s ).toInt();
1281 const int expStrength = constraintElement.attribute( u
"exp_strength"_s, u
"1"_s ).toInt();
1292 const QDomElement constraintExpressionElement = docElem.firstChildElement( u
"constraintExpression"_s );
1293 if ( !constraintExpressionElement.isNull() )
1295 QString expression = constraintExpressionElement.attribute( u
"exp"_s, QString() );
1296 QString description = constraintExpressionElement.attribute( u
"desc"_s, QString() );
1302 const QDomElement widgetGeneralSettingsElement = docElem.firstChildElement( u
"widgetGeneralSettings"_s );
1303 if ( !widgetGeneralSettingsElement.isNull() )
1305 const int editable = widgetGeneralSettingsElement.attribute( u
"editable"_s, u
"0"_s ).toInt();
1307 if ( widgetGeneralSettingsElement.hasAttribute( u
"reuse_last_values"_s ) )
1316 const int labelOnTop = widgetGeneralSettingsElement.attribute( u
"label_on_top"_s, u
"0"_s ).toInt();
1323 loadAttributeTypeDialogFromConfiguration( config );
1328 const QDomElement displayElement = docElem.firstChildElement( u
"widgetDisplay"_s );
1329 if ( !displayElement.isNull() )
1331 const int showLabel = displayElement.attribute( u
"showLabel"_s, u
"0"_s ).toInt();
1332 const int horizontalStretch = displayElement.attribute( u
"horizontalStretch"_s, u
"0"_s ).toInt();
1333 const int verticalStretch = displayElement.attribute( u
"verticalStretch"_s, u
"0"_s ).toInt();
1334 QgsAttributeEditorElement::LabelStyle style;
1335 style.
readXml( displayElement );
1347void QgsAttributesFormProperties::setAvailableWidgetsIndicatorProvidersEnabled(
bool enabled )
1350 if ( enabled && !mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1353 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1355 else if ( !enabled && mDefaultValueIndicatorProviderAvailableWidgets->isEnabled() )
1358 mDefaultValueIndicatorProviderAvailableWidgets->setEnabled( enabled );
1361 if ( enabled && !mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1364 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1366 else if ( !enabled && mConstraintIndicatorProviderAvailableWidgets->isEnabled() )
1369 mConstraintIndicatorProviderAvailableWidgets->setEnabled( enabled );
1373void QgsAttributesFormProperties::setFormLayoutIndicatorProvidersEnabled(
bool enabled )
1376 if ( enabled && !mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1379 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1381 else if ( !enabled && mDefaultValueIndicatorProviderFormLayout->isEnabled() )
1384 mDefaultValueIndicatorProviderFormLayout->setEnabled( enabled );
1387 if ( enabled && !mConstraintIndicatorProviderFormLayout->isEnabled() )
1390 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1392 else if ( !enabled && mConstraintIndicatorProviderFormLayout->isEnabled() )
1395 mConstraintIndicatorProviderFormLayout->setEnabled( enabled );
1399void QgsAttributesFormProperties::previewForm()
1401 if ( !mSourceFieldsProperties )
1410 QList<QPair<QgsField, QString>> expressionFields;
1412 for (
int i = 0; i <
mLayer->fields().size(); i++ )
1416 expressionFields << qMakePair(
mLayer->fields().at( i ),
mLayer->expressionField( i ) );
1424 std::unique_ptr<QgsVectorLayer> vlayer;
1426 for (
const QPair<QgsField, QString> &expressionField : std::as_const( expressionFields ) )
1428 vlayer->addExpressionField( expressionField.second, expressionField.first );
1431 mSourceFieldsProperties->applyToLayer( vlayer.get() );
1432 applyToLayer( vlayer.get() );
1435 QgsAttributeDialog form( vlayer.get(), &feature,
false,
this,
true );
1439 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.
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.