21#include "qgsattributetypedialog.h"
22#include "qgsattributeformcontaineredit.h"
23#include "qgsattributewidgetedit.h"
60 QGridLayout *availableWidgetsWidgetLayout =
new QGridLayout;
63 availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
64 mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout );
70 QGridLayout *formLayoutWidgetLayout =
new QGridLayout;
72 mFormLayoutWidget->setLayout( formLayoutWidgetLayout );
74 formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
75 mFormLayoutTree->setHeaderLabels( QStringList() << tr(
"Form Layout" ) );
78 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
79 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
80 connect( mAddTabOrGroupButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::addContainer );
81 connect( mRemoveTabOrGroupButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::removeTabOrGroupButton );
82 connect( mInvertSelectionButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked );
83 connect( mEditorLayoutComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged );
84 connect( pbnSelectEditForm, &QToolButton::clicked,
this, &QgsAttributesFormProperties::pbnSelectEditForm_clicked );
85 connect( mTbInitCode, &QPushButton::clicked,
this, &QgsAttributesFormProperties::mTbInitCode_clicked );
118 for (
int i = 0; i < fields.
size(); ++i )
132 if ( !field.
alias().isEmpty() )
133 tooltip = tr(
"%1 (%2)" ).arg( field.
name(), field.
alias() );
135 tooltip = field.
name();
136 item->setToolTip( 0, tooltip );
138 catitem->setExpanded(
true );
153 catitem->setExpanded(
true );
161 for (
const auto &action : std::as_const( actions ) )
163 if ( action.isValid() && action.runable() &&
164 ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) ||
165 action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
167 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
194 catitem ->setExpanded(
true );
202 mFormLayoutTree->setSelectionBehavior( QAbstractItemView::SelectRows );
203 mFormLayoutTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
240 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( QVariant::fromValue(
mLayer->
editFormConfig().
layout() ) ) );
242 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
245 mEditFormLineEdit->setText( cfg.
uiForm() );
257 if ( mInitCode.isEmpty() )
259 mInitCode.append( tr(
"# -*- coding: utf-8 -*-\n\"\"\"\n"
260 "QGIS forms can have a Python function that is called when the form is\n"
263 "Use this function to add extra logic to your forms.\n"
265 "Enter the name of the function in the \"Python Init function\"\n"
267 "An example follows:\n"
269 "from qgis.PyQt.QtWidgets import QWidget\n\n"
270 "def my_form_open(dialog, layer, feature):\n"
271 " geom = feature.geometry()\n"
272 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n" ) );
276void QgsAttributesFormProperties::loadAttributeTypeDialog()
283 const FieldConfig cfg = item->data( 0,
FieldConfigRole ).value<FieldConfig>();
284 const QString fieldName = item->data( 0,
FieldNameRole ).toString();
326 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
332void QgsAttributesFormProperties::storeAttributeTypeDialog()
384 cfg.mFieldConstraints = constraints;
397 QTreeWidgetItem *item = *itemIt;
398 if ( item->data( 0,
FieldNameRole ).toString() == fieldName )
399 item->setData( 0,
FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
403void QgsAttributesFormProperties::storeAttributeWidgetEdit()
411void QgsAttributesFormProperties::loadAttributeWidgetEdit()
416 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
418 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
422void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
425 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
429void QgsAttributesFormProperties::storeAttributeContainerEdit()
437void QgsAttributesFormProperties::loadAttributeContainerEdit()
442 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
446 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
453 auto setCommonProperties = [widgetDef]( DnDTreeItemData & itemData )
455 itemData.setShowLabel( widgetDef->
showLabel() );
456 itemData.setLabelStyle( widgetDef->
labelStyle() );
461 QTreeWidgetItem *newWidget =
nullptr;
462 switch ( widgetDef->
type() )
467 setCommonProperties( itemData );
468 newWidget = tree->
addItem( parent, itemData );
476 if ( action.isValid() )
478 DnDTreeItemData itemData = DnDTreeItemData(
DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
479 setCommonProperties( itemData );
480 newWidget = tree->
addItem( parent, itemData );
493 setCommonProperties( itemData );
495 RelationEditorConfiguration relEdConfig;
499 relEdConfig.nmRelationId = relationEditor->
nmRelationId();
501 relEdConfig.label = relationEditor->
label();
502 itemData.setRelationEditorConfiguration( relEdConfig );
503 newWidget = tree->
addItem( parent, itemData );
516 itemData.setContainerType( container->
type() );
520 itemData.setCollapsed( container->
collapsed() );
522 setCommonProperties( itemData );
524 newWidget = tree->
addItem( parent, itemData );
526 const QList<QgsAttributeEditorElement *> children = container->
children();
529 loadAttributeEditorTreeItem( wdg, newWidget, tree );
538 QmlElementEditorConfiguration qmlEdConfig;
539 qmlEdConfig.qmlCode = qmlElementEditor->
qmlCode();
540 itemData.setQmlElementEditorConfiguration( qmlEdConfig );
541 setCommonProperties( itemData );
542 newWidget = tree->
addItem( parent, itemData );
550 HtmlElementEditorConfiguration htmlEdConfig;
551 htmlEdConfig.htmlCode = htmlElementEditor->
htmlCode();
552 itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
553 setCommonProperties( itemData );
554 newWidget = tree->
addItem( parent, itemData );
562 TextElementEditorConfiguration textEdConfig;
563 textEdConfig.text = textElementEditor->
text();
564 itemData.setTextElementEditorConfiguration( textEdConfig );
565 setCommonProperties( itemData );
566 newWidget = tree->
addItem( parent, itemData );
574 SpacerElementEditorConfiguration spacerEdConfig;
575 spacerEdConfig.drawLine = spacerElementEditor->
drawLine();
576 itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
577 setCommonProperties( itemData );
578 itemData.setShowLabel(
false );
579 newWidget = tree->
addItem( parent, itemData );
585 QgsDebugError( QStringLiteral(
"Not loading invalid attribute editor type..." ) );
591 newWidget->setExpanded(
true );
597void QgsAttributesFormProperties::onAttributeSelectionChanged()
599 disconnect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
601 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
604void QgsAttributesFormProperties::onFormLayoutSelectionChanged()
607 disconnect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
609 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
617 storeAttributeWidgetEdit();
619 clearAttributeTypeFrame();
621 if ( emitter->selectedItems().count() != 1 )
623 receiver->clearSelection();
627 const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
628 switch ( itemData.type() )
635 loadAttributeWidgetEdit();
639 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
647 loadAttributeWidgetEdit();
648 loadAttributeTypeDialog();
653 receiver->clearSelection();
654 loadAttributeContainerEdit();
661 loadInfoWidget( action.html() );
671 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
675 loadInfoWidget( tr(
"This configuration is available with double-click" ) );
677 receiver->clearSelection();
682 receiver->clearSelection();
689void QgsAttributesFormProperties::clearAttributeTypeFrame()
717void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
722 for (
int i = 0; i < rootItem->childCount(); ++i )
724 rootItem->child( i )->setSelected( ! selectedItemList.contains( rootItem->child( i ) ) );
728void QgsAttributesFormProperties::addContainer()
730 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList;
734 const DnDTreeItemData itemData = ( *it )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
740 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().value( 0 );
743 if ( !dialog.exec() )
746 const QString name = dialog.name();
747 QTreeWidgetItem *parentContainerItem = dialog.parentContainerItem();
750 dialog.columnCount(),
751 dialog.containerType() );
754void QgsAttributesFormProperties::removeTabOrGroupButton()
760 const QList<QTreeWidgetItem *> items =
mFormLayoutTree->selectedItems();
764 delete items.at( 0 );
775 switch ( itemData.
type() )
823 for (
int t = 0; t < item->childCount(); t++ )
830 widgetDef = container;
882void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
888 mFormLayoutWidget->setVisible(
false );
889 mUiFileFrame->setVisible(
false );
890 mAddTabOrGroupButton->setVisible(
false );
891 mRemoveTabOrGroupButton->setVisible(
false );
892 mInvertSelectionButton->setVisible(
false );
896 mFormLayoutWidget->setVisible(
true );
897 mUiFileFrame->setVisible(
false );
898 mAddTabOrGroupButton->setVisible(
true );
899 mRemoveTabOrGroupButton->setVisible(
true );
900 mInvertSelectionButton->setVisible(
true );
905 mFormLayoutWidget->setVisible(
false );
906 mUiFileFrame->setVisible(
true );
907 mAddTabOrGroupButton->setVisible(
false );
908 mRemoveTabOrGroupButton->setVisible(
false );
909 mInvertSelectionButton->setVisible(
false );
914void QgsAttributesFormProperties::mTbInitCode_clicked()
923 if ( !attributesFormInitCode.exec() )
926 mInitCodeSource = attributesFormInitCode.
codeSource();
927 mInitCode = attributesFormInitCode.
initCode();
933void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
936 const QString lastUsedDir = myQSettings.
value( QStringLiteral(
"style/lastUIDir" ), QDir::homePath() ).toString();
937 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
939 if ( uifilename.isNull() )
942 const QFileInfo fi( uifilename );
943 myQSettings.
setValue( QStringLiteral(
"style/lastUIDir" ), fi.path() );
944 mEditFormLineEdit->setText( uifilename );
949 storeAttributeWidgetEdit();
950 storeAttributeContainerEdit();
951 storeAttributeTypeDialog();
957 storeAttributeWidgetEdit();
958 storeAttributeContainerEdit();
959 storeAttributeTypeDialog();
965 for (
int i = 0; i < fieldContainer->childCount(); i++ )
967 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
970 const QString fieldName { fieldItem->data( 0,
FieldNameRole ).toString() };
1022 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1024 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1026 if ( editorElement )
1027 editFormConfig.
addTab( editorElement );
1030 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
1044 for (
int i = 0; i < relationContainer->childCount(); i++ )
1046 QTreeWidgetItem *relationItem = relationContainer->child( i );
1049 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1051 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1054 if ( tabItemData.
type() == itemData.
type() && tabItemData.
name() == itemData.
name() )
1091QgsAttributesFormProperties::FieldConfig::operator QVariant()
1093 return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *
this );
1100QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
1102 return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *
this );
1111 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << title );
1112 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1113 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1118 parent->addChild( newItem );
1119 newItem->setExpanded(
true );
1124 : QTreeWidget( parent )
1127 connect(
this, &QTreeWidget::itemDoubleClicked,
this, &QgsAttributesDnDTree::onItemDoubleClicked );
1132 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << data.
name() );
1134 switch ( data.
type() )
1143 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1149 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1150 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1157 newItem->setIcon( 0, icon );
1160 parent->addChild( newItem );
1162 parent->insertChild( index, newItem );
1174 const QMimeData *data =
event->mimeData();
1176 if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1180 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1181 QDataStream stream( &itemData, QIODevice::ReadOnly );
1182 stream >> itemElement;
1185 if ( event->source() ==
this )
1187 event->setDropAction( Qt::MoveAction );
1195 QTreeWidget::dragMoveEvent( event );
1201 bool bDropSuccessful =
false;
1203 if ( action == Qt::IgnoreAction )
1205 bDropSuccessful =
true;
1207 else if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1209 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1210 QDataStream stream( &itemData, QIODevice::ReadOnly );
1213 while ( !stream.atEnd() )
1215 stream >> itemElement;
1217 QTreeWidgetItem *newItem;
1221 newItem =
addItem( parent, itemElement, index++ );
1222 bDropSuccessful =
true;
1226 newItem =
addItem( invisibleRootItem(), itemElement, index++ );
1227 bDropSuccessful =
true;
1232 onItemDoubleClicked( newItem, 0 );
1237 onItemDoubleClicked( newItem, 0 );
1242 onItemDoubleClicked( newItem, 0 );
1247 onItemDoubleClicked( newItem, 0 );
1251 newItem->setSelected(
true );
1255 return bDropSuccessful;
1260 if ( !event->mimeData()->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1263 if ( event->source() ==
this )
1265 event->setDropAction( Qt::MoveAction );
1268 QTreeWidget::dropEvent( event );
1273 return QStringList() << QStringLiteral(
"application/x-qgsattributetabledesignerelement" );
1276#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1282 if ( items.count() <= 0 )
1285 const QStringList types = mimeTypes();
1287 if ( types.isEmpty() )
1290 QMimeData *data =
new QMimeData();
1291 const QString format = types.at( 0 );
1293 QDataStream stream( &encoded, QIODevice::WriteOnly );
1295 const auto constItems = items;
1296 for (
const QTreeWidgetItem *item : constItems )
1306 data->setData( format, encoded );
1311void QgsAttributesDnDTree::onItemDoubleClicked( QTreeWidgetItem *item,
int column )
1317 QGroupBox *baseData =
new QGroupBox( tr(
"Base configuration" ) );
1319 QFormLayout *baseLayout =
new QFormLayout();
1320 baseData->setLayout( baseLayout );
1321 QCheckBox *showLabelCheckbox =
new QCheckBox( QStringLiteral(
"Show label" ) );
1322 showLabelCheckbox->setChecked( itemData.
showLabel() );
1323 baseLayout->addRow( showLabelCheckbox );
1324 QWidget *baseWidget =
new QWidget();
1325 baseWidget->setLayout( baseLayout );
1327 switch ( itemData.
type() )
1342 dlg.setWindowTitle( tr(
"Configure QML Widget" ) );
1344 QVBoxLayout *mainLayout =
new QVBoxLayout();
1345 QHBoxLayout *qmlLayout =
new QHBoxLayout();
1346 QVBoxLayout *layout =
new QVBoxLayout();
1347 mainLayout->addLayout( qmlLayout );
1348 qmlLayout->addLayout( layout );
1349 dlg.setLayout( mainLayout );
1350 layout->addWidget( baseWidget );
1352 QLineEdit *title =
new QLineEdit( itemData.
name() );
1363 connect( qmlCode, &QsciScintilla::textChanged,
this, [ = ]
1371 QComboBox *qmlObjectTemplate =
new QComboBox();
1372 qmlObjectTemplate->addItem( tr(
"Free Text…" ) );
1373 qmlObjectTemplate->addItem( tr(
"Rectangle" ) );
1374 qmlObjectTemplate->addItem( tr(
"Pie Chart" ) );
1375 qmlObjectTemplate->addItem( tr(
"Bar Chart" ) );
1376 connect( qmlObjectTemplate, qOverload<int>( &QComboBox::activated ), qmlCode, [ = ](
int index )
1383 qmlCode->setText( QString() );
1388 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1393 " color: \"steelblue\"\n"
1394 " Text{ text: \"A rectangle\" }\n"
1400 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1401 "import QtCharts 2.0\n"
1409 " PieSlice { label: \"First slice\"; value: 25 }\n"
1410 " PieSlice { label: \"Second slice\"; value: 45 }\n"
1411 " PieSlice { label: \"Third slice\"; value: 30 }\n"
1418 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1419 "import QtCharts 2.0\n"
1422 " title: \"Bar series\"\n"
1425 " legend.alignment: Qt.AlignBottom\n"
1426 " antialiasing: true\n"
1435 " axisY: valueAxisY\n"
1436 " axisX: BarCategoryAxis { categories: [\"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\" ] }\n"
1437 " BarSet { label: \"Bob\"; values: [2, 2, 3, 4, 5, 6] }\n"
1438 " BarSet { label: \"Susan\"; values: [5, 1, 2, 4, 1, 7] }\n"
1439 " BarSet { label: \"James\"; values: [3, 5, 8, 13, 5, 8] }\n"
1451 expressionWidget->registerExpressionContextGenerator(
this );
1452 expressionWidget->setLayer( mLayer );
1453 QToolButton *addFieldButton =
new QToolButton();
1456 QToolButton *editExpressionButton =
new QToolButton();
1458 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1460 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1462 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1463 if ( !expression.isEmpty() )
1464 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1467 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1470 expression.replace( QLatin1String(
"\\\"" ), QLatin1String(
"\"" ) );
1474 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1475 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1477 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1478 if ( !expression.isEmpty() )
1479 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1483 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1484 layout->addWidget( title );
1485 QGroupBox *qmlCodeBox =
new QGroupBox( tr(
"QML Code" ) );
1486 qmlCodeBox->setLayout(
new QVBoxLayout );
1487 qmlCodeBox->layout()->addWidget( qmlObjectTemplate );
1488 QWidget *expressionWidgetBox =
new QWidget();
1489 qmlCodeBox->layout()->addWidget( expressionWidgetBox );
1490 expressionWidgetBox->setLayout(
new QHBoxLayout );
1491 expressionWidgetBox->layout()->setContentsMargins( 0, 0, 0, 0 );
1492 expressionWidgetBox->layout()->addWidget( expressionWidget );
1493 expressionWidgetBox->layout()->addWidget( addFieldButton );
1494 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1495 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1496 layout->addWidget( qmlCodeBox );
1497 layout->addWidget( qmlCode );
1499 qmlPreviewBox->setLayout(
new QGridLayout );
1500 qmlPreviewBox->setMinimumWidth( 400 );
1501 qmlPreviewBox->layout()->addWidget( qmlWrapper->
widget() );
1503 emit qmlCode->textChanged();
1504 qmlLayout->addWidget( qmlPreviewBox );
1506 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1508 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1509 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1511 mainLayout->addWidget( buttonBox );
1516 qmlEdCfg.
qmlCode = qmlCode->text();
1517 itemData.
setName( title->text() );
1519 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1522 item->setText( 0, title->text() );
1532 dlg.setWindowTitle( tr(
"Configure HTML Widget" ) );
1534 QVBoxLayout *mainLayout =
new QVBoxLayout();
1535 QHBoxLayout *htmlLayout =
new QHBoxLayout();
1536 QVBoxLayout *layout =
new QVBoxLayout();
1537 mainLayout->addLayout( htmlLayout );
1538 htmlLayout->addLayout( layout );
1539 dlg.setLayout( mainLayout );
1540 layout->addWidget( baseWidget );
1542 QLineEdit *title =
new QLineEdit( itemData.
name() );
1546 htmlCode->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1554 connect( htmlCode, &QgsCodeEditorHTML::textChanged,
this, [ = ]
1563 expressionWidget->registerExpressionContextGenerator(
this );
1564 expressionWidget->setLayer( mLayer );
1565 QToolButton *addFieldButton =
new QToolButton();
1568 QToolButton *editExpressionButton =
new QToolButton();
1570 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1572 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1574 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1575 if ( !expression.isEmpty() )
1576 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1579 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1582 expression.replace( QLatin1String(
"\\\"" ), QLatin1String(
"\"" ) );
1586 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1587 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1589 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1590 if ( !expression.isEmpty() )
1591 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1595 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1596 layout->addWidget( title );
1597 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"HTML Code" ) );
1598 layout->addWidget( expressionWidgetBox );
1599 expressionWidgetBox->setLayout(
new QHBoxLayout );
1600 expressionWidgetBox->layout()->addWidget( expressionWidget );
1601 expressionWidgetBox->layout()->addWidget( addFieldButton );
1602 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1603 layout->addWidget( htmlCode );
1605 htmlPreviewBox->setLayout(
new QGridLayout );
1606 htmlPreviewBox->setMinimumWidth( 400 );
1607 htmlPreviewBox->layout()->addWidget( htmlWrapper->
widget() );
1609 emit htmlCode->textChanged();
1610 htmlLayout->addWidget( htmlPreviewBox );
1612 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1614 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1615 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1617 mainLayout->addWidget( buttonBox );
1622 htmlEdCfg.
htmlCode = htmlCode->text();
1623 itemData.
setName( title->text() );
1625 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1628 item->setText( 0, title->text() );
1638 dlg.setWindowTitle( tr(
"Configure Text Widget" ) );
1640 QVBoxLayout *mainLayout =
new QVBoxLayout();
1641 QHBoxLayout *textLayout =
new QHBoxLayout();
1642 QVBoxLayout *layout =
new QVBoxLayout();
1643 mainLayout->addLayout( textLayout );
1644 textLayout->addLayout( layout );
1645 dlg.setLayout( mainLayout );
1646 layout->addWidget( baseWidget );
1648 QLineEdit *title =
new QLineEdit( itemData.
name() );
1651 text->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1659 connect( text, &QgsCodeEditorExpression::textChanged,
this, [ = ]
1661 textWrapper->
setText( text->text( ) );
1668 expressionWidget->registerExpressionContextGenerator(
this );
1669 expressionWidget->setLayer( mLayer );
1670 QToolButton *addFieldButton =
new QToolButton();
1673 QToolButton *editExpressionButton =
new QToolButton();
1675 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1677 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1679 QString expression = expressionWidget->expression().trimmed();
1680 if ( !expression.isEmpty() )
1681 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1683 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1690 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1691 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1693 QString expression = exprDlg.expressionText().trimmed();
1694 if ( !expression.isEmpty() )
1695 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1699 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1700 layout->addWidget( title );
1701 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"Text" ) );
1702 layout->addWidget( expressionWidgetBox );
1703 expressionWidgetBox->setLayout(
new QHBoxLayout );
1704 expressionWidgetBox->layout()->addWidget( expressionWidget );
1705 expressionWidgetBox->layout()->addWidget( addFieldButton );
1706 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1707 layout->addWidget( text );
1709 textPreviewBox->setLayout(
new QGridLayout );
1710 textPreviewBox->setMinimumWidth( 400 );
1711 textPreviewBox->layout()->addWidget( textWrapper->
widget() );
1713 emit text->textChanged();
1714 textLayout->addWidget( textPreviewBox );
1716 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1718 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1719 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1721 mainLayout->addWidget( buttonBox );
1726 textEdCfg.
text = text->text();
1727 itemData.
setName( title->text() );
1729 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1732 item->setText( 0, title->text() );
1742 dlg.setWindowTitle( tr(
"Configure Spacer Widget" ) );
1744 QVBoxLayout *mainLayout =
new QVBoxLayout();
1745 mainLayout->addWidget(
new QLabel( tr(
"Title" ) ) );
1746 QLineEdit *title =
new QLineEdit( itemData.
name() );
1747 mainLayout->addWidget( title );
1749 QHBoxLayout *cbLayout =
new QHBoxLayout( );
1750 mainLayout->addLayout( cbLayout );
1751 dlg.setLayout( mainLayout );
1752 QCheckBox *cb =
new QCheckBox { &dlg };
1754 cbLayout->addWidget(
new QLabel( tr(
"Draw horizontal line" ), &dlg ) );
1755 cbLayout->addWidget( cb );
1758 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1760 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1761 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1763 mainLayout->addWidget( buttonBox );
1768 spacerEdCfg.
drawLine = cb->isChecked();
1771 itemData.
setName( title->text() );
1773 item->setText( 0, title->text() );
1806 QTreeWidgetItemIterator it(
this );
1812 if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
1819 ( *it )->setSelected(
true );
1842 QString displayName;
1845 stream >> type >> name >> displayName;
1856 return mContainerType;
1861 mContainerType = type;
1871 mLabelStyle = labelStyle;
1881 mShowLabel = showLabel;
1886 return mVisibilityExpression;
1891 mVisibilityExpression = visibilityExpression;
1896 return mCollapsedExpression;
1901 mCollapsedExpression = collapsedExpression;
1906 return mRelationEditorConfiguration;
1911 mRelationEditorConfiguration = relationEditorConfiguration;
1916 return mQmlElementEditorConfiguration;
1921 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
1927 return mHtmlElementEditorConfiguration;
1932 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
1937 return mSpacerElementEditorConfiguration;
1942 mSpacerElementEditorConfiguration = spacerElementEditorConfiguration;
1947 return mBackgroundColor;
1952 mBackgroundColor = backgroundColor;
1957 return mTextElementEditorConfiguration;
1962 mTextElementEditorConfiguration = textElementEditorConfiguration;
1965void QgsAttributesFormProperties::updatedFields()
1968 QMap<QString, FieldConfig> fieldConfigs;
1970 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1972 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1973 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1975 fieldConfigs[fieldName] = cfg;
1981 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1983 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1984 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1985 if ( fieldConfigs.contains( fieldName ) )
AttributeEditorContainerType
Attribute editor container types.
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.
@ Action
A layer action element.
@ QmlElement
A QML element.
@ HtmlElement
A HTML element.
@ TextElement
A text element.
@ SpacerElement
A spacer element.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QgsAction action(QUuid id) const
Gets an action by its id.
Utility class that encapsulates an action based on vector attributes.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
This element will load a layer action onto the form.
const QgsAction & action(const QgsVectorLayer *layer) const
Returns the (possibly lazy loaded) action for the given layer.
This is a container for attribute editors, used to group them visually in the attribute form if it is...
virtual void addChildElement(QgsAttributeEditorElement *element)
Add a child element to this container.
QgsOptionalExpression visibilityExpression() const
The visibility expression is used in the attribute form to show or hide this container based on an ex...
void setColumnCount(int columnCount)
Set the number of columns in this group.
void setVisibilityExpression(const QgsOptionalExpression &visibilityExpression)
The visibility expression is used in the attribute form to show or hide this container based on an ex...
QgsOptionalExpression collapsedExpression() const
The collapsed expression is used in the attribute form to set the collapsed status of the group box c...
bool collapsed() const
For group box containers returns true if this group box is collapsed.
Qgis::AttributeEditorContainerType type() const
Returns the container type.
void setType(Qgis::AttributeEditorContainerType type)
Sets the container type.
void setCollapsedExpression(const QgsOptionalExpression &collapsedExpression)
The collapsed expression is used in the attribute form to set the collapsed status of the group box o...
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
QColor backgroundColor() const
Returns the background color of the container.
void setCollapsed(bool collapsed)
For group box containers sets if this group box is collapsed.
int columnCount() const
Gets the number of columns in this group.
void setBackgroundColor(const QColor &backgroundColor)
Sets the background color to backgroundColor.
This is an abstract base class for any elements of a drag and drop form.
void setHorizontalStretch(int stretch)
Sets the horizontal stretch factor for the element.
LabelStyle labelStyle() const
Returns the label style.
void setLabelStyle(const LabelStyle &labelStyle)
Sets the labelStyle.
Qgis::AttributeEditorType type() const
The type of this element.
int verticalStretch() const
Returns the vertical stretch factor for the element.
bool showLabel() const
Controls if this element should be labeled with a title (field, relation or groupname).
QString name() const
Returns the name of this element.
void setVerticalStretch(int stretch)
Sets the vertical stretch factor for the element.
void setShowLabel(bool showLabel)
Controls if this element should be labeled with a title (field, relation or groupname).
int horizontalStretch() const
Returns the horizontal stretch factor for the element.
This element will load a field's widget onto the form.
An attribute editor widget that will represent arbitrary HTML code.
QString htmlCode() const
The Html code that will be represented within this widget.
void setHtmlCode(const QString &htmlCode)
Sets the HTML code that will be represented within this widget to htmlCode.
An attribute editor widget that will represent arbitrary QML code.
QString qmlCode() const
The QML code that will be represented within this widget.
void setQmlCode(const QString &qmlCode)
Sets the QML code that will be represented within this widget to qmlCode.
This element will load a relation editor onto the form.
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
void setRelationWidgetTypeId(const QString &relationWidgetTypeId)
Sets the relation widget type.
const QgsRelation & relation() const
Gets the id of the relation which shall be embedded.
QVariantMap relationEditorConfiguration() const
Returns the relation editor widget configuration.
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup.
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
bool forceSuppressFormPopup() const
Determines the force suppress form popup status.
QString relationWidgetTypeId() const
Returns the current relation widget type id.
void setRelationEditorConfiguration(const QVariantMap &config)
Sets the relation editor configuration.
void setLabel(const QString &label=QString())
Sets label for this element If it's empty it takes the relation id as label.
QString label() const
Determines the label of this element.
An attribute editor widget that will represent a spacer.
void setDrawLine(bool drawLine)
Sets a flag to define if the spacer element will contain an horizontal line.
bool drawLine() const
Returns true if the spacer element will contain an horizontal line.
An attribute editor widget that will represent arbitrary text code.
void setText(const QString &text)
Sets the text that will be represented within this widget to text.
QString text() const
The Text that will be represented within this widget.
This class overrides mime type handling to be able to work with the drag and drop attribute editor.
void setType(QgsAttributesDnDTree::Type value)
QTreeWidgetItem * addItem(QTreeWidgetItem *parent, QgsAttributesFormProperties::DnDTreeItemData data, int index=-1, const QIcon &icon=QIcon())
Adds a new item to a parent.
void dropEvent(QDropEvent *event) override
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QTreeWidgetItem * addContainer(QTreeWidgetItem *parent, const QString &title, int columnCount, Qgis::AttributeEditorContainerType type)
Adds a new container to parent.
QStringList mimeTypes() const override
QgsAttributesDnDTree(QgsVectorLayer *layer, QWidget *parent=nullptr)
QMimeData * mimeData(const QList< QTreeWidgetItem * > &items) const override
bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action) override
void dragMoveEvent(QDragMoveEvent *event) override
Is called when mouse is moved over attributes tree before a drop event.
void selectFirstMatchingItem(const QgsAttributesFormProperties::DnDTreeItemData &data)
A HTML editor based on QScintilla2.
A text editor based on QScintilla2.
void insertText(const QString &text)
Insert text at cursor position, or replace any selected text if user has made a selection.
The QgsDefaultValue class provides a container for managing client side default values for fields.
A generic dialog for building expression strings.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Stores information about constraints which may be present on a field.
@ 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.
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().
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
Encapsulate a field in an attribute table or data source.
Qgis::FieldDomainSplitPolicy splitPolicy() const
Returns the field's split policy, which indicates how field values should be handled during a split o...
Qgis::FieldDuplicatePolicy duplicatePolicy() const
Returns the field's duplicate policy, which indicates how field values should be handled during a dup...
QgsFieldConstraints constraints
Container of fields for a vector layer.
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
QIcon iconForField(int fieldIdx, bool considerOrigin=false) const
Returns an icon corresponding to a field index, based on the field's type and source.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
An expression with an additional enabled flag.
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
int count() const
Returns the number of properties contained within the collection.
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
static const QgsSettingsEntryBool * settingsDigitizingDisableEnterAttributeValuesDialog
Settings entry digitizing disable enter attribute values dialog.
This class is a composition of two QSettings instances:
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.
Wraps a label widget to display text.
void setText(const QString &text)
Sets the text code to htmlCode.
void reinitWidget()
Clears the content and makes new initialization.
void setFeature(const QgsFeature &feature) override
Represents a vector layer which manages a vector based data sets.
QgsDefaultValue defaultValueDefinition(int index) const
Returns the definition of the expression used when calculating the default value for a field.
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field 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.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
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.
#define QgsDebugError(str)
The TabStyle struct defines color and font overrides for form fields, tabs and groups labels.