21#include "moc_qgsattributesformproperties.cpp"
22#include "qgsattributetypedialog.h"
23#include "qgsattributeformcontaineredit.h"
24#include "qgsattributewidgetedit.h"
61 QGridLayout *availableWidgetsWidgetLayout =
new QGridLayout;
64 availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
65 mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout );
71 QGridLayout *formLayoutWidgetLayout =
new QGridLayout;
73 mFormLayoutWidget->setLayout( formLayoutWidgetLayout );
75 formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
76 mFormLayoutTree->setHeaderLabels( QStringList() << tr(
"Form Layout" ) );
79 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
80 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
81 connect( mAddTabOrGroupButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::addContainer );
82 connect( mRemoveTabOrGroupButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::removeTabOrGroupButton );
83 connect( mInvertSelectionButton, &QAbstractButton::clicked,
this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked );
84 connect( mEditorLayoutComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged );
85 connect( pbnSelectEditForm, &QToolButton::clicked,
this, &QgsAttributesFormProperties::pbnSelectEditForm_clicked );
86 connect( mTbInitCode, &QPushButton::clicked,
this, &QgsAttributesFormProperties::mTbInitCode_clicked );
119 for (
int i = 0; i < fields.
size(); ++i )
133 if ( !field.
alias().isEmpty() )
134 tooltip = tr(
"%1 (%2)" ).arg( field.
name(), field.
alias() );
136 tooltip = field.
name();
137 item->setToolTip( 0, tooltip );
139 catitem->setExpanded(
true );
154 catitem->setExpanded(
true );
162 for (
const auto &action : std::as_const( actions ) )
164 if ( action.isValid() && action.runable() &&
165 ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) ||
166 action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
168 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
195 catitem ->setExpanded(
true );
203 mFormLayoutTree->setSelectionBehavior( QAbstractItemView::SelectRows );
204 mFormLayoutTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
241 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( QVariant::fromValue(
mLayer->
editFormConfig().
layout() ) ) );
243 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
246 mEditFormLineEdit->setText( cfg.
uiForm() );
258 if ( mInitCode.isEmpty() )
260 mInitCode.append( tr(
"# -*- coding: utf-8 -*-\n\"\"\"\n"
261 "QGIS forms can have a Python function that is called when the form is\n"
264 "Use this function to add extra logic to your forms.\n"
266 "Enter the name of the function in the \"Python Init function\"\n"
268 "An example follows:\n"
270 "from qgis.PyQt.QtWidgets import QWidget\n\n"
271 "def my_form_open(dialog, layer, feature):\n"
272 " geom = feature.geometry()\n"
273 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n" ) );
277void QgsAttributesFormProperties::loadAttributeTypeDialog()
284 const FieldConfig cfg = item->data( 0,
FieldConfigRole ).value<FieldConfig>();
285 const QString fieldName = item->data( 0,
FieldNameRole ).toString();
327 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
333void QgsAttributesFormProperties::storeAttributeTypeDialog()
385 cfg.mFieldConstraints = constraints;
398 QTreeWidgetItem *item = *itemIt;
399 if ( item->data( 0,
FieldNameRole ).toString() == fieldName )
400 item->setData( 0,
FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
404void QgsAttributesFormProperties::storeAttributeWidgetEdit()
412void QgsAttributesFormProperties::loadAttributeWidgetEdit()
417 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
419 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
423void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
426 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
430void QgsAttributesFormProperties::storeAttributeContainerEdit()
438void QgsAttributesFormProperties::loadAttributeContainerEdit()
443 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
447 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
454 auto setCommonProperties = [widgetDef]( DnDTreeItemData & itemData )
456 itemData.setShowLabel( widgetDef->
showLabel() );
457 itemData.setLabelStyle( widgetDef->
labelStyle() );
462 QTreeWidgetItem *newWidget =
nullptr;
463 switch ( widgetDef->
type() )
468 setCommonProperties( itemData );
469 newWidget = tree->
addItem( parent, itemData );
477 if ( action.isValid() )
479 DnDTreeItemData itemData = DnDTreeItemData(
DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
480 setCommonProperties( itemData );
481 newWidget = tree->
addItem( parent, itemData );
494 setCommonProperties( itemData );
496 RelationEditorConfiguration relEdConfig;
500 relEdConfig.nmRelationId = relationEditor->
nmRelationId();
502 relEdConfig.label = relationEditor->
label();
503 itemData.setRelationEditorConfiguration( relEdConfig );
504 newWidget = tree->
addItem( parent, itemData );
517 itemData.setContainerType( container->
type() );
521 itemData.setCollapsed( container->
collapsed() );
523 setCommonProperties( itemData );
525 newWidget = tree->
addItem( parent, itemData );
527 const QList<QgsAttributeEditorElement *> children = container->
children();
530 loadAttributeEditorTreeItem( wdg, newWidget, tree );
539 QmlElementEditorConfiguration qmlEdConfig;
540 qmlEdConfig.qmlCode = qmlElementEditor->
qmlCode();
541 itemData.setQmlElementEditorConfiguration( qmlEdConfig );
542 setCommonProperties( itemData );
543 newWidget = tree->
addItem( parent, itemData );
551 HtmlElementEditorConfiguration htmlEdConfig;
552 htmlEdConfig.htmlCode = htmlElementEditor->
htmlCode();
553 itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
554 setCommonProperties( itemData );
555 newWidget = tree->
addItem( parent, itemData );
563 TextElementEditorConfiguration textEdConfig;
564 textEdConfig.text = textElementEditor->
text();
565 itemData.setTextElementEditorConfiguration( textEdConfig );
566 setCommonProperties( itemData );
567 newWidget = tree->
addItem( parent, itemData );
575 SpacerElementEditorConfiguration spacerEdConfig;
576 spacerEdConfig.drawLine = spacerElementEditor->
drawLine();
577 itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
578 setCommonProperties( itemData );
579 itemData.setShowLabel(
false );
580 newWidget = tree->
addItem( parent, itemData );
586 QgsDebugError( QStringLiteral(
"Not loading invalid attribute editor type..." ) );
592 newWidget->setExpanded(
true );
598void QgsAttributesFormProperties::onAttributeSelectionChanged()
600 disconnect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
602 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
605void QgsAttributesFormProperties::onFormLayoutSelectionChanged()
608 disconnect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
610 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
618 storeAttributeWidgetEdit();
620 clearAttributeTypeFrame();
622 if ( emitter->selectedItems().count() != 1 )
624 receiver->clearSelection();
628 const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
629 switch ( itemData.type() )
636 loadAttributeWidgetEdit();
640 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
648 loadAttributeWidgetEdit();
649 loadAttributeTypeDialog();
654 receiver->clearSelection();
655 loadAttributeContainerEdit();
662 loadInfoWidget( action.html() );
672 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
676 loadInfoWidget( tr(
"This configuration is available with double-click" ) );
678 receiver->clearSelection();
683 receiver->clearSelection();
690void QgsAttributesFormProperties::clearAttributeTypeFrame()
718void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
723 for (
int i = 0; i < rootItem->childCount(); ++i )
725 rootItem->child( i )->setSelected( ! selectedItemList.contains( rootItem->child( i ) ) );
729void QgsAttributesFormProperties::addContainer()
731 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList;
735 const DnDTreeItemData itemData = ( *it )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
741 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().value( 0 );
744 if ( !dialog.exec() )
747 const QString name = dialog.name();
748 QTreeWidgetItem *parentContainerItem = dialog.parentContainerItem();
751 dialog.columnCount(),
752 dialog.containerType() );
755void QgsAttributesFormProperties::removeTabOrGroupButton()
761 const QList<QTreeWidgetItem *> items =
mFormLayoutTree->selectedItems();
765 delete items.at( 0 );
776 switch ( itemData.
type() )
824 for (
int t = 0; t < item->childCount(); t++ )
831 widgetDef = container;
883void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
889 mFormLayoutWidget->setVisible(
false );
890 mUiFileFrame->setVisible(
false );
891 mAddTabOrGroupButton->setVisible(
false );
892 mRemoveTabOrGroupButton->setVisible(
false );
893 mInvertSelectionButton->setVisible(
false );
897 mFormLayoutWidget->setVisible(
true );
898 mUiFileFrame->setVisible(
false );
899 mAddTabOrGroupButton->setVisible(
true );
900 mRemoveTabOrGroupButton->setVisible(
true );
901 mInvertSelectionButton->setVisible(
true );
906 mFormLayoutWidget->setVisible(
false );
907 mUiFileFrame->setVisible(
true );
908 mAddTabOrGroupButton->setVisible(
false );
909 mRemoveTabOrGroupButton->setVisible(
false );
910 mInvertSelectionButton->setVisible(
false );
915void QgsAttributesFormProperties::mTbInitCode_clicked()
924 if ( !attributesFormInitCode.exec() )
927 mInitCodeSource = attributesFormInitCode.
codeSource();
928 mInitCode = attributesFormInitCode.
initCode();
934void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
937 const QString lastUsedDir = myQSettings.
value( QStringLiteral(
"style/lastUIDir" ), QDir::homePath() ).toString();
938 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
940 if ( uifilename.isNull() )
943 const QFileInfo fi( uifilename );
944 myQSettings.
setValue( QStringLiteral(
"style/lastUIDir" ), fi.path() );
945 mEditFormLineEdit->setText( uifilename );
950 storeAttributeWidgetEdit();
951 storeAttributeContainerEdit();
952 storeAttributeTypeDialog();
958 storeAttributeWidgetEdit();
959 storeAttributeContainerEdit();
960 storeAttributeTypeDialog();
966 for (
int i = 0; i < fieldContainer->childCount(); i++ )
968 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
971 const QString fieldName { fieldItem->data( 0,
FieldNameRole ).toString() };
1023 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1025 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1027 if ( editorElement )
1028 editFormConfig.
addTab( editorElement );
1031 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
1045 for (
int i = 0; i < relationContainer->childCount(); i++ )
1047 QTreeWidgetItem *relationItem = relationContainer->child( i );
1050 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1052 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1055 if ( tabItemData.
type() == itemData.
type() && tabItemData.
name() == itemData.
name() )
1092QgsAttributesFormProperties::FieldConfig::operator QVariant()
1094 return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *
this );
1101QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
1103 return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *
this );
1112 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << title );
1113 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1114 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1119 parent->addChild( newItem );
1120 newItem->setExpanded(
true );
1125 : QTreeWidget( parent )
1128 connect(
this, &QTreeWidget::itemDoubleClicked,
this, &QgsAttributesDnDTree::onItemDoubleClicked );
1133 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << data.
name() );
1135 switch ( data.
type() )
1144 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1150 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1151 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1158 newItem->setIcon( 0, icon );
1161 parent->addChild( newItem );
1163 parent->insertChild( index, newItem );
1175 const QMimeData *data =
event->mimeData();
1177 if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1181 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1182 QDataStream stream( &itemData, QIODevice::ReadOnly );
1183 stream >> itemElement;
1186 if ( event->source() ==
this )
1188 event->setDropAction( Qt::MoveAction );
1196 QTreeWidget::dragMoveEvent( event );
1202 bool bDropSuccessful =
false;
1204 if ( action == Qt::IgnoreAction )
1206 bDropSuccessful =
true;
1208 else if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1210 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1211 QDataStream stream( &itemData, QIODevice::ReadOnly );
1214 while ( !stream.atEnd() )
1216 stream >> itemElement;
1218 QTreeWidgetItem *newItem;
1222 newItem =
addItem( parent, itemElement, index++ );
1223 bDropSuccessful =
true;
1227 newItem =
addItem( invisibleRootItem(), itemElement, index++ );
1228 bDropSuccessful =
true;
1233 onItemDoubleClicked( newItem, 0 );
1238 onItemDoubleClicked( newItem, 0 );
1243 onItemDoubleClicked( newItem, 0 );
1248 onItemDoubleClicked( newItem, 0 );
1252 newItem->setSelected(
true );
1256 return bDropSuccessful;
1261 if ( !event->mimeData()->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1264 if ( event->source() ==
this )
1266 event->setDropAction( Qt::MoveAction );
1269 QTreeWidget::dropEvent( event );
1274 return QStringList() << QStringLiteral(
"application/x-qgsattributetabledesignerelement" );
1277#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1283 if ( items.count() <= 0 )
1286 const QStringList types = mimeTypes();
1288 if ( types.isEmpty() )
1291 QMimeData *data =
new QMimeData();
1292 const QString format = types.at( 0 );
1294 QDataStream stream( &encoded, QIODevice::WriteOnly );
1296 const auto constItems = items;
1297 for (
const QTreeWidgetItem *item : constItems )
1307 data->setData( format, encoded );
1312void QgsAttributesDnDTree::onItemDoubleClicked( QTreeWidgetItem *item,
int column )
1318 QGroupBox *baseData =
new QGroupBox( tr(
"Base configuration" ) );
1320 QFormLayout *baseLayout =
new QFormLayout();
1321 baseData->setLayout( baseLayout );
1322 QCheckBox *showLabelCheckbox =
new QCheckBox( QStringLiteral(
"Show label" ) );
1323 showLabelCheckbox->setChecked( itemData.
showLabel() );
1324 baseLayout->addRow( showLabelCheckbox );
1325 QWidget *baseWidget =
new QWidget();
1326 baseWidget->setLayout( baseLayout );
1328 switch ( itemData.
type() )
1343 dlg.setWindowTitle( tr(
"Configure QML Widget" ) );
1345 QVBoxLayout *mainLayout =
new QVBoxLayout();
1346 QHBoxLayout *qmlLayout =
new QHBoxLayout();
1347 QVBoxLayout *layout =
new QVBoxLayout();
1348 mainLayout->addLayout( qmlLayout );
1349 qmlLayout->addLayout( layout );
1350 dlg.setLayout( mainLayout );
1351 layout->addWidget( baseWidget );
1353 QLineEdit *title =
new QLineEdit( itemData.
name() );
1364 connect( qmlCode, &QsciScintilla::textChanged,
this, [ = ]
1372 QComboBox *qmlObjectTemplate =
new QComboBox();
1373 qmlObjectTemplate->addItem( tr(
"Free Text…" ) );
1374 qmlObjectTemplate->addItem( tr(
"Rectangle" ) );
1375 qmlObjectTemplate->addItem( tr(
"Pie Chart" ) );
1376 qmlObjectTemplate->addItem( tr(
"Bar Chart" ) );
1377 connect( qmlObjectTemplate, qOverload<int>( &QComboBox::activated ), qmlCode, [ = ](
int index )
1384 qmlCode->setText( QString() );
1389 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1394 " color: \"steelblue\"\n"
1395 " Text{ text: \"A rectangle\" }\n"
1401 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1402 "import QtCharts 2.0\n"
1410 " PieSlice { label: \"First slice\"; value: 25 }\n"
1411 " PieSlice { label: \"Second slice\"; value: 45 }\n"
1412 " PieSlice { label: \"Third slice\"; value: 30 }\n"
1419 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1420 "import QtCharts 2.0\n"
1423 " title: \"Bar series\"\n"
1426 " legend.alignment: Qt.AlignBottom\n"
1427 " antialiasing: true\n"
1436 " axisY: valueAxisY\n"
1437 " axisX: BarCategoryAxis { categories: [\"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\" ] }\n"
1438 " BarSet { label: \"Bob\"; values: [2, 2, 3, 4, 5, 6] }\n"
1439 " BarSet { label: \"Susan\"; values: [5, 1, 2, 4, 1, 7] }\n"
1440 " BarSet { label: \"James\"; values: [3, 5, 8, 13, 5, 8] }\n"
1452 expressionWidget->registerExpressionContextGenerator(
this );
1453 expressionWidget->setLayer( mLayer );
1454 QToolButton *addFieldButton =
new QToolButton();
1457 QToolButton *editExpressionButton =
new QToolButton();
1459 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1461 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1463 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1464 if ( !expression.isEmpty() )
1465 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1468 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1471 expression.replace( QLatin1String(
"\\\"" ), QLatin1String(
"\"" ) );
1475 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1476 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1478 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1479 if ( !expression.isEmpty() )
1480 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1484 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1485 layout->addWidget( title );
1486 QGroupBox *qmlCodeBox =
new QGroupBox( tr(
"QML Code" ) );
1487 qmlCodeBox->setLayout(
new QVBoxLayout );
1488 qmlCodeBox->layout()->addWidget( qmlObjectTemplate );
1489 QWidget *expressionWidgetBox =
new QWidget();
1490 qmlCodeBox->layout()->addWidget( expressionWidgetBox );
1491 expressionWidgetBox->setLayout(
new QHBoxLayout );
1492 expressionWidgetBox->layout()->setContentsMargins( 0, 0, 0, 0 );
1493 expressionWidgetBox->layout()->addWidget( expressionWidget );
1494 expressionWidgetBox->layout()->addWidget( addFieldButton );
1495 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1496 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1497 layout->addWidget( qmlCodeBox );
1498 layout->addWidget( qmlCode );
1500 qmlPreviewBox->setLayout(
new QGridLayout );
1501 qmlPreviewBox->setMinimumWidth( 400 );
1502 qmlPreviewBox->layout()->addWidget( qmlWrapper->
widget() );
1504 emit qmlCode->textChanged();
1505 qmlLayout->addWidget( qmlPreviewBox );
1507 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1509 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1510 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1512 mainLayout->addWidget( buttonBox );
1517 qmlEdCfg.
qmlCode = qmlCode->text();
1518 itemData.
setName( title->text() );
1520 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1523 item->setText( 0, title->text() );
1533 dlg.setWindowTitle( tr(
"Configure HTML Widget" ) );
1535 QVBoxLayout *mainLayout =
new QVBoxLayout();
1536 QHBoxLayout *htmlLayout =
new QHBoxLayout();
1537 QVBoxLayout *layout =
new QVBoxLayout();
1538 mainLayout->addLayout( htmlLayout );
1539 htmlLayout->addLayout( layout );
1540 dlg.setLayout( mainLayout );
1541 layout->addWidget( baseWidget );
1543 QLineEdit *title =
new QLineEdit( itemData.
name() );
1547 htmlCode->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1555 connect( htmlCode, &QgsCodeEditorHTML::textChanged,
this, [ = ]
1564 expressionWidget->registerExpressionContextGenerator(
this );
1565 expressionWidget->setLayer( mLayer );
1566 QToolButton *addFieldButton =
new QToolButton();
1569 QToolButton *editExpressionButton =
new QToolButton();
1571 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1573 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1575 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1576 if ( !expression.isEmpty() )
1577 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1580 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1583 expression.replace( QLatin1String(
"\\\"" ), QLatin1String(
"\"" ) );
1587 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1588 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1590 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1591 if ( !expression.isEmpty() )
1592 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1596 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1597 layout->addWidget( title );
1598 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"HTML Code" ) );
1599 layout->addWidget( expressionWidgetBox );
1600 expressionWidgetBox->setLayout(
new QHBoxLayout );
1601 expressionWidgetBox->layout()->addWidget( expressionWidget );
1602 expressionWidgetBox->layout()->addWidget( addFieldButton );
1603 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1604 layout->addWidget( htmlCode );
1606 htmlPreviewBox->setLayout(
new QGridLayout );
1607 htmlPreviewBox->setMinimumWidth( 400 );
1608 htmlPreviewBox->layout()->addWidget( htmlWrapper->
widget() );
1610 emit htmlCode->textChanged();
1611 htmlLayout->addWidget( htmlPreviewBox );
1613 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1615 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1616 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1618 mainLayout->addWidget( buttonBox );
1623 htmlEdCfg.
htmlCode = htmlCode->text();
1624 itemData.
setName( title->text() );
1626 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1629 item->setText( 0, title->text() );
1639 dlg.setWindowTitle( tr(
"Configure Text Widget" ) );
1641 QVBoxLayout *mainLayout =
new QVBoxLayout();
1642 QHBoxLayout *textLayout =
new QHBoxLayout();
1643 QVBoxLayout *layout =
new QVBoxLayout();
1644 mainLayout->addLayout( textLayout );
1645 textLayout->addLayout( layout );
1646 dlg.setLayout( mainLayout );
1647 layout->addWidget( baseWidget );
1649 QLineEdit *title =
new QLineEdit( itemData.
name() );
1652 text->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1660 connect( text, &QgsCodeEditorExpression::textChanged,
this, [ = ]
1662 textWrapper->
setText( text->text( ) );
1669 expressionWidget->registerExpressionContextGenerator(
this );
1670 expressionWidget->setLayer( mLayer );
1671 QToolButton *addFieldButton =
new QToolButton();
1674 QToolButton *editExpressionButton =
new QToolButton();
1676 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1678 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1680 QString expression = expressionWidget->expression().trimmed();
1681 if ( !expression.isEmpty() )
1682 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1684 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1691 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1692 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1694 QString expression = exprDlg.expressionText().trimmed();
1695 if ( !expression.isEmpty() )
1696 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1700 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1701 layout->addWidget( title );
1702 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"Text" ) );
1703 layout->addWidget( expressionWidgetBox );
1704 expressionWidgetBox->setLayout(
new QHBoxLayout );
1705 expressionWidgetBox->layout()->addWidget( expressionWidget );
1706 expressionWidgetBox->layout()->addWidget( addFieldButton );
1707 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1708 layout->addWidget( text );
1710 textPreviewBox->setLayout(
new QGridLayout );
1711 textPreviewBox->setMinimumWidth( 400 );
1712 textPreviewBox->layout()->addWidget( textWrapper->
widget() );
1714 emit text->textChanged();
1715 textLayout->addWidget( textPreviewBox );
1717 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1719 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1720 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1722 mainLayout->addWidget( buttonBox );
1727 textEdCfg.
text = text->text();
1728 itemData.
setName( title->text() );
1730 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1733 item->setText( 0, title->text() );
1743 dlg.setWindowTitle( tr(
"Configure Spacer Widget" ) );
1745 QVBoxLayout *mainLayout =
new QVBoxLayout();
1746 mainLayout->addWidget(
new QLabel( tr(
"Title" ) ) );
1747 QLineEdit *title =
new QLineEdit( itemData.
name() );
1748 mainLayout->addWidget( title );
1750 QHBoxLayout *cbLayout =
new QHBoxLayout( );
1751 mainLayout->addLayout( cbLayout );
1752 dlg.setLayout( mainLayout );
1753 QCheckBox *cb =
new QCheckBox { &dlg };
1755 cbLayout->addWidget(
new QLabel( tr(
"Draw horizontal line" ), &dlg ) );
1756 cbLayout->addWidget( cb );
1759 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1761 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1762 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1764 mainLayout->addWidget( buttonBox );
1769 spacerEdCfg.
drawLine = cb->isChecked();
1772 itemData.
setName( title->text() );
1774 item->setText( 0, title->text() );
1807 QTreeWidgetItemIterator it(
this );
1813 if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
1820 ( *it )->setSelected(
true );
1843 QString displayName;
1846 stream >> type >> name >> displayName;
1857 return mContainerType;
1862 mContainerType = type;
1872 mLabelStyle = labelStyle;
1882 mShowLabel = showLabel;
1887 return mVisibilityExpression;
1892 mVisibilityExpression = visibilityExpression;
1897 return mCollapsedExpression;
1902 mCollapsedExpression = collapsedExpression;
1907 return mRelationEditorConfiguration;
1912 mRelationEditorConfiguration = relationEditorConfiguration;
1917 return mQmlElementEditorConfiguration;
1922 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
1928 return mHtmlElementEditorConfiguration;
1933 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
1938 return mSpacerElementEditorConfiguration;
1943 mSpacerElementEditorConfiguration = spacerElementEditorConfiguration;
1948 return mBackgroundColor;
1953 mBackgroundColor = backgroundColor;
1958 return mTextElementEditorConfiguration;
1963 mTextElementEditorConfiguration = textElementEditorConfiguration;
1966void QgsAttributesFormProperties::updatedFields()
1969 QMap<QString, FieldConfig> fieldConfigs;
1971 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1973 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1974 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1976 fieldConfigs[fieldName] = cfg;
1982 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1984 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1985 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1986 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.