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 );
112 for (
int i = 0; i < fields.
size(); ++i )
126 if ( !field.
alias().isEmpty() )
127 tooltip = tr(
"%1 (%2)" ).arg( field.
name(), field.
alias() );
129 tooltip = field.
name();
130 item->setToolTip( 0, tooltip );
132 catitem->setExpanded(
true );
147 catitem->setExpanded(
true );
155 for (
const auto &action : std::as_const( actions ) )
157 if ( action.isValid() && action.runable() &&
158 ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) ||
159 action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
161 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
188 catitem ->setExpanded(
true );
196 mFormLayoutTree->setSelectionBehavior( QAbstractItemView::SelectRows );
197 mFormLayoutTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
234 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( QVariant::fromValue(
mLayer->
editFormConfig().
layout() ) ) );
236 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
239 mEditFormLineEdit->setText( cfg.
uiForm() );
251 if ( mInitCode.isEmpty() )
253 mInitCode.append( tr(
"# -*- coding: utf-8 -*-\n\"\"\"\n"
254 "QGIS forms can have a Python function that is called when the form is\n"
257 "Use this function to add extra logic to your forms.\n"
259 "Enter the name of the function in the \"Python Init function\"\n"
261 "An example follows:\n"
263 "from qgis.PyQt.QtWidgets import QWidget\n\n"
264 "def my_form_open(dialog, layer, feature):\n"
265 " geom = feature.geometry()\n"
266 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n" ) );
270void QgsAttributesFormProperties::loadAttributeTypeDialog()
277 const FieldConfig cfg = item->data( 0,
FieldConfigRole ).value<FieldConfig>();
278 const QString fieldName = item->data( 0,
FieldNameRole ).toString();
300 QgsFieldConstraints::Constraints providerConstraints = QgsFieldConstraints::Constraints();
319 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
325void QgsAttributesFormProperties::storeAttributeTypeDialog()
375 cfg.mFieldConstraints = constraints;
388 QTreeWidgetItem *item = *itemIt;
389 if ( item->data( 0,
FieldNameRole ).toString() == fieldName )
390 item->setData( 0,
FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
394void QgsAttributesFormProperties::storeAttributeWidgetEdit()
402void QgsAttributesFormProperties::loadAttributeWidgetEdit()
407 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
409 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
413void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
416 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
420void QgsAttributesFormProperties::storeAttributeContainerEdit()
428void QgsAttributesFormProperties::loadAttributeContainerEdit()
433 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
437 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
444 auto setCommonProperties = [widgetDef]( DnDTreeItemData & itemData )
446 itemData.setShowLabel( widgetDef->
showLabel() );
447 itemData.setLabelStyle( widgetDef->
labelStyle() );
452 QTreeWidgetItem *newWidget =
nullptr;
453 switch ( widgetDef->
type() )
458 setCommonProperties( itemData );
459 newWidget = tree->
addItem( parent, itemData );
467 if ( action.isValid() )
469 DnDTreeItemData itemData = DnDTreeItemData(
DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
470 setCommonProperties( itemData );
471 newWidget = tree->
addItem( parent, itemData );
484 setCommonProperties( itemData );
486 RelationEditorConfiguration relEdConfig;
490 relEdConfig.nmRelationId = relationEditor->
nmRelationId();
492 relEdConfig.label = relationEditor->
label();
493 itemData.setRelationEditorConfiguration( relEdConfig );
494 newWidget = tree->
addItem( parent, itemData );
507 itemData.setContainerType( container->
type() );
511 itemData.setCollapsed( container->
collapsed() );
513 setCommonProperties( itemData );
515 newWidget = tree->
addItem( parent, itemData );
517 const QList<QgsAttributeEditorElement *> children = container->
children();
520 loadAttributeEditorTreeItem( wdg, newWidget, tree );
529 QmlElementEditorConfiguration qmlEdConfig;
530 qmlEdConfig.qmlCode = qmlElementEditor->
qmlCode();
531 itemData.setQmlElementEditorConfiguration( qmlEdConfig );
532 setCommonProperties( itemData );
533 newWidget = tree->
addItem( parent, itemData );
541 HtmlElementEditorConfiguration htmlEdConfig;
542 htmlEdConfig.htmlCode = htmlElementEditor->
htmlCode();
543 itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
544 setCommonProperties( itemData );
545 newWidget = tree->
addItem( parent, itemData );
553 TextElementEditorConfiguration textEdConfig;
554 textEdConfig.text = textElementEditor->
text();
555 itemData.setTextElementEditorConfiguration( textEdConfig );
556 setCommonProperties( itemData );
557 newWidget = tree->
addItem( parent, itemData );
565 SpacerElementEditorConfiguration spacerEdConfig;
566 spacerEdConfig.drawLine = spacerElementEditor->
drawLine();
567 itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
568 setCommonProperties( itemData );
569 itemData.setShowLabel(
false );
570 newWidget = tree->
addItem( parent, itemData );
576 QgsDebugError( QStringLiteral(
"Not loading invalid attribute editor type..." ) );
582 newWidget->setExpanded(
true );
588void QgsAttributesFormProperties::onAttributeSelectionChanged()
590 disconnect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
592 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
595void QgsAttributesFormProperties::onFormLayoutSelectionChanged()
598 disconnect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
600 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
608 storeAttributeWidgetEdit();
609 storeAttributeTypeDialog();
610 storeAttributeContainerEdit();
612 clearAttributeTypeFrame();
614 if ( emitter->selectedItems().count() != 1 )
616 receiver->clearSelection();
620 const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
621 switch ( itemData.type() )
628 loadAttributeWidgetEdit();
632 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
640 loadAttributeWidgetEdit();
641 loadAttributeTypeDialog();
646 receiver->clearSelection();
647 loadAttributeContainerEdit();
654 loadInfoWidget( action.html() );
664 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
668 loadInfoWidget( tr(
"This configuration is available with double-click" ) );
670 receiver->clearSelection();
675 receiver->clearSelection();
682void QgsAttributesFormProperties::clearAttributeTypeFrame()
710void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
715 for (
int i = 0; i < rootItem->childCount(); ++i )
717 rootItem->child( i )->setSelected( ! selectedItemList.contains( rootItem->child( i ) ) );
721void QgsAttributesFormProperties::addContainer()
723 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList;
727 const DnDTreeItemData itemData = ( *it )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
733 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().value( 0 );
736 if ( !dialog.exec() )
739 const QString name = dialog.name();
740 QTreeWidgetItem *parentContainerItem = dialog.parentContainerItem();
743 dialog.columnCount(),
744 dialog.containerType() );
747void QgsAttributesFormProperties::removeTabOrGroupButton()
753 const QList<QTreeWidgetItem *> items =
mFormLayoutTree->selectedItems();
757 delete items.at( 0 );
768 switch ( itemData.
type() )
816 for (
int t = 0; t < item->childCount(); t++ )
823 widgetDef = container;
875void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
881 mFormLayoutWidget->setVisible(
false );
882 mUiFileFrame->setVisible(
false );
883 mAddTabOrGroupButton->setVisible(
false );
884 mRemoveTabOrGroupButton->setVisible(
false );
885 mInvertSelectionButton->setVisible(
false );
889 mFormLayoutWidget->setVisible(
true );
890 mUiFileFrame->setVisible(
false );
891 mAddTabOrGroupButton->setVisible(
true );
892 mRemoveTabOrGroupButton->setVisible(
true );
893 mInvertSelectionButton->setVisible(
true );
898 mFormLayoutWidget->setVisible(
false );
899 mUiFileFrame->setVisible(
true );
900 mAddTabOrGroupButton->setVisible(
false );
901 mRemoveTabOrGroupButton->setVisible(
false );
902 mInvertSelectionButton->setVisible(
false );
907void QgsAttributesFormProperties::mTbInitCode_clicked()
916 if ( !attributesFormInitCode.exec() )
919 mInitCodeSource = attributesFormInitCode.
codeSource();
920 mInitCode = attributesFormInitCode.
initCode();
926void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
929 const QString lastUsedDir = myQSettings.
value( QStringLiteral(
"style/lastUIDir" ), QDir::homePath() ).toString();
930 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
932 if ( uifilename.isNull() )
935 const QFileInfo fi( uifilename );
936 myQSettings.
setValue( QStringLiteral(
"style/lastUIDir" ), fi.path() );
937 mEditFormLineEdit->setText( uifilename );
942 storeAttributeWidgetEdit();
943 storeAttributeContainerEdit();
944 storeAttributeTypeDialog();
950 for (
int i = 0; i < fieldContainer->childCount(); i++ )
952 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
955 const QString fieldName { fieldItem->data( 0,
FieldNameRole ).toString() };
1006 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1008 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1010 if ( editorElement )
1011 editFormConfig.
addTab( editorElement );
1014 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
1028 for (
int i = 0; i < relationContainer->childCount(); i++ )
1030 QTreeWidgetItem *relationItem = relationContainer->child( i );
1033 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1035 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1038 if ( tabItemData.
type() == itemData.
type() && tabItemData.
name() == itemData.
name() )
1075QgsAttributesFormProperties::FieldConfig::operator QVariant()
1077 return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *
this );
1084QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
1086 return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *
this );
1095 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << title );
1096 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1097 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1102 parent->addChild( newItem );
1103 newItem->setExpanded(
true );
1108 : QTreeWidget( parent )
1111 connect(
this, &QTreeWidget::itemDoubleClicked,
this, &QgsAttributesDnDTree::onItemDoubleClicked );
1116 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << data.
name() );
1118 switch ( data.
type() )
1127 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1133 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1134 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1141 newItem->setIcon( 0, icon );
1144 parent->addChild( newItem );
1146 parent->insertChild( index, newItem );
1158 const QMimeData *data =
event->mimeData();
1160 if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1164 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1165 QDataStream stream( &itemData, QIODevice::ReadOnly );
1166 stream >> itemElement;
1169 if ( event->source() ==
this )
1171 event->setDropAction( Qt::MoveAction );
1179 QTreeWidget::dragMoveEvent( event );
1185 bool bDropSuccessful =
false;
1187 if ( action == Qt::IgnoreAction )
1189 bDropSuccessful =
true;
1191 else if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1193 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1194 QDataStream stream( &itemData, QIODevice::ReadOnly );
1197 while ( !stream.atEnd() )
1199 stream >> itemElement;
1201 QTreeWidgetItem *newItem;
1205 newItem =
addItem( parent, itemElement, index++ );
1206 bDropSuccessful =
true;
1210 newItem =
addItem( invisibleRootItem(), itemElement, index++ );
1211 bDropSuccessful =
true;
1216 onItemDoubleClicked( newItem, 0 );
1221 onItemDoubleClicked( newItem, 0 );
1226 onItemDoubleClicked( newItem, 0 );
1231 onItemDoubleClicked( newItem, 0 );
1235 newItem->setSelected(
true );
1239 return bDropSuccessful;
1244 if ( !event->mimeData()->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1247 if ( event->source() ==
this )
1249 event->setDropAction( Qt::MoveAction );
1252 QTreeWidget::dropEvent( event );
1257 return QStringList() << QStringLiteral(
"application/x-qgsattributetabledesignerelement" );
1260#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1266 if ( items.count() <= 0 )
1269 const QStringList types = mimeTypes();
1271 if ( types.isEmpty() )
1274 QMimeData *data =
new QMimeData();
1275 const QString format = types.at( 0 );
1277 QDataStream stream( &encoded, QIODevice::WriteOnly );
1279 const auto constItems = items;
1280 for (
const QTreeWidgetItem *item : constItems )
1290 data->setData( format, encoded );
1295void QgsAttributesDnDTree::onItemDoubleClicked( QTreeWidgetItem *item,
int column )
1301 QGroupBox *baseData =
new QGroupBox( tr(
"Base configuration" ) );
1303 QFormLayout *baseLayout =
new QFormLayout();
1304 baseData->setLayout( baseLayout );
1305 QCheckBox *showLabelCheckbox =
new QCheckBox( QStringLiteral(
"Show label" ) );
1306 showLabelCheckbox->setChecked( itemData.
showLabel() );
1307 baseLayout->addRow( showLabelCheckbox );
1308 QWidget *baseWidget =
new QWidget();
1309 baseWidget->setLayout( baseLayout );
1311 switch ( itemData.
type() )
1326 dlg.setWindowTitle( tr(
"Configure QML Widget" ) );
1328 QVBoxLayout *mainLayout =
new QVBoxLayout();
1329 QHBoxLayout *qmlLayout =
new QHBoxLayout();
1330 QVBoxLayout *layout =
new QVBoxLayout();
1331 mainLayout->addLayout( qmlLayout );
1332 qmlLayout->addLayout( layout );
1333 dlg.setLayout( mainLayout );
1334 layout->addWidget( baseWidget );
1336 QLineEdit *title =
new QLineEdit( itemData.
name() );
1347 connect( qmlCode, &QsciScintilla::textChanged,
this, [ = ]
1355 QComboBox *qmlObjectTemplate =
new QComboBox();
1356 qmlObjectTemplate->addItem( tr(
"Free Text…" ) );
1357 qmlObjectTemplate->addItem( tr(
"Rectangle" ) );
1358 qmlObjectTemplate->addItem( tr(
"Pie Chart" ) );
1359 qmlObjectTemplate->addItem( tr(
"Bar Chart" ) );
1360 connect( qmlObjectTemplate, qOverload<int>( &QComboBox::activated ), qmlCode, [ = ](
int index )
1367 qmlCode->setText( QString() );
1372 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1377 " color: \"steelblue\"\n"
1378 " Text{ text: \"A rectangle\" }\n"
1384 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1385 "import QtCharts 2.0\n"
1393 " PieSlice { label: \"First slice\"; value: 25 }\n"
1394 " PieSlice { label: \"Second slice\"; value: 45 }\n"
1395 " PieSlice { label: \"Third slice\"; value: 30 }\n"
1402 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1403 "import QtCharts 2.0\n"
1406 " title: \"Bar series\"\n"
1409 " legend.alignment: Qt.AlignBottom\n"
1410 " antialiasing: true\n"
1419 " axisY: valueAxisY\n"
1420 " axisX: BarCategoryAxis { categories: [\"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\" ] }\n"
1421 " BarSet { label: \"Bob\"; values: [2, 2, 3, 4, 5, 6] }\n"
1422 " BarSet { label: \"Susan\"; values: [5, 1, 2, 4, 1, 7] }\n"
1423 " BarSet { label: \"James\"; values: [3, 5, 8, 13, 5, 8] }\n"
1435 expressionWidget->registerExpressionContextGenerator(
this );
1436 expressionWidget->setLayer( mLayer );
1437 QToolButton *addFieldButton =
new QToolButton();
1440 QToolButton *editExpressionButton =
new QToolButton();
1442 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1444 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1446 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1447 if ( !expression.isEmpty() )
1448 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1451 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1454 expression.replace( QStringLiteral(
"\\\"" ), QStringLiteral(
"\"" ) );
1458 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1459 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1461 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1462 if ( !expression.isEmpty() )
1463 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1467 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1468 layout->addWidget( title );
1469 QGroupBox *qmlCodeBox =
new QGroupBox( tr(
"QML Code" ) );
1470 qmlCodeBox->setLayout(
new QVBoxLayout );
1471 qmlCodeBox->layout()->addWidget( qmlObjectTemplate );
1472 QWidget *expressionWidgetBox =
new QWidget();
1473 qmlCodeBox->layout()->addWidget( expressionWidgetBox );
1474 expressionWidgetBox->setLayout(
new QHBoxLayout );
1475 expressionWidgetBox->layout()->setContentsMargins( 0, 0, 0, 0 );
1476 expressionWidgetBox->layout()->addWidget( expressionWidget );
1477 expressionWidgetBox->layout()->addWidget( addFieldButton );
1478 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1479 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1480 layout->addWidget( qmlCodeBox );
1481 layout->addWidget( qmlCode );
1483 qmlPreviewBox->setLayout(
new QGridLayout );
1484 qmlPreviewBox->setMinimumWidth( 400 );
1485 qmlPreviewBox->layout()->addWidget( qmlWrapper->
widget() );
1487 emit qmlCode->textChanged();
1488 qmlLayout->addWidget( qmlPreviewBox );
1490 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1492 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1493 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1495 mainLayout->addWidget( buttonBox );
1500 qmlEdCfg.
qmlCode = qmlCode->text();
1501 itemData.
setName( title->text() );
1503 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1506 item->setText( 0, title->text() );
1516 dlg.setWindowTitle( tr(
"Configure HTML Widget" ) );
1518 QVBoxLayout *mainLayout =
new QVBoxLayout();
1519 QHBoxLayout *htmlLayout =
new QHBoxLayout();
1520 QVBoxLayout *layout =
new QVBoxLayout();
1521 mainLayout->addLayout( htmlLayout );
1522 htmlLayout->addLayout( layout );
1523 dlg.setLayout( mainLayout );
1524 layout->addWidget( baseWidget );
1526 QLineEdit *title =
new QLineEdit( itemData.
name() );
1530 htmlCode->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1538 connect( htmlCode, &QgsCodeEditorHTML::textChanged,
this, [ = ]
1547 expressionWidget->registerExpressionContextGenerator(
this );
1548 expressionWidget->setLayer( mLayer );
1549 QToolButton *addFieldButton =
new QToolButton();
1552 QToolButton *editExpressionButton =
new QToolButton();
1554 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1556 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1558 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1559 if ( !expression.isEmpty() )
1560 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1563 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1566 expression.replace( QStringLiteral(
"\\\"" ), QStringLiteral(
"\"" ) );
1570 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1571 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1573 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1574 if ( !expression.isEmpty() )
1575 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1579 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1580 layout->addWidget( title );
1581 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"HTML Code" ) );
1582 layout->addWidget( expressionWidgetBox );
1583 expressionWidgetBox->setLayout(
new QHBoxLayout );
1584 expressionWidgetBox->layout()->addWidget( expressionWidget );
1585 expressionWidgetBox->layout()->addWidget( addFieldButton );
1586 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1587 layout->addWidget( htmlCode );
1589 htmlPreviewBox->setLayout(
new QGridLayout );
1590 htmlPreviewBox->setMinimumWidth( 400 );
1591 htmlPreviewBox->layout()->addWidget( htmlWrapper->
widget() );
1593 emit htmlCode->textChanged();
1594 htmlLayout->addWidget( htmlPreviewBox );
1596 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1598 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1599 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1601 mainLayout->addWidget( buttonBox );
1606 htmlEdCfg.
htmlCode = htmlCode->text();
1607 itemData.
setName( title->text() );
1609 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1612 item->setText( 0, title->text() );
1622 dlg.setWindowTitle( tr(
"Configure Text Widget" ) );
1624 QVBoxLayout *mainLayout =
new QVBoxLayout();
1625 QHBoxLayout *textLayout =
new QHBoxLayout();
1626 QVBoxLayout *layout =
new QVBoxLayout();
1627 mainLayout->addLayout( textLayout );
1628 textLayout->addLayout( layout );
1629 dlg.setLayout( mainLayout );
1630 layout->addWidget( baseWidget );
1632 QLineEdit *title =
new QLineEdit( itemData.
name() );
1635 text->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1643 connect( text, &QgsCodeEditorExpression::textChanged,
this, [ = ]
1645 textWrapper->
setText( text->text( ) );
1652 expressionWidget->registerExpressionContextGenerator(
this );
1653 expressionWidget->setLayer( mLayer );
1654 QToolButton *addFieldButton =
new QToolButton();
1657 QToolButton *editExpressionButton =
new QToolButton();
1659 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1661 connect( addFieldButton, &QAbstractButton::clicked,
this, [ = ]
1663 QString expression = expressionWidget->expression().trimmed();
1664 if ( !expression.isEmpty() )
1665 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1667 connect( editExpressionButton, &QAbstractButton::clicked,
this, [ = ]
1674 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1675 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1677 QString expression = exprDlg.expressionText().trimmed();
1678 if ( !expression.isEmpty() )
1679 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1683 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1684 layout->addWidget( title );
1685 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"Text" ) );
1686 layout->addWidget( expressionWidgetBox );
1687 expressionWidgetBox->setLayout(
new QHBoxLayout );
1688 expressionWidgetBox->layout()->addWidget( expressionWidget );
1689 expressionWidgetBox->layout()->addWidget( addFieldButton );
1690 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1691 layout->addWidget( text );
1693 textPreviewBox->setLayout(
new QGridLayout );
1694 textPreviewBox->setMinimumWidth( 400 );
1695 textPreviewBox->layout()->addWidget( textWrapper->
widget() );
1697 emit text->textChanged();
1698 textLayout->addWidget( textPreviewBox );
1700 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1702 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1703 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1705 mainLayout->addWidget( buttonBox );
1710 textEdCfg.
text = text->text();
1711 itemData.
setName( title->text() );
1713 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1716 item->setText( 0, title->text() );
1726 dlg.setWindowTitle( tr(
"Configure Spacer Widget" ) );
1728 QVBoxLayout *mainLayout =
new QVBoxLayout();
1729 mainLayout->addWidget(
new QLabel( tr(
"Title" ) ) );
1730 QLineEdit *title =
new QLineEdit( itemData.
name() );
1731 mainLayout->addWidget( title );
1733 QHBoxLayout *cbLayout =
new QHBoxLayout( );
1734 mainLayout->addLayout( cbLayout );
1735 dlg.setLayout( mainLayout );
1736 QCheckBox *cb =
new QCheckBox { &dlg };
1738 cbLayout->addWidget(
new QLabel( tr(
"Draw horizontal line" ), &dlg ) );
1739 cbLayout->addWidget( cb );
1742 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1744 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1745 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1747 mainLayout->addWidget( buttonBox );
1752 spacerEdCfg.
drawLine = cb->isChecked();
1755 itemData.
setName( title->text() );
1757 item->setText( 0, title->text() );
1790 QTreeWidgetItemIterator it(
this );
1796 if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
1803 ( *it )->setSelected(
true );
1826 QString displayName;
1829 stream >> type >> name >> displayName;
1840 return mContainerType;
1845 mContainerType = type;
1855 mLabelStyle = labelStyle;
1865 mShowLabel = showLabel;
1870 return mVisibilityExpression;
1875 mVisibilityExpression = visibilityExpression;
1880 return mCollapsedExpression;
1885 mCollapsedExpression = collapsedExpression;
1890 return mRelationEditorConfiguration;
1895 mRelationEditorConfiguration = relationEditorConfiguration;
1900 return mQmlElementEditorConfiguration;
1905 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
1911 return mHtmlElementEditorConfiguration;
1916 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
1921 return mSpacerElementEditorConfiguration;
1926 mSpacerElementEditorConfiguration = spacerElementEditorConfiguration;
1931 return mBackgroundColor;
1936 mBackgroundColor = backgroundColor;
1941 return mTextElementEditorConfiguration;
1946 mTextElementEditorConfiguration = textElementEditorConfiguration;
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 (since QGIS 3.22)
@ QmlElement
A QML element.
@ HtmlElement
A HTML element.
@ TextElement
A text element (since QGIS 3.30)
@ SpacerElement
A spacer element (since QGIS 3.30)
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)
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.
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...
QgsFieldConstraints constraints
Container of fields for a vector layer.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
@ OriginExpression
Field is calculated from an expression.
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
int count() const
Returns number of items.
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
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).
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.
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.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void setConstraintExpression(int index, const QString &expression, const QString &description=QString())
Sets the constraint expression for the specified field 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.
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.