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 );
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 );
150 if ( polymorphicRelation.
isValid() )
152 name = QStringLiteral(
"%1 (%2)" ).arg( relation.name(), polymorphicRelation.
name() );
156 name = relation.
name();
163 catitem->setExpanded(
true );
171 for (
const auto &action : std::as_const( actions ) )
173 if ( action.isValid() && action.runable() && ( action.actionScopes().contains( QStringLiteral(
"Feature" ) ) || action.actionScopes().contains( QStringLiteral(
"Layer" ) ) ) )
175 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
202 catitem->setExpanded(
true );
210 mFormLayoutTree->setSelectionBehavior( QAbstractItemView::SelectRows );
211 mFormLayoutTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
248 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( QVariant::fromValue(
mLayer->
editFormConfig().
layout() ) ) );
250 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
253 mEditFormLineEdit->setText( cfg.
uiForm() );
265 if ( mInitCode.isEmpty() )
267 mInitCode.append( tr(
"# -*- coding: utf-8 -*-\n\"\"\"\n"
268 "QGIS forms can have a Python function that is called when the form is\n"
271 "Use this function to add extra logic to your forms.\n"
273 "Enter the name of the function in the \"Python Init function\"\n"
275 "An example follows:\n"
277 "from qgis.PyQt.QtWidgets import QWidget\n\n"
278 "def my_form_open(dialog, layer, feature):\n"
279 " geom = feature.geometry()\n"
280 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n" ) );
284void QgsAttributesFormProperties::loadAttributeTypeDialog()
291 const FieldConfig cfg = item->data( 0,
FieldConfigRole ).value<FieldConfig>();
292 const QString fieldName = item->data( 0,
FieldNameRole ).toString();
334 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
340void QgsAttributesFormProperties::storeAttributeTypeDialog()
389 cfg.mFieldConstraints = constraints;
402 QTreeWidgetItem *item = *itemIt;
403 if ( item->data( 0,
FieldNameRole ).toString() == fieldName )
404 item->setData( 0,
FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
408void QgsAttributesFormProperties::storeAttributeWidgetEdit()
416void QgsAttributesFormProperties::loadAttributeWidgetEdit()
421 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
423 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
427void QgsAttributesFormProperties::loadInfoWidget(
const QString &infoText )
430 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
434void QgsAttributesFormProperties::storeAttributeContainerEdit()
442void QgsAttributesFormProperties::loadAttributeContainerEdit()
447 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().at( 0 );
451 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
457 auto setCommonProperties = [widgetDef]( DnDTreeItemData &itemData ) {
458 itemData.setShowLabel( widgetDef->
showLabel() );
459 itemData.setLabelStyle( widgetDef->
labelStyle() );
464 QTreeWidgetItem *newWidget =
nullptr;
465 switch ( widgetDef->
type() )
470 setCommonProperties( itemData );
471 newWidget = tree->
addItem( parent, itemData );
479 if ( action.isValid() )
481 DnDTreeItemData itemData = DnDTreeItemData(
DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
482 setCommonProperties( itemData );
483 newWidget = tree->
addItem( parent, itemData );
496 setCommonProperties( itemData );
498 RelationEditorConfiguration relEdConfig;
502 relEdConfig.nmRelationId = relationEditor->
nmRelationId();
504 relEdConfig.label = relationEditor->
label();
505 itemData.setRelationEditorConfiguration( relEdConfig );
506 newWidget = tree->
addItem( parent, itemData );
519 itemData.setContainerType( container->
type() );
523 itemData.setCollapsed( container->
collapsed() );
525 setCommonProperties( itemData );
527 newWidget = tree->
addItem( parent, itemData );
529 const QList<QgsAttributeEditorElement *> children = container->
children();
532 loadAttributeEditorTreeItem( wdg, newWidget, tree );
541 QmlElementEditorConfiguration qmlEdConfig;
542 qmlEdConfig.qmlCode = qmlElementEditor->
qmlCode();
543 itemData.setQmlElementEditorConfiguration( qmlEdConfig );
544 setCommonProperties( itemData );
545 newWidget = tree->
addItem( parent, itemData );
553 HtmlElementEditorConfiguration htmlEdConfig;
554 htmlEdConfig.htmlCode = htmlElementEditor->
htmlCode();
555 itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
556 setCommonProperties( itemData );
557 newWidget = tree->
addItem( parent, itemData );
565 TextElementEditorConfiguration textEdConfig;
566 textEdConfig.text = textElementEditor->
text();
567 itemData.setTextElementEditorConfiguration( textEdConfig );
568 setCommonProperties( itemData );
569 newWidget = tree->
addItem( parent, itemData );
577 SpacerElementEditorConfiguration spacerEdConfig;
578 spacerEdConfig.drawLine = spacerElementEditor->
drawLine();
579 itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
580 setCommonProperties( itemData );
581 itemData.setShowLabel(
false );
582 newWidget = tree->
addItem( parent, itemData );
588 QgsDebugError( QStringLiteral(
"Not loading invalid attribute editor type..." ) );
594 newWidget->setExpanded(
true );
600void QgsAttributesFormProperties::onAttributeSelectionChanged()
602 disconnect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
604 connect(
mFormLayoutTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
607void QgsAttributesFormProperties::onFormLayoutSelectionChanged()
610 disconnect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
612 connect(
mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged,
this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
620 storeAttributeWidgetEdit();
622 clearAttributeTypeFrame();
624 if ( emitter->selectedItems().count() != 1 )
626 receiver->clearSelection();
630 const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
631 switch ( itemData.type() )
638 loadAttributeWidgetEdit();
642 loadInfoWidget( tr(
"This configuration is available in the Drag and Drop Designer" ) );
650 loadAttributeWidgetEdit();
651 loadAttributeTypeDialog();
656 receiver->clearSelection();
657 loadAttributeContainerEdit();
664 loadInfoWidget( action.html() );
674 loadInfoWidget( tr(
"This configuration is available with double-click in the Drag and Drop Designer" ) );
678 loadInfoWidget( tr(
"This configuration is available with double-click" ) );
680 receiver->clearSelection();
685 receiver->clearSelection();
692void QgsAttributesFormProperties::clearAttributeTypeFrame()
720void QgsAttributesFormProperties::onInvertSelectionButtonClicked(
bool checked )
725 for (
int i = 0; i < rootItem->childCount(); ++i )
727 rootItem->child( i )->setSelected( !selectedItemList.contains( rootItem->child( i ) ) );
731void QgsAttributesFormProperties::addContainer()
733 QList<QgsAddAttributeFormContainerDialog::ContainerPair> existingContainerList;
737 const DnDTreeItemData itemData = ( *it )->data( 0,
DnDTreeRole ).value<DnDTreeItemData>();
743 QTreeWidgetItem *currentItem =
mFormLayoutTree->selectedItems().value( 0 );
746 if ( !dialog.exec() )
749 const QString name = dialog.name();
750 QTreeWidgetItem *parentContainerItem = dialog.parentContainerItem();
754void QgsAttributesFormProperties::removeTabOrGroupButton()
760 const QList<QTreeWidgetItem *> items =
mFormLayoutTree->selectedItems();
764 delete items.at( 0 );
774 switch ( itemData.
type() )
823 for (
int t = 0; t < item->childCount(); t++ )
830 widgetDef = container;
881void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged(
int )
887 mFormLayoutWidget->setVisible(
false );
888 mUiFileFrame->setVisible(
false );
889 mAddTabOrGroupButton->setVisible(
false );
890 mRemoveTabOrGroupButton->setVisible(
false );
891 mInvertSelectionButton->setVisible(
false );
895 mFormLayoutWidget->setVisible(
true );
896 mUiFileFrame->setVisible(
false );
897 mAddTabOrGroupButton->setVisible(
true );
898 mRemoveTabOrGroupButton->setVisible(
true );
899 mInvertSelectionButton->setVisible(
true );
904 mFormLayoutWidget->setVisible(
false );
905 mUiFileFrame->setVisible(
true );
906 mAddTabOrGroupButton->setVisible(
false );
907 mRemoveTabOrGroupButton->setVisible(
false );
908 mInvertSelectionButton->setVisible(
false );
913void QgsAttributesFormProperties::mTbInitCode_clicked()
922 if ( !attributesFormInitCode.exec() )
925 mInitCodeSource = attributesFormInitCode.
codeSource();
926 mInitCode = attributesFormInitCode.
initCode();
931void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
934 const QString lastUsedDir = myQSettings.
value( QStringLiteral(
"style/lastUIDir" ), QDir::homePath() ).toString();
935 const QString uifilename = QFileDialog::getOpenFileName(
this, tr(
"Select edit form" ), lastUsedDir, tr(
"UI file" ) +
" (*.ui)" );
937 if ( uifilename.isNull() )
940 const QFileInfo fi( uifilename );
941 myQSettings.
setValue( QStringLiteral(
"style/lastUIDir" ), fi.path() );
942 mEditFormLineEdit->setText( uifilename );
947 storeAttributeWidgetEdit();
948 storeAttributeContainerEdit();
949 storeAttributeTypeDialog();
955 storeAttributeWidgetEdit();
956 storeAttributeContainerEdit();
957 storeAttributeTypeDialog();
963 for (
int i = 0; i < fieldContainer->childCount(); i++ )
965 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
968 const QString fieldName { fieldItem->data( 0,
FieldNameRole ).toString() };
1020 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1022 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1024 if ( editorElement )
1025 editFormConfig.
addTab( editorElement );
1028 editFormConfig.
setUiForm( mEditFormLineEdit->text() );
1042 for (
int i = 0; i < relationContainer->childCount(); i++ )
1044 QTreeWidgetItem *relationItem = relationContainer->child( i );
1047 for (
int t = 0; t <
mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
1049 QTreeWidgetItem *tabItem =
mFormLayoutTree->invisibleRootItem()->child( t );
1052 if ( tabItemData.
type() == itemData.
type() && tabItemData.
name() == itemData.
name() )
1089QgsAttributesFormProperties::FieldConfig::operator QVariant()
1091 return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *
this );
1098QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
1100 return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *
this );
1109 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << title );
1110 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1111 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1116 parent->addChild( newItem );
1117 newItem->setExpanded(
true );
1122 : QTreeWidget( parent )
1125 connect(
this, &QTreeWidget::itemDoubleClicked,
this, &QgsAttributesDnDTree::onItemDoubleClicked );
1130 QTreeWidgetItem *newItem =
new QTreeWidgetItem( QStringList() << data.
name() );
1132 switch ( data.
type() )
1141 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1147 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1148 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1155 newItem->setIcon( 0, icon );
1162 newItem->setText( 0, tr(
"Invalid relation" ) );
1163 newItem->setForeground( 0, QColor( 255, 0, 0 ) );
1168 parent->addChild( newItem );
1170 parent->insertChild( index, newItem );
1182 const QMimeData *data =
event->mimeData();
1184 if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1188 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1189 QDataStream stream( &itemData, QIODevice::ReadOnly );
1190 stream >> itemElement;
1193 if ( event->source() ==
this )
1195 event->setDropAction( Qt::MoveAction );
1203 QTreeWidget::dragMoveEvent( event );
1209 bool bDropSuccessful =
false;
1211 if ( action == Qt::IgnoreAction )
1213 bDropSuccessful =
true;
1215 else if ( data->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1217 QByteArray itemData = data->data( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) );
1218 QDataStream stream( &itemData, QIODevice::ReadOnly );
1221 while ( !stream.atEnd() )
1223 stream >> itemElement;
1225 QTreeWidgetItem *newItem;
1229 newItem =
addItem( parent, itemElement, index++ );
1230 bDropSuccessful =
true;
1234 newItem =
addItem( invisibleRootItem(), itemElement, index++ );
1235 bDropSuccessful =
true;
1240 onItemDoubleClicked( newItem, 0 );
1245 onItemDoubleClicked( newItem, 0 );
1250 onItemDoubleClicked( newItem, 0 );
1255 onItemDoubleClicked( newItem, 0 );
1259 newItem->setSelected(
true );
1263 return bDropSuccessful;
1268 if ( !event->mimeData()->hasFormat( QStringLiteral(
"application/x-qgsattributetabledesignerelement" ) ) )
1271 if ( event->source() ==
this )
1273 event->setDropAction( Qt::MoveAction );
1276 QTreeWidget::dropEvent( event );
1281 return QStringList() << QStringLiteral(
"application/x-qgsattributetabledesignerelement" );
1284#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1290 if ( items.count() <= 0 )
1293 const QStringList types = mimeTypes();
1295 if ( types.isEmpty() )
1298 QMimeData *data =
new QMimeData();
1299 const QString format = types.at( 0 );
1301 QDataStream stream( &encoded, QIODevice::WriteOnly );
1303 const auto constItems = items;
1304 for (
const QTreeWidgetItem *item : constItems )
1314 data->setData( format, encoded );
1319void QgsAttributesDnDTree::onItemDoubleClicked( QTreeWidgetItem *item,
int column )
1325 QGroupBox *baseData =
new QGroupBox( tr(
"Base configuration" ) );
1327 QFormLayout *baseLayout =
new QFormLayout();
1328 baseData->setLayout( baseLayout );
1329 QCheckBox *showLabelCheckbox =
new QCheckBox( QStringLiteral(
"Show label" ) );
1330 showLabelCheckbox->setChecked( itemData.
showLabel() );
1331 baseLayout->addRow( showLabelCheckbox );
1332 QWidget *baseWidget =
new QWidget();
1333 baseWidget->setLayout( baseLayout );
1335 switch ( itemData.
type() )
1350 dlg.setWindowTitle( tr(
"Configure QML Widget" ) );
1352 QVBoxLayout *mainLayout =
new QVBoxLayout();
1353 QHBoxLayout *qmlLayout =
new QHBoxLayout();
1354 QVBoxLayout *layout =
new QVBoxLayout();
1355 mainLayout->addLayout( qmlLayout );
1356 qmlLayout->addLayout( layout );
1357 dlg.setLayout( mainLayout );
1358 layout->addWidget( baseWidget );
1360 QLineEdit *title =
new QLineEdit( itemData.
name() );
1371 connect( qmlCode, &QsciScintilla::textChanged,
this, [=] {
1378 QComboBox *qmlObjectTemplate =
new QComboBox();
1379 qmlObjectTemplate->addItem( tr(
"Free Text…" ) );
1380 qmlObjectTemplate->addItem( tr(
"Rectangle" ) );
1381 qmlObjectTemplate->addItem( tr(
"Pie Chart" ) );
1382 qmlObjectTemplate->addItem( tr(
"Bar Chart" ) );
1383 connect( qmlObjectTemplate, qOverload<int>( &QComboBox::activated ), qmlCode, [=](
int index ) {
1389 qmlCode->setText( QString() );
1394 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1399 " color: \"steelblue\"\n"
1400 " Text{ text: \"A rectangle\" }\n"
1406 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1407 "import QtCharts 2.0\n"
1415 " PieSlice { label: \"First slice\"; value: 25 }\n"
1416 " PieSlice { label: \"Second slice\"; value: 45 }\n"
1417 " PieSlice { label: \"Third slice\"; value: 30 }\n"
1424 qmlCode->setText( QStringLiteral(
"import QtQuick 2.0\n"
1425 "import QtCharts 2.0\n"
1428 " title: \"Bar series\"\n"
1431 " legend.alignment: Qt.AlignBottom\n"
1432 " antialiasing: true\n"
1441 " axisY: valueAxisY\n"
1442 " axisX: BarCategoryAxis { categories: [\"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\" ] }\n"
1443 " BarSet { label: \"Bob\"; values: [2, 2, 3, 4, 5, 6] }\n"
1444 " BarSet { label: \"Susan\"; values: [5, 1, 2, 4, 1, 7] }\n"
1445 " BarSet { label: \"James\"; values: [3, 5, 8, 13, 5, 8] }\n"
1457 expressionWidget->registerExpressionContextGenerator(
this );
1458 expressionWidget->setLayer( mLayer );
1459 QToolButton *addFieldButton =
new QToolButton();
1462 QToolButton *editExpressionButton =
new QToolButton();
1464 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1466 connect( addFieldButton, &QAbstractButton::clicked,
this, [=] {
1467 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1468 if ( !expression.isEmpty() )
1469 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1472 connect( editExpressionButton, &QAbstractButton::clicked,
this, [=] {
1474 expression.replace( QLatin1String(
"\\\"" ), QLatin1String(
"\"" ) );
1478 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1479 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1481 QString expression = exprDlg.expressionText().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1482 if ( !expression.isEmpty() )
1483 qmlCode->
insertText( QStringLiteral(
"expression.evaluate(\"%1\")" ).arg( expression ) );
1487 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1488 layout->addWidget( title );
1489 QGroupBox *qmlCodeBox =
new QGroupBox( tr(
"QML Code" ) );
1490 qmlCodeBox->setLayout(
new QVBoxLayout );
1491 qmlCodeBox->layout()->addWidget( qmlObjectTemplate );
1492 QWidget *expressionWidgetBox =
new QWidget();
1493 qmlCodeBox->layout()->addWidget( expressionWidgetBox );
1494 expressionWidgetBox->setLayout(
new QHBoxLayout );
1495 expressionWidgetBox->layout()->setContentsMargins( 0, 0, 0, 0 );
1496 expressionWidgetBox->layout()->addWidget( expressionWidget );
1497 expressionWidgetBox->layout()->addWidget( addFieldButton );
1498 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1499 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1500 layout->addWidget( qmlCodeBox );
1501 layout->addWidget( qmlCode );
1503 qmlPreviewBox->setLayout(
new QGridLayout );
1504 qmlPreviewBox->setMinimumWidth( 400 );
1505 qmlPreviewBox->layout()->addWidget( qmlWrapper->
widget() );
1507 emit qmlCode->textChanged();
1508 qmlLayout->addWidget( qmlPreviewBox );
1510 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1512 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1513 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1515 mainLayout->addWidget( buttonBox );
1520 qmlEdCfg.
qmlCode = qmlCode->text();
1521 itemData.
setName( title->text() );
1523 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1526 item->setText( 0, title->text() );
1536 dlg.setWindowTitle( tr(
"Configure HTML Widget" ) );
1538 QVBoxLayout *mainLayout =
new QVBoxLayout();
1539 QHBoxLayout *htmlLayout =
new QHBoxLayout();
1540 QVBoxLayout *layout =
new QVBoxLayout();
1541 mainLayout->addLayout( htmlLayout );
1542 htmlLayout->addLayout( layout );
1543 dlg.setLayout( mainLayout );
1544 layout->addWidget( baseWidget );
1546 QLineEdit *title =
new QLineEdit( itemData.
name() );
1550 htmlCode->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1558 connect( htmlCode, &QgsCodeEditorHTML::textChanged,
this, [=] {
1566 expressionWidget->registerExpressionContextGenerator(
this );
1567 expressionWidget->setLayer( mLayer );
1568 QToolButton *addFieldButton =
new QToolButton();
1571 QToolButton *editExpressionButton =
new QToolButton();
1573 editExpressionButton->setToolTip( tr(
"Insert/Edit Expression" ) );
1575 connect( addFieldButton, &QAbstractButton::clicked,
this, [=] {
1576 QString expression = expressionWidget->expression().trimmed().replace(
'"', QLatin1String(
"\\\"" ) );
1577 if ( !expression.isEmpty() )
1578 htmlCode->
insertText( QStringLiteral(
"<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expression ) );
1581 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, [=] {
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, [=] {
1678 QString expression = expressionWidget->expression().trimmed();
1679 if ( !expression.isEmpty() )
1680 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1682 connect( editExpressionButton, &QAbstractButton::clicked,
this, [=] {
1688 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1689 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
1691 QString expression = exprDlg.expressionText().trimmed();
1692 if ( !expression.isEmpty() )
1693 text->
insertText( QStringLiteral(
"[%%1%]" ).arg( expression ) );
1697 layout->addWidget(
new QLabel( tr(
"Title" ) ) );
1698 layout->addWidget( title );
1699 QGroupBox *expressionWidgetBox =
new QGroupBox( tr(
"Text" ) );
1700 layout->addWidget( expressionWidgetBox );
1701 expressionWidgetBox->setLayout(
new QHBoxLayout );
1702 expressionWidgetBox->layout()->addWidget( expressionWidget );
1703 expressionWidgetBox->layout()->addWidget( addFieldButton );
1704 expressionWidgetBox->layout()->addWidget( editExpressionButton );
1705 layout->addWidget( text );
1707 textPreviewBox->setLayout(
new QGridLayout );
1708 textPreviewBox->setMinimumWidth( 400 );
1709 textPreviewBox->layout()->addWidget( textWrapper->
widget() );
1711 emit text->textChanged();
1712 textLayout->addWidget( textPreviewBox );
1714 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1716 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1717 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1719 mainLayout->addWidget( buttonBox );
1724 textEdCfg.
text = text->text();
1725 itemData.
setName( title->text() );
1727 itemData.
setShowLabel( showLabelCheckbox->isChecked() );
1730 item->setText( 0, title->text() );
1740 dlg.setWindowTitle( tr(
"Configure Spacer Widget" ) );
1742 QVBoxLayout *mainLayout =
new QVBoxLayout();
1743 mainLayout->addWidget(
new QLabel( tr(
"Title" ) ) );
1744 QLineEdit *title =
new QLineEdit( itemData.
name() );
1745 mainLayout->addWidget( title );
1747 QHBoxLayout *cbLayout =
new QHBoxLayout();
1748 mainLayout->addLayout( cbLayout );
1749 dlg.setLayout( mainLayout );
1750 QCheckBox *cb =
new QCheckBox { &dlg };
1752 cbLayout->addWidget(
new QLabel( tr(
"Draw horizontal line" ), &dlg ) );
1753 cbLayout->addWidget( cb );
1756 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1758 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1759 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1761 mainLayout->addWidget( buttonBox );
1766 spacerEdCfg.
drawLine = cb->isChecked();
1769 itemData.
setName( title->text() );
1771 item->setText( 0, title->text() );
1804 QTreeWidgetItemIterator it(
this );
1810 if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
1817 ( *it )->setSelected(
true );
1840 QString displayName;
1843 stream >> type >> name >> displayName;
1854 return mContainerType;
1859 mContainerType = type;
1869 mLabelStyle = labelStyle;
1879 mShowLabel = showLabel;
1884 return mVisibilityExpression;
1889 mVisibilityExpression = visibilityExpression;
1894 return mCollapsedExpression;
1899 mCollapsedExpression = collapsedExpression;
1904 return mRelationEditorConfiguration;
1909 mRelationEditorConfiguration = relationEditorConfiguration;
1914 return mQmlElementEditorConfiguration;
1919 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
1925 return mHtmlElementEditorConfiguration;
1930 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
1935 return mSpacerElementEditorConfiguration;
1940 mSpacerElementEditorConfiguration = spacerElementEditorConfiguration;
1945 return mBackgroundColor;
1950 mBackgroundColor = backgroundColor;
1955 return mTextElementEditorConfiguration;
1960 mTextElementEditorConfiguration = textElementEditorConfiguration;
1963void QgsAttributesFormProperties::updatedFields()
1966 QMap<QString, FieldConfig> fieldConfigs;
1968 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1970 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1971 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1973 fieldConfigs[fieldName] = cfg;
1979 for (
int i = 0; i < fieldContainer->childCount(); i++ )
1981 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
1982 const QString fieldName = fieldItem->data( 0,
FieldNameRole ).toString();
1983 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)
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)
QTreeWidgetItem * addItem(QTreeWidgetItem *parent, const QgsAttributesFormProperties::DnDTreeItemData &data, int index=-1, const QIcon &icon=QIcon())
Adds a new item to a parent.
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.
A polymorphic relation consists of the same properties like a normal relation except for the referenc...
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.
QgsVectorLayer * referencedLayer
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.