QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
qgsattributesformproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsattributesformproperties.cpp
3 ---------------------
4 begin : August 2017
5 copyright : (C) 2017 by David Signer
6 email : david at opengis dot ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsactionmanager.h"
17#include "qgsaddtaborgroup.h"
19#include "qgsattributetypedialog.h"
20#include "qgsattributeformcontaineredit.h"
21#include "qgsattributewidgetedit.h"
23#include "qgsfieldcombobox.h"
24#include "qgsqmlwidgetwrapper.h"
26#include "qgsapplication.h"
27#include "qgscolorbutton.h"
28#include "qgscodeeditorhtml.h"
36
37
39 : QWidget( parent )
40 , mLayer( layer )
41{
42 if ( !layer )
43 return;
44
45 setupUi( this );
46
47 mEditorLayoutComboBox->addItem( tr( "Autogenerate" ), QgsEditFormConfig::EditorLayout::GeneratedLayout );
48 mEditorLayoutComboBox->addItem( tr( "Drag and Drop Designer" ), QgsEditFormConfig::EditorLayout::TabLayout );
49 mEditorLayoutComboBox->addItem( tr( "Provide ui-file" ), QgsEditFormConfig::EditorLayout::UiFileLayout );
50
51 // available widgets tree
52 QGridLayout *availableWidgetsWidgetLayout = new QGridLayout;
54 availableWidgetsWidgetLayout->addWidget( mAvailableWidgetsTree );
55 availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
56 mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout );
57 mAvailableWidgetsTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
58 mAvailableWidgetsTree->setHeaderLabels( QStringList() << tr( "Available Widgets" ) );
60
61 // form layout tree
62 QGridLayout *formLayoutWidgetLayout = new QGridLayout;
64 mFormLayoutWidget->setLayout( formLayoutWidgetLayout );
65 formLayoutWidgetLayout->addWidget( mFormLayoutTree );
66 formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
67 mFormLayoutTree->setHeaderLabels( QStringList() << tr( "Form Layout" ) );
69
70 connect( mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
71 connect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
72 connect( mAddTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::addTabOrGroupButton );
73 connect( mRemoveTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::removeTabOrGroupButton );
74 connect( mInvertSelectionButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked );
75 connect( mEditorLayoutComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged );
76 connect( pbnSelectEditForm, &QToolButton::clicked, this, &QgsAttributesFormProperties::pbnSelectEditForm_clicked );
77 connect( mTbInitCode, &QPushButton::clicked, this, &QgsAttributesFormProperties::mTbInitCode_clicked );
78}
79
89
91{
92 mAvailableWidgetsTree->clear();
93 mAvailableWidgetsTree->setSortingEnabled( false );
94 mAvailableWidgetsTree->setSelectionBehavior( QAbstractItemView::SelectRows );
95 mAvailableWidgetsTree->setAcceptDrops( false );
96 mAvailableWidgetsTree->setDragDropMode( QAbstractItemView::DragOnly );
97
98 //load Fields
99
100 DnDTreeItemData catItemData = DnDTreeItemData( DnDTreeItemData::WidgetType, QStringLiteral( "Fields" ), QStringLiteral( "Fields" ) );
101 QTreeWidgetItem *catitem = mAvailableWidgetsTree->addItem( mAvailableWidgetsTree->invisibleRootItem(), catItemData );
102
103 const QgsFields fields = mLayer->fields();
104 for ( int i = 0; i < fields.size(); ++i )
105 {
106 const QgsField field = fields.at( i );
108 itemData.setShowLabel( true );
109
110 FieldConfig cfg( mLayer, i );
111
112 QTreeWidgetItem *item = mAvailableWidgetsTree->addItem( catitem, itemData, -1, fields.iconForField( i, true ) );
113
114 item->setData( 0, FieldConfigRole, cfg );
115 item->setData( 0, FieldNameRole, field.name() );
116
117 QString tooltip;
118 if ( !field.alias().isEmpty() )
119 tooltip = tr( "%1 (%2)" ).arg( field.name(), field.alias() );
120 else
121 tooltip = field.name();
122 item->setToolTip( 0, tooltip );
123 }
124 catitem->setExpanded( true );
125
126 //load Relations
127 catItemData = DnDTreeItemData( DnDTreeItemData::WidgetType, QStringLiteral( "Relations" ), tr( "Relations" ) );
128 catitem = mAvailableWidgetsTree->addItem( mAvailableWidgetsTree->invisibleRootItem(), catItemData );
129
130 const QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );
131
132 for ( const QgsRelation &relation : relations )
133 {
134 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Relation, relation.id(), relation.name() );
135 itemData.setShowLabel( true );
136 QTreeWidgetItem *item = mAvailableWidgetsTree->addItem( catitem, itemData );
137 item->setData( 0, FieldNameRole, relation.id() );
138 }
139 catitem->setExpanded( true );
140
141 // Form actions
142 catItemData = DnDTreeItemData( DnDTreeItemData::WidgetType, QStringLiteral( "Actions" ), tr( "Actions" ) );
143 catitem = mAvailableWidgetsTree->addItem( mAvailableWidgetsTree->invisibleRootItem(), catItemData );
144
145 const QList<QgsAction> actions { mLayer->actions()->actions( ) };
146
147 for ( const auto &action : std::as_const( actions ) )
148 {
149 if ( action.isValid() && action.runable() &&
150 ( action.actionScopes().contains( QStringLiteral( "Feature" ) ) ||
151 action.actionScopes().contains( QStringLiteral( "Layer" ) ) ) )
152 {
153 const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
154 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Action, action.id().toString(), actionTitle );
155 itemData.setShowLabel( true );
156 mAvailableWidgetsTree->addItem( catitem, itemData );
157 }
158 }
159
160 // QML/HTML widget
161 catItemData = DnDTreeItemData( DnDTreeItemData::WidgetType, QStringLiteral( "Other" ), tr( "Other Widgets" ) );
162 catitem = mAvailableWidgetsTree->addItem( mAvailableWidgetsTree->invisibleRootItem(), catItemData );
163
164 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::QmlWidget, QStringLiteral( "QmlWidget" ), tr( "QML Widget" ) );
165 itemData.setShowLabel( true );
166 mAvailableWidgetsTree->addItem( catitem, itemData );
167
168 auto itemDataHtml { DnDTreeItemData( DnDTreeItemData::HtmlWidget, QStringLiteral( "HtmlWidget" ), tr( "HTML Widget" ) ) };
169 itemDataHtml.setShowLabel( true );
170 mAvailableWidgetsTree->addItem( catitem, itemDataHtml );
171 catitem ->setExpanded( true );
172}
173
175{
176 // tabs and groups info
177 mFormLayoutTree->clear();
178 mFormLayoutTree->setSortingEnabled( false );
179 mFormLayoutTree->setSelectionBehavior( QAbstractItemView::SelectRows );
180 mFormLayoutTree->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
181 mFormLayoutTree->setAcceptDrops( true );
182 mFormLayoutTree->setDragDropMode( QAbstractItemView::DragDrop );
183
184 const auto constTabs = mLayer->editFormConfig().tabs();
185 for ( QgsAttributeEditorElement *wdg : constTabs )
186 {
187 loadAttributeEditorTreeItem( wdg, mFormLayoutTree->invisibleRootItem(), mFormLayoutTree );
188 }
189}
190
191
193{
195 {
196 mFormSuppressCmbBx->addItem( tr( "Hide Form on Add Feature (global settings)" ) );
197 }
198 else
199 {
200 mFormSuppressCmbBx->addItem( tr( "Show Form on Add Feature (global settings)" ) );
201 }
202 mFormSuppressCmbBx->addItem( tr( "Hide Form on Add Feature" ) );
203 mFormSuppressCmbBx->addItem( tr( "Show Form on Add Feature" ) );
204
205 mFormSuppressCmbBx->setCurrentIndex( mLayer->editFormConfig().suppress() );
206}
207
214
216{
217 mEditorLayoutComboBox->setCurrentIndex( mEditorLayoutComboBox->findData( mLayer->editFormConfig().layout() ) );
218
219 mEditorLayoutComboBox_currentIndexChanged( mEditorLayoutComboBox->currentIndex() );
220
222 mEditFormLineEdit->setText( cfg.uiForm() );
223}
224
226{
228
229 mInitCodeSource = cfg.initCodeSource();
230 mInitFunction = cfg.initFunction();
231 mInitFilePath = cfg.initFilePath();
232 mInitCode = cfg.initCode();
233
234 if ( mInitCode.isEmpty() )
235 {
236 mInitCode.append( tr( "# -*- coding: utf-8 -*-\n\"\"\"\n"
237 "QGIS forms can have a Python function that is called when the form is\n"
238 "opened.\n"
239 "\n"
240 "Use this function to add extra logic to your forms.\n"
241 "\n"
242 "Enter the name of the function in the \"Python Init function\"\n"
243 "field.\n"
244 "An example follows:\n"
245 "\"\"\"\n"
246 "from qgis.PyQt.QtWidgets import QWidget\n\n"
247 "def my_form_open(dialog, layer, feature):\n"
248 " geom = feature.geometry()\n"
249 " control = dialog.findChild(QWidget, \"MyLineEdit\")\n" ) );
250 }
251}
252
253void QgsAttributesFormProperties::loadAttributeTypeDialog()
254{
255 if ( mAvailableWidgetsTree->selectedItems().count() != 1 )
256 return;
257
258 QTreeWidgetItem *item = mAvailableWidgetsTree->selectedItems().at( 0 );
259
260 const FieldConfig cfg = item->data( 0, FieldConfigRole ).value<FieldConfig>();
261 const QString fieldName = item->data( 0, FieldNameRole ).toString();
262 const int index = mLayer->fields().indexOf( fieldName );
263
264 if ( index < 0 )
265 return;
266
267 mAttributeTypeDialog = new QgsAttributeTypeDialog( mLayer, index, mAttributeTypeFrame );
268
269 const QgsFieldConstraints constraints = cfg.mFieldConstraints;
270
271 mAttributeTypeDialog->setAlias( cfg.mAlias );
272 mAttributeTypeDialog->setDataDefinedProperties( cfg.mDataDefinedProperties );
273 mAttributeTypeDialog->setComment( cfg.mComment );
274 mAttributeTypeDialog->setFieldEditable( cfg.mEditable );
275 mAttributeTypeDialog->setLabelOnTop( cfg.mLabelOnTop );
276 mAttributeTypeDialog->setReuseLastValues( cfg.mReuseLastValues );
281
282 QgsFieldConstraints::Constraints providerConstraints = QgsFieldConstraints::Constraints();
284 providerConstraints |= QgsFieldConstraints::ConstraintNotNull;
286 providerConstraints |= QgsFieldConstraints::ConstraintUnique;
288 providerConstraints |= QgsFieldConstraints::ConstraintExpression;
289 mAttributeTypeDialog->setProviderConstraints( providerConstraints );
290
291 mAttributeTypeDialog->setConstraintExpression( constraints.constraintExpression() );
292 mAttributeTypeDialog->setConstraintExpressionDescription( constraints.constraintDescription() );
294 mAttributeTypeDialog->setDefaultValueExpression( mLayer->defaultValueDefinition( index ).expression() );
295 mAttributeTypeDialog->setApplyDefaultValueOnUpdate( mLayer->defaultValueDefinition( index ).applyOnUpdate() );
296
297 mAttributeTypeDialog->setEditorWidgetConfig( cfg.mEditorWidgetConfig );
298 mAttributeTypeDialog->setEditorWidgetType( cfg.mEditorWidgetType );
299
300 mAttributeTypeDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
301 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
302
303 mAttributeTypeFrame->layout()->addWidget( mAttributeTypeDialog );
304}
305
306
307void QgsAttributesFormProperties::storeAttributeTypeDialog()
308{
310 return;
311
312 if ( mAttributeTypeDialog->fieldIdx() < 0 || mAttributeTypeDialog->fieldIdx() >= mLayer->fields().count() )
313 return;
314
315 FieldConfig cfg;
316
317 cfg.mComment = mLayer->fields().at( mAttributeTypeDialog->fieldIdx() ).comment();
318 cfg.mEditable = mAttributeTypeDialog->fieldEditable();
319 cfg.mLabelOnTop = mAttributeTypeDialog->labelOnTop();
320 cfg.mReuseLastValues = mAttributeTypeDialog->reuseLastValues();
321 cfg.mAlias = mAttributeTypeDialog->alias();
322 cfg.mDataDefinedProperties = mAttributeTypeDialog->dataDefinedProperties();
323
324 QgsFieldConstraints constraints;
325 if ( mAttributeTypeDialog->notNull() )
326 {
328 }
329 else if ( mAttributeTypeDialog->notNullFromProvider() )
330 {
332 }
333
334 if ( mAttributeTypeDialog->unique() )
335 {
337 }
338 else if ( mAttributeTypeDialog->uniqueFromProvider() )
339 {
341 }
342
343 if ( !mAttributeTypeDialog->constraintExpression().isEmpty() )
344 {
346 }
347
348 constraints.setConstraintExpression( mAttributeTypeDialog->constraintExpression(), mAttributeTypeDialog->constraintExpressionDescription() );
349
354 constraints.setConstraintStrength( QgsFieldConstraints::ConstraintExpression, mAttributeTypeDialog->constraintExpressionEnforced() ?
356
357 cfg.mFieldConstraints = constraints;
358
359 mLayer->setDefaultValueDefinition( mAttributeTypeDialog->fieldIdx(), QgsDefaultValue( mAttributeTypeDialog->defaultValueExpression(), mAttributeTypeDialog->applyDefaultValueOnUpdate() ) );
360
361 cfg.mEditorWidgetType = mAttributeTypeDialog->editorWidgetType();
362 cfg.mEditorWidgetConfig = mAttributeTypeDialog->editorWidgetConfig();
363
364 const QString fieldName = mLayer->fields().at( mAttributeTypeDialog->fieldIdx() ).name();
365
366 for ( auto itemIt = QTreeWidgetItemIterator( mAvailableWidgetsTree ); *itemIt; ++itemIt )
367 {
368 QTreeWidgetItem *item = *itemIt;
369 if ( item->data( 0, FieldNameRole ).toString() == fieldName )
370 item->setData( 0, FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
371 }
372}
373
374void QgsAttributesFormProperties::storeAttributeWidgetEdit()
375{
377 return;
378
379 mAttributeWidgetEdit->updateItemData();
380}
381
382void QgsAttributesFormProperties::loadAttributeWidgetEdit()
383{
384 if ( mFormLayoutTree->selectedItems().count() != 1 )
385 return;
386
387 QTreeWidgetItem *currentItem = mFormLayoutTree->selectedItems().at( 0 );
388 mAttributeWidgetEdit = new QgsAttributeWidgetEdit( currentItem, this );
389 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
390 mAttributeTypeFrame->layout()->addWidget( mAttributeWidgetEdit );
391}
392
393void QgsAttributesFormProperties::loadInfoWidget( const QString &infoText )
394{
395 mInfoTextWidget = new QLabel( infoText );
396 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
397 mAttributeTypeFrame->layout()->addWidget( mInfoTextWidget );
398}
399
400void QgsAttributesFormProperties::storeAttributeContainerEdit()
401{
403 return;
404
405 mAttributeContainerEdit->updateItemData();
406}
407
408void QgsAttributesFormProperties::loadAttributeContainerEdit()
409{
410 if ( mFormLayoutTree->selectedItems().count() != 1 )
411 return;
412
413 QTreeWidgetItem *currentItem = mFormLayoutTree->selectedItems().at( 0 );
414 mAttributeContainerEdit = new QgsAttributeFormContainerEdit( currentItem, mLayer, this );
415 mAttributeContainerEdit->registerExpressionContextGenerator( this );
416 mAttributeContainerEdit->layout()->setContentsMargins( 0, 0, 0, 0 );
417 mAttributeTypeFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
418 mAttributeTypeFrame->layout()->addWidget( mAttributeContainerEdit );
419
420}
421
422QTreeWidgetItem *QgsAttributesFormProperties::loadAttributeEditorTreeItem( QgsAttributeEditorElement *const widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree )
423{
424 QTreeWidgetItem *newWidget = nullptr;
425 switch ( widgetDef->type() )
426 {
428 {
429 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Field, widgetDef->name(), widgetDef->name() );
430 itemData.setShowLabel( widgetDef->showLabel() );
431 itemData.setLabelStyle( widgetDef->labelStyle() );
432 newWidget = tree->addItem( parent, itemData );
433 break;
434 }
435
437 {
438 const QgsAttributeEditorAction *actionEditor = static_cast<const QgsAttributeEditorAction *>( widgetDef );
439 const QgsAction action { actionEditor->action( mLayer ) };
440 if ( action.isValid() )
441 {
442 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
443 itemData.setShowLabel( widgetDef->showLabel() );
444 itemData.setLabelStyle( widgetDef->labelStyle() );
445 newWidget = tree->addItem( parent, itemData );
446 }
447 else
448 {
449 QgsDebugMsg( QStringLiteral( "Invalid form action" ) );
450 }
451 break;
452 }
453
455 {
456 const QgsAttributeEditorRelation *relationEditor = static_cast<const QgsAttributeEditorRelation *>( widgetDef );
457 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Relation, relationEditor->relation().id(), relationEditor->relation().name() );
458 itemData.setShowLabel( widgetDef->showLabel() );
459 itemData.setLabelStyle( widgetDef->labelStyle() );
460
461 RelationEditorConfiguration relEdConfig;
462// relEdConfig.buttons = relationEditor->visibleButtons();
463 relEdConfig.mRelationWidgetType = relationEditor->relationWidgetTypeId();
464 relEdConfig.mRelationWidgetConfig = relationEditor->relationEditorConfiguration();
465 relEdConfig.nmRelationId = relationEditor->nmRelationId();
466 relEdConfig.forceSuppressFormPopup = relationEditor->forceSuppressFormPopup();
467 relEdConfig.label = relationEditor->label();
468 itemData.setRelationEditorConfiguration( relEdConfig );
469 newWidget = tree->addItem( parent, itemData );
470 break;
471 }
472
474 {
475 DnDTreeItemData itemData( DnDTreeItemData::Container, widgetDef->name(), widgetDef->name() );
476 itemData.setShowLabel( widgetDef->showLabel() );
477
478 const QgsAttributeEditorContainer *container = static_cast<const QgsAttributeEditorContainer *>( widgetDef );
479 if ( !container )
480 break;
481
482 itemData.setColumnCount( container->columnCount() );
483 itemData.setShowAsGroupBox( container->isGroupBox() );
484 itemData.setBackgroundColor( container->backgroundColor() );
485 itemData.setVisibilityExpression( container->visibilityExpression() );
486 itemData.setCollapsedExpression( container->collapsedExpression() );
487 itemData.setCollapsed( container->collapsed() );
488 itemData.setLabelStyle( widgetDef->labelStyle() );
489 newWidget = tree->addItem( parent, itemData );
490
491 const QList<QgsAttributeEditorElement *> children = container->children();
492 for ( QgsAttributeEditorElement *wdg : children )
493 {
494 loadAttributeEditorTreeItem( wdg, newWidget, tree );
495 }
496 break;
497 }
498
500 {
501 const QgsAttributeEditorQmlElement *qmlElementEditor = static_cast<const QgsAttributeEditorQmlElement *>( widgetDef );
502 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::QmlWidget, widgetDef->name(), widgetDef->name() );
503 itemData.setShowLabel( widgetDef->showLabel() );
504 QmlElementEditorConfiguration qmlEdConfig;
505 qmlEdConfig.qmlCode = qmlElementEditor->qmlCode();
506 itemData.setQmlElementEditorConfiguration( qmlEdConfig );
507 itemData.setLabelStyle( widgetDef->labelStyle() );
508 newWidget = tree->addItem( parent, itemData );
509 break;
510 }
511
513 {
514 const QgsAttributeEditorHtmlElement *htmlElementEditor = static_cast<const QgsAttributeEditorHtmlElement *>( widgetDef );
515 DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::HtmlWidget, widgetDef->name(), widgetDef->name() );
516 itemData.setShowLabel( widgetDef->showLabel() );
517 HtmlElementEditorConfiguration htmlEdConfig;
518 htmlEdConfig.htmlCode = htmlElementEditor->htmlCode();
519 itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
520 itemData.setLabelStyle( widgetDef->labelStyle() );
521 newWidget = tree->addItem( parent, itemData );
522 break;
523 }
524
526 {
527 QgsDebugMsg( QStringLiteral( "Not loading invalid attribute editor type..." ) );
528 break;
529 }
530 }
531
532 return newWidget;
533}
534
535
536void QgsAttributesFormProperties::onAttributeSelectionChanged()
537{
538 disconnect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
539 loadAttributeSpecificEditor( mAvailableWidgetsTree, mFormLayoutTree );
540 connect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
541}
542
543void QgsAttributesFormProperties::onFormLayoutSelectionChanged()
544{
545 // when the selection changes in the DnD layout, sync the main tree
546 disconnect( mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
547 loadAttributeSpecificEditor( mFormLayoutTree, mAvailableWidgetsTree );
548 connect( mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
549}
550
551void QgsAttributesFormProperties::loadAttributeSpecificEditor( QgsAttributesDnDTree *emitter, QgsAttributesDnDTree *receiver )
552{
553 const QgsEditFormConfig::EditorLayout layout = mEditorLayoutComboBox->currentData().value<QgsEditFormConfig::EditorLayout>();
554
556 storeAttributeWidgetEdit();
557 storeAttributeTypeDialog();
558 storeAttributeContainerEdit();
559
560 clearAttributeTypeFrame();
561
562 if ( emitter->selectedItems().count() != 1 )
563 {
564 receiver->clearSelection();
565 }
566 else
567 {
568 const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
569 switch ( itemData.type() )
570 {
572 {
573 receiver->selectFirstMatchingItem( itemData );
575 {
576 loadAttributeWidgetEdit();
577 }
578 else
579 {
580 loadInfoWidget( tr( "This configuration is available in the Drag and Drop Designer" ) );
581 }
582 break;
583 }
585 {
586 receiver->selectFirstMatchingItem( itemData );
588 loadAttributeWidgetEdit();
589 loadAttributeTypeDialog();
590 break;
591 }
593 {
594 receiver->clearSelection();
595 loadAttributeContainerEdit();
596 break;
597 }
599 {
600 receiver->selectFirstMatchingItem( itemData );
601 const QgsAction action {mLayer->actions()->action( itemData.name() )};
602 loadInfoWidget( action.html() );
603 break;
604 }
607 {
609 {
610 loadInfoWidget( tr( "This configuration is available with double-click in the Drag and Drop Designer" ) );
611 }
612 else
613 {
614 loadInfoWidget( tr( "This configuration is available with double-click" ) );
615 }
616 receiver->clearSelection();
617 break;
618 }
620 {
621 receiver->clearSelection();
622 break;
623 }
624 }
625 }
626}
627
628void QgsAttributesFormProperties::clearAttributeTypeFrame()
629{
631 {
632 mAttributeTypeFrame->layout()->removeWidget( mAttributeWidgetEdit );
633 mAttributeWidgetEdit->deleteLater();
634 mAttributeWidgetEdit = nullptr;
635 }
637 {
638 mAttributeTypeFrame->layout()->removeWidget( mAttributeTypeDialog );
639 mAttributeTypeDialog->deleteLater();
640 mAttributeTypeDialog = nullptr;
641 }
643 {
644 mAttributeTypeFrame->layout()->removeWidget( mAttributeContainerEdit );
645 mAttributeContainerEdit->deleteLater();
646 mAttributeContainerEdit = nullptr;
647 }
648 if ( mInfoTextWidget )
649 {
650 mAttributeTypeFrame->layout()->removeWidget( mInfoTextWidget );
651 mInfoTextWidget->deleteLater();
652 mInfoTextWidget = nullptr;
653 }
654}
655
656void QgsAttributesFormProperties::onInvertSelectionButtonClicked( bool checked )
657{
658 Q_UNUSED( checked )
659 const auto selectedItemList { mFormLayoutTree->selectedItems() };
660 const auto rootItem { mFormLayoutTree->invisibleRootItem() };
661 for ( int i = 0; i < rootItem->childCount(); ++i )
662 {
663 rootItem->child( i )->setSelected( ! selectedItemList.contains( rootItem->child( i ) ) );
664 }
665}
666
667void QgsAttributesFormProperties::addTabOrGroupButton()
668{
669 QList<QgsAddTabOrGroup::TabPair> tabList;
670
671 for ( QTreeWidgetItemIterator it( mFormLayoutTree ); *it; ++it )
672 {
673 const DnDTreeItemData itemData = ( *it )->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
674 if ( itemData.type() == DnDTreeItemData::Container )
675 {
676 tabList.append( QgsAddTabOrGroup::TabPair( itemData.name(), *it ) );
677 }
678 }
679 QTreeWidgetItem *currentItem = mFormLayoutTree->selectedItems().value( 0 );
680 QgsAddTabOrGroup addTabOrGroup( mLayer, tabList, currentItem, this );
681
682 if ( !addTabOrGroup.exec() )
683 return;
684
685 const QString name = addTabOrGroup.name();
686 if ( addTabOrGroup.tabButtonIsChecked() )
687 {
688 mFormLayoutTree->addContainer( mFormLayoutTree->invisibleRootItem(), name, addTabOrGroup.columnCount() );
689 }
690 else
691 {
692 QTreeWidgetItem *tabItem = addTabOrGroup.tab();
693 mFormLayoutTree->addContainer( tabItem, name, addTabOrGroup.columnCount() );
694 }
695}
696
697void QgsAttributesFormProperties::removeTabOrGroupButton()
698{
699 // deleting an item may delete any number of nested child items -- so we delete
700 // them one at a time and then see if there's any selection left
701 while ( true )
702 {
703 const QList<QTreeWidgetItem *> items = mFormLayoutTree->selectedItems();
704 if ( items.empty() )
705 break;
706
707 delete items.at( 0 );
708 }
709
710}
711
712
714{
715 QgsAttributeEditorElement *widgetDef = nullptr;
716
717 const DnDTreeItemData itemData = item->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
718
719 switch ( itemData.type() )
720 {
721 //indexed here?
723 {
724 const int idx = mLayer->fields().lookupField( itemData.name() );
725 widgetDef = new QgsAttributeEditorField( itemData.name(), idx, parent );
726 break;
727 }
728
730 {
731 const QgsAction action { mLayer->actions()->action( itemData.name() )};
732 widgetDef = new QgsAttributeEditorAction( action, parent );
733 break;
734 }
735
737 {
738 const QgsRelation relation = QgsProject::instance()->relationManager()->relation( itemData.name() );
739 QgsAttributeEditorRelation *relDef = new QgsAttributeEditorRelation( relation, parent );
741 relDef->setRelationWidgetTypeId( relationEditorConfig.mRelationWidgetType );
742 relDef->setRelationEditorConfiguration( relationEditorConfig.mRelationWidgetConfig );
743 relDef->setNmRelationId( relationEditorConfig.nmRelationId );
744 relDef->setForceSuppressFormPopup( relationEditorConfig.forceSuppressFormPopup );
745 relDef->setLabel( relationEditorConfig.label );
746 widgetDef = relDef;
747 break;
748 }
749
751 {
752 QgsAttributeEditorContainer *container = new QgsAttributeEditorContainer( item->text( 0 ), parent, itemData.backgroundColor() );
753 container->setColumnCount( itemData.columnCount() );
754 container->setIsGroupBox( forceGroup ? true : itemData.showAsGroupBox() );
755 container->setCollapsed( itemData.collapsed() );
756 container->setCollapsedExpression( itemData.collapsedExpression() );
757 container->setVisibilityExpression( itemData.visibilityExpression() );
758 container->setBackgroundColor( itemData.backgroundColor( ) );
759
760 for ( int t = 0; t < item->childCount(); t++ )
761 {
762 QgsAttributeEditorElement *element { createAttributeEditorWidget( item->child( t ), container ) };
763 if ( element )
764 container->addChildElement( element );
765 }
766
767 widgetDef = container;
768 break;
769 }
770
772 {
773 QgsAttributeEditorQmlElement *element = new QgsAttributeEditorQmlElement( item->text( 0 ), parent );
774 element->setQmlCode( itemData.qmlElementEditorConfiguration().qmlCode );
775 widgetDef = element;
776 break;
777 }
778
780 {
781 QgsAttributeEditorHtmlElement *element = new QgsAttributeEditorHtmlElement( item->text( 0 ), parent );
783 widgetDef = element;
784 break;
785 }
786
788 break;
789
790 }
791
792 if ( widgetDef )
793 {
794 widgetDef->setShowLabel( itemData.showLabel() );
795 widgetDef->setLabelStyle( itemData.labelStyle() );
796 }
797
798 return widgetDef;
799}
800
801void QgsAttributesFormProperties::mEditorLayoutComboBox_currentIndexChanged( int index )
802{
803 Q_UNUSED( index )
804
805 const QgsEditFormConfig::EditorLayout layout = mEditorLayoutComboBox->currentData().value<QgsEditFormConfig::EditorLayout>();
806 switch ( layout )
807 {
809 mFormLayoutWidget->setVisible( false );
810 mUiFileFrame->setVisible( false );
811 mAddTabOrGroupButton->setVisible( false );
812 mRemoveTabOrGroupButton->setVisible( false );
813 mInvertSelectionButton->setVisible( false );
814 break;
815
817 mFormLayoutWidget->setVisible( true );
818 mUiFileFrame->setVisible( false );
819 mAddTabOrGroupButton->setVisible( true );
820 mRemoveTabOrGroupButton->setVisible( true );
821 mInvertSelectionButton->setVisible( true );
822 break;
823
825 // ui file
826 mFormLayoutWidget->setVisible( false );
827 mUiFileFrame->setVisible( true );
828 mAddTabOrGroupButton->setVisible( false );
829 mRemoveTabOrGroupButton->setVisible( false );
830 mInvertSelectionButton->setVisible( false );
831 break;
832 }
833}
834
835void QgsAttributesFormProperties::mTbInitCode_clicked()
836{
837 QgsAttributesFormInitCode attributesFormInitCode;
838
839 attributesFormInitCode.setCodeSource( mInitCodeSource );
840 attributesFormInitCode.setInitCode( mInitCode );
841 attributesFormInitCode.setInitFilePath( mInitFilePath );
842 attributesFormInitCode.setInitFunction( mInitFunction );
843
844 if ( !attributesFormInitCode.exec() )
845 return;
846
847 mInitCodeSource = attributesFormInitCode.codeSource();
848 mInitCode = attributesFormInitCode.initCode();
849 mInitFilePath = attributesFormInitCode.initFilePath();
850 mInitFunction = attributesFormInitCode.initFunction();
851
852}
853
854void QgsAttributesFormProperties::pbnSelectEditForm_clicked()
855{
856 QgsSettings myQSettings;
857 const QString lastUsedDir = myQSettings.value( QStringLiteral( "style/lastUIDir" ), QDir::homePath() ).toString();
858 const QString uifilename = QFileDialog::getOpenFileName( this, tr( "Select edit form" ), lastUsedDir, tr( "UI file" ) + " (*.ui)" );
859
860 if ( uifilename.isNull() )
861 return;
862
863 const QFileInfo fi( uifilename );
864 myQSettings.setValue( QStringLiteral( "style/lastUIDir" ), fi.path() );
865 mEditFormLineEdit->setText( uifilename );
866}
867
869{
870 storeAttributeWidgetEdit();
871 storeAttributeContainerEdit();
872 storeAttributeTypeDialog();
873
874 QgsEditFormConfig editFormConfig = mLayer->editFormConfig();
875
876 QTreeWidgetItem *fieldContainer = mAvailableWidgetsTree->invisibleRootItem()->child( 0 );
877
878 for ( int i = 0; i < fieldContainer->childCount(); i++ )
879 {
880 QTreeWidgetItem *fieldItem = fieldContainer->child( i );
881 const FieldConfig cfg = fieldItem->data( 0, FieldConfigRole ).value<FieldConfig>();
882
883 const QString fieldName { fieldItem->data( 0, FieldNameRole ).toString() };
884 const int idx = mLayer->fields().indexOf( fieldName );
885
886 //continue in case field does not exist anymore
887 if ( idx < 0 )
888 continue;
889
890 editFormConfig.setReadOnly( idx, !cfg.mEditable );
891 editFormConfig.setLabelOnTop( idx, cfg.mLabelOnTop );
892 editFormConfig.setReuseLastValue( idx, cfg.mReuseLastValues );
893
894 if ( cfg.mDataDefinedProperties.count() > 0 )
895 {
896 editFormConfig.setDataDefinedFieldProperties( fieldName, cfg.mDataDefinedProperties );
897 }
898
900
901 const QgsFieldConstraints constraints = cfg.mFieldConstraints;
902 mLayer->setConstraintExpression( idx, constraints.constraintExpression(), constraints.constraintDescription() );
904 {
906 }
907 else
908 {
910 }
912 {
914 }
915 else
916 {
918 }
920 {
922 }
923 else
924 {
926 }
927
928 mLayer->setFieldAlias( idx, cfg.mAlias );
929 }
930
931 // tabs and groups
932 editFormConfig.clearTabs();
933 for ( int t = 0; t < mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
934 {
935 QTreeWidgetItem *tabItem = mFormLayoutTree->invisibleRootItem()->child( t );
936 QgsAttributeEditorElement *editorElement { createAttributeEditorWidget( tabItem, nullptr, false ) };
937 if ( editorElement )
938 editFormConfig.addTab( editorElement );
939 }
940
941 editFormConfig.setUiForm( mEditFormLineEdit->text() );
942
943 editFormConfig.setLayout( static_cast<QgsEditFormConfig::EditorLayout>( mEditorLayoutComboBox->currentIndex() ) );
944
945 editFormConfig.setInitCodeSource( mInitCodeSource );
946 editFormConfig.setInitFunction( mInitFunction );
947 editFormConfig.setInitFilePath( mInitFilePath );
948 editFormConfig.setInitCode( mInitCode );
949
950 editFormConfig.setSuppress( static_cast<QgsEditFormConfig::FeatureFormSuppress>( mFormSuppressCmbBx->currentIndex() ) );
951
952 // write the legacy config of relation widgets to support settings read by the API
953 QTreeWidgetItem *relationContainer = mAvailableWidgetsTree->invisibleRootItem()->child( 1 );
954
955 for ( int i = 0; i < relationContainer->childCount(); i++ )
956 {
957 QTreeWidgetItem *relationItem = relationContainer->child( i );
958 const DnDTreeItemData itemData = relationItem->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
959
960 for ( int t = 0; t < mFormLayoutTree->invisibleRootItem()->childCount(); t++ )
961 {
962 QTreeWidgetItem *tabItem = mFormLayoutTree->invisibleRootItem()->child( t );
963 const DnDTreeItemData tabItemData = tabItem->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
964
965 if ( tabItemData.type() == itemData.type() && tabItemData.name() == itemData.name() )
966 {
967 QVariantMap cfg;
968
969 cfg[QStringLiteral( "nm-rel" )] = tabItemData.relationEditorConfiguration().nmRelationId;
970 cfg[QStringLiteral( "force-suppress-popup" )] = tabItemData.relationEditorConfiguration().forceSuppressFormPopup;
971
972 editFormConfig.setWidgetConfig( tabItemData.name(), cfg );
973 break;
974 }
975 }
976 }
977
978 mLayer->setEditFormConfig( editFormConfig );
979}
980
981
982/*
983 * FieldConfig implementation
984 */
986{
987 mAlias = layer->fields().at( idx ).alias();
989 mComment = layer->fields().at( idx ).comment();
990 mEditable = !layer->editFormConfig().readOnly( idx );
992 && layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression;
993 mLabelOnTop = layer->editFormConfig().labelOnTop( idx );
995 mFieldConstraints = layer->fields().at( idx ).constraints();
996 const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( layer, layer->fields().field( idx ).name() );
997 mEditorWidgetType = setup.type();
998 mEditorWidgetConfig = setup.config();
999}
1000
1001QgsAttributesFormProperties::FieldConfig::operator QVariant()
1002{
1003 return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *this );
1004}
1005
1006/*
1007 * RelationEditorConfiguration implementation
1008 */
1009
1010QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
1011{
1012 return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *this );
1013}
1014
1015/*
1016 * DnDTree implementation
1017 */
1018
1019QTreeWidgetItem *QgsAttributesDnDTree::addContainer( QTreeWidgetItem *parent, const QString &title, int columnCount )
1020{
1021 QTreeWidgetItem *newItem = new QTreeWidgetItem( QStringList() << title );
1022 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1023 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1025 itemData.setColumnCount( columnCount );
1026 newItem->setData( 0, QgsAttributesFormProperties::DnDTreeRole, itemData );
1027 parent->addChild( newItem );
1028 newItem->setExpanded( true );
1029 return newItem;
1030}
1031
1033 : QTreeWidget( parent )
1034 , mLayer( layer )
1035{
1036 connect( this, &QTreeWidget::itemDoubleClicked, this, &QgsAttributesDnDTree::onItemDoubleClicked );
1037}
1038
1039QTreeWidgetItem *QgsAttributesDnDTree::addItem( QTreeWidgetItem *parent, QgsAttributesFormProperties::DnDTreeItemData data, int index, const QIcon &icon )
1040{
1041 QTreeWidgetItem *newItem = new QTreeWidgetItem( QStringList() << data.name() );
1042
1043 switch ( data.type() )
1044 {
1050 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1051 break;
1052
1055 {
1056 newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
1057 newItem->setBackground( 0, QBrush( Qt::lightGray ) );
1058 }
1059 break;
1060 }
1061
1062 newItem->setData( 0, QgsAttributesFormProperties::DnDTreeRole, data );
1063 newItem->setText( 0, data.displayName() );
1064 newItem->setIcon( 0, icon );
1065
1066 if ( index < 0 )
1067 parent->addChild( newItem );
1068 else
1069 parent->insertChild( index, newItem );
1070
1071 return newItem;
1072}
1073
1079void QgsAttributesDnDTree::dragMoveEvent( QDragMoveEvent *event )
1080{
1081 const QMimeData *data = event->mimeData();
1082
1083 if ( data->hasFormat( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) ) )
1084 {
1086
1087 QByteArray itemData = data->data( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) );
1088 QDataStream stream( &itemData, QIODevice::ReadOnly );
1089 stream >> itemElement;
1090
1091 // Inner drag and drop actions are always MoveAction
1092 if ( event->source() == this )
1093 {
1094 event->setDropAction( Qt::MoveAction );
1095 }
1096 }
1097 else
1098 {
1099 event->ignore();
1100 }
1101
1102 QTreeWidget::dragMoveEvent( event );
1103}
1104
1105
1106bool QgsAttributesDnDTree::dropMimeData( QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action )
1107{
1108 bool bDropSuccessful = false;
1109
1110 if ( action == Qt::IgnoreAction )
1111 {
1112 bDropSuccessful = true;
1113 }
1114 else if ( data->hasFormat( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) ) )
1115 {
1116 QByteArray itemData = data->data( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) );
1117 QDataStream stream( &itemData, QIODevice::ReadOnly );
1119
1120 while ( !stream.atEnd() )
1121 {
1122 stream >> itemElement;
1123
1124 QTreeWidgetItem *newItem;
1125
1126 if ( parent )
1127 {
1128 newItem = addItem( parent, itemElement, index++ );
1129 bDropSuccessful = true;
1130 }
1131 else
1132 {
1133 newItem = addItem( invisibleRootItem(), itemElement, index++ );
1134 bDropSuccessful = true;
1135 }
1136
1138 {
1139 onItemDoubleClicked( newItem, 0 );
1140 }
1141
1143 {
1144 onItemDoubleClicked( newItem, 0 );
1145 }
1146 clearSelection();
1147 newItem->setSelected( true );
1148 }
1149 }
1150
1151 return bDropSuccessful;
1152}
1153
1154void QgsAttributesDnDTree::dropEvent( QDropEvent *event )
1155{
1156 if ( !event->mimeData()->hasFormat( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) ) )
1157 return;
1158
1159 if ( event->source() == this )
1160 {
1161 event->setDropAction( Qt::MoveAction );
1162 }
1163
1164 QTreeWidget::dropEvent( event );
1165}
1166
1168{
1169 return QStringList() << QStringLiteral( "application/x-qgsattributetabledesignerelement" );
1170}
1171
1172#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1173QMimeData *QgsAttributesDnDTree::mimeData( const QList<QTreeWidgetItem *> items ) const
1174#else
1175QMimeData *QgsAttributesDnDTree::mimeData( const QList<QTreeWidgetItem *> &items ) const
1176#endif
1177{
1178 if ( items.count() <= 0 )
1179 return nullptr;
1180
1181 const QStringList types = mimeTypes();
1182
1183 if ( types.isEmpty() )
1184 return nullptr;
1185
1186 QMimeData *data = new QMimeData();
1187 const QString format = types.at( 0 );
1188 QByteArray encoded;
1189 QDataStream stream( &encoded, QIODevice::WriteOnly );
1190
1191 const auto constItems = items;
1192 for ( const QTreeWidgetItem *item : constItems )
1193 {
1194 if ( item )
1195 {
1196 // Relevant information is always in the DnDTreeRole of the first column
1198 stream << itemData;
1199 }
1200 }
1201
1202 data->setData( format, encoded );
1203
1204 return data;
1205}
1206
1207void QgsAttributesDnDTree::onItemDoubleClicked( QTreeWidgetItem *item, int column )
1208{
1209 Q_UNUSED( column )
1210
1212
1213 QGroupBox *baseData = new QGroupBox( tr( "Base configuration" ) );
1214
1215 QFormLayout *baseLayout = new QFormLayout();
1216 baseData->setLayout( baseLayout );
1217 QCheckBox *showLabelCheckbox = new QCheckBox( QStringLiteral( "Show label" ) );
1218 showLabelCheckbox->setChecked( itemData.showLabel() );
1219 baseLayout->addRow( showLabelCheckbox );
1220 QWidget *baseWidget = new QWidget();
1221 baseWidget->setLayout( baseLayout );
1222
1223 switch ( itemData.type() )
1224 {
1230 break;
1231
1233 {
1234 if ( mType == QgsAttributesDnDTree::Type::Drag )
1235 return;
1236
1237 QDialog dlg;
1238 dlg.setWindowTitle( tr( "Configure QML Widget" ) );
1239
1240 QVBoxLayout *mainLayout = new QVBoxLayout();
1241 QHBoxLayout *qmlLayout = new QHBoxLayout();
1242 QVBoxLayout *layout = new QVBoxLayout();
1243 mainLayout->addLayout( qmlLayout );
1244 qmlLayout->addLayout( layout );
1245 dlg.setLayout( mainLayout );
1246 layout->addWidget( baseWidget );
1247
1248 QLineEdit *title = new QLineEdit( itemData.name() );
1249
1250 //qmlCode
1251 QPlainTextEdit *qmlCode = new QPlainTextEdit( itemData.qmlElementEditorConfiguration().qmlCode );
1252 qmlCode->setPlaceholderText( tr( "Insert QML code here…" ) );
1253
1254 QgsQmlWidgetWrapper *qmlWrapper = new QgsQmlWidgetWrapper( mLayer, nullptr, this );
1255 QgsFeature previewFeature;
1256 mLayer->getFeatures().nextFeature( previewFeature );
1257
1258 //update preview on text change
1259 connect( qmlCode, &QPlainTextEdit::textChanged, this, [ = ]
1260 {
1261 qmlWrapper->setQmlCode( qmlCode->toPlainText() );
1262 qmlWrapper->reinitWidget();
1263 qmlWrapper->setFeature( previewFeature );
1264 } );
1265
1266 //templates
1267 QComboBox *qmlObjectTemplate = new QComboBox();
1268 qmlObjectTemplate->addItem( tr( "Free Text…" ) );
1269 qmlObjectTemplate->addItem( tr( "Rectangle" ) );
1270 qmlObjectTemplate->addItem( tr( "Pie Chart" ) );
1271 qmlObjectTemplate->addItem( tr( "Bar Chart" ) );
1272 connect( qmlObjectTemplate, qOverload<int>( &QComboBox::activated ), qmlCode, [ = ]( int index )
1273 {
1274 qmlCode->clear();
1275 switch ( index )
1276 {
1277 case 0:
1278 {
1279 qmlCode->setPlaceholderText( tr( "Insert QML code here…" ) );
1280 break;
1281 }
1282 case 1:
1283 {
1284 qmlCode->insertPlainText( QStringLiteral( "import QtQuick 2.0\n"
1285 "\n"
1286 "Rectangle {\n"
1287 " width: 100\n"
1288 " height: 100\n"
1289 " color: \"steelblue\"\n"
1290 " Text{ text: \"A rectangle\" }\n"
1291 "}\n" ) );
1292 break;
1293 }
1294 case 2:
1295 {
1296 qmlCode->insertPlainText( QStringLiteral( "import QtQuick 2.0\n"
1297 "import QtCharts 2.0\n"
1298 "\n"
1299 "ChartView {\n"
1300 " width: 400\n"
1301 " height: 400\n"
1302 "\n"
1303 " PieSeries {\n"
1304 " id: pieSeries\n"
1305 " PieSlice { label: \"First slice\"; value: 25 }\n"
1306 " PieSlice { label: \"Second slice\"; value: 45 }\n"
1307 " PieSlice { label: \"Third slice\"; value: 30 }\n"
1308 " }\n"
1309 "}\n" ) );
1310 break;
1311 }
1312 case 3:
1313 {
1314 qmlCode->insertPlainText( QStringLiteral( "import QtQuick 2.0\n"
1315 "import QtCharts 2.0\n"
1316 "\n"
1317 "ChartView {\n"
1318 " title: \"Bar series\"\n"
1319 " width: 600\n"
1320 " height:400\n"
1321 " legend.alignment: Qt.AlignBottom\n"
1322 " antialiasing: true\n"
1323 " ValueAxis{\n"
1324 " id: valueAxisY\n"
1325 " min: 0\n"
1326 " max: 15\n"
1327 " }\n"
1328 "\n"
1329 " BarSeries {\n"
1330 " id: mySeries\n"
1331 " axisY: valueAxisY\n"
1332 " axisX: BarCategoryAxis { categories: [\"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\" ] }\n"
1333 " BarSet { label: \"Bob\"; values: [2, 2, 3, 4, 5, 6] }\n"
1334 " BarSet { label: \"Susan\"; values: [5, 1, 2, 4, 1, 7] }\n"
1335 " BarSet { label: \"James\"; values: [3, 5, 8, 13, 5, 8] }\n"
1336 " }\n"
1337 "}\n" ) );
1338 break;
1339 }
1340 default:
1341 break;
1342 }
1343 } );
1344
1345 QgsFieldExpressionWidget *expressionWidget = new QgsFieldExpressionWidget;
1346 expressionWidget->setLayer( mLayer );
1347 QToolButton *addExpressionButton = new QToolButton();
1348 addExpressionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
1349
1350 connect( addExpressionButton, &QAbstractButton::clicked, this, [ = ]
1351 {
1352 qmlCode->insertPlainText( QStringLiteral( "expression.evaluate(\"%1\")" ).arg( expressionWidget->expression().replace( '"', QLatin1String( "\\\"" ) ) ) );
1353 } );
1354
1355 layout->addWidget( new QLabel( tr( "Title" ) ) );
1356 layout->addWidget( title );
1357 QGroupBox *qmlCodeBox = new QGroupBox( tr( "QML Code" ) );
1358 qmlCodeBox->setLayout( new QGridLayout );
1359 qmlCodeBox->layout()->addWidget( qmlObjectTemplate );
1360 QGroupBox *expressionWidgetBox = new QGroupBox();
1361 qmlCodeBox->layout()->addWidget( expressionWidgetBox );
1362 expressionWidgetBox->setLayout( new QHBoxLayout );
1363 expressionWidgetBox->layout()->addWidget( expressionWidget );
1364 expressionWidgetBox->layout()->addWidget( addExpressionButton );
1365 qmlCodeBox->layout()->addWidget( qmlCode );
1366 layout->addWidget( qmlCodeBox );
1367 QScrollArea *qmlPreviewBox = new QgsScrollArea();
1368 qmlPreviewBox->setLayout( new QGridLayout );
1369 qmlPreviewBox->setMinimumWidth( 400 );
1370 qmlPreviewBox->layout()->addWidget( qmlWrapper->widget() );
1371 //emit to load preview for the first time
1372 emit qmlCode->textChanged();
1373 qmlLayout->addWidget( qmlPreviewBox );
1374
1375 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1376
1377 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1378 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1379
1380 mainLayout->addWidget( buttonBox );
1381
1382 if ( dlg.exec() )
1383 {
1385 qmlEdCfg.qmlCode = qmlCode->toPlainText();
1386 itemData.setName( title->text() );
1387 itemData.setQmlElementEditorConfiguration( qmlEdCfg );
1388 itemData.setShowLabel( showLabelCheckbox->isChecked() );
1389
1390 item->setData( 0, QgsAttributesFormProperties::DnDTreeRole, itemData );
1391 item->setText( 0, title->text() );
1392 }
1393 }
1394 break;
1395
1397 {
1398 if ( mType == QgsAttributesDnDTree::Type::Drag )
1399 return;
1400 QDialog dlg;
1401 dlg.setWindowTitle( tr( "Configure HTML Widget" ) );
1402
1403 QVBoxLayout *mainLayout = new QVBoxLayout();
1404 QHBoxLayout *htmlLayout = new QHBoxLayout();
1405 QVBoxLayout *layout = new QVBoxLayout();
1406 mainLayout->addLayout( htmlLayout );
1407 htmlLayout->addLayout( layout );
1408 dlg.setLayout( mainLayout );
1409 layout->addWidget( baseWidget );
1410
1411 QLineEdit *title = new QLineEdit( itemData.name() );
1412
1413 //htmlCode
1414 QgsCodeEditorHTML *htmlCode = new QgsCodeEditorHTML( );
1415 htmlCode->setSizePolicy( QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding );
1416 htmlCode->setText( itemData.htmlElementEditorConfiguration().htmlCode );
1417
1418 QgsHtmlWidgetWrapper *htmlWrapper = new QgsHtmlWidgetWrapper( mLayer, nullptr, this );
1419 QgsFeature previewFeature;
1420 mLayer->getFeatures().nextFeature( previewFeature );
1421
1422 //update preview on text change
1423 connect( htmlCode, &QgsCodeEditorHTML::textChanged, this, [ = ]
1424 {
1425 htmlWrapper->setHtmlCode( htmlCode->text( ) );
1426 htmlWrapper->reinitWidget();
1427 htmlWrapper->setFeature( previewFeature );
1428 } );
1429
1430 QgsFieldExpressionWidget *expressionWidget = new QgsFieldExpressionWidget;
1431 expressionWidget->setLayer( mLayer );
1432 QToolButton *addExpressionButton = new QToolButton();
1433 addExpressionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
1434
1435 connect( addExpressionButton, &QAbstractButton::clicked, this, [ = ]
1436 {
1437 htmlCode->insertText( QStringLiteral( "<script>document.write(expression.evaluate(\"%1\"));</script>" ).arg( expressionWidget->expression().replace( '"', QLatin1String( "\\\"" ) ) ) );
1438 } );
1439
1440 layout->addWidget( new QLabel( tr( "Title" ) ) );
1441 layout->addWidget( title );
1442 QGroupBox *expressionWidgetBox = new QGroupBox( tr( "HTML Code" ) );
1443 layout->addWidget( expressionWidgetBox );
1444 expressionWidgetBox->setLayout( new QHBoxLayout );
1445 expressionWidgetBox->layout()->addWidget( expressionWidget );
1446 expressionWidgetBox->layout()->addWidget( addExpressionButton );
1447 layout->addWidget( htmlCode );
1448 QScrollArea *htmlPreviewBox = new QgsScrollArea();
1449 htmlPreviewBox->setLayout( new QGridLayout );
1450 htmlPreviewBox->setMinimumWidth( 400 );
1451 htmlPreviewBox->layout()->addWidget( htmlWrapper->widget() );
1452 //emit to load preview for the first time
1453 emit htmlCode->textChanged();
1454 htmlLayout->addWidget( htmlPreviewBox );
1455
1456 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1457
1458 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1459 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1460
1461 mainLayout->addWidget( buttonBox );
1462
1463 if ( dlg.exec() )
1464 {
1466 htmlEdCfg.htmlCode = htmlCode->text();
1467 itemData.setName( title->text() );
1468 itemData.setHtmlElementEditorConfiguration( htmlEdCfg );
1469 itemData.setShowLabel( showLabelCheckbox->isChecked() );
1470
1471 item->setData( 0, QgsAttributesFormProperties::DnDTreeRole, itemData );
1472 item->setText( 0, title->text() );
1473 }
1474 }
1475 break;
1476 }
1477}
1478
1480{
1481 return mType;
1482}
1483
1485{
1486 mType = value;
1487}
1488
1490{
1491 QTreeWidgetItemIterator it( this );
1492 while ( *it )
1493 {
1495 if ( data.type() == rowData.type() && data.name() == rowData.name() )
1496 {
1497 if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
1498 {
1499 // the selection is already good
1500 }
1501 else
1502 {
1503 clearSelection();
1504 ( *it )->setSelected( true );
1505 }
1506 return;
1507 }
1508 ++it;
1509 }
1510 clearSelection();
1511}
1512
1513
1514/*
1515 * Serialization helpers for DesigerTreeItemData so we can stuff this easily into QMimeData
1516 */
1517
1518QDataStream &operator<<( QDataStream &stream, const QgsAttributesFormProperties::DnDTreeItemData &data )
1519{
1520 stream << static_cast<quint32>( data.type() ) << data.name() << data.displayName();
1521 return stream;
1522}
1523
1524QDataStream &operator>>( QDataStream &stream, QgsAttributesFormProperties::DnDTreeItemData &data )
1525{
1526 QString name;
1527 QString displayName;
1528 quint32 type;
1529
1530 stream >> type >> name >> displayName;
1531
1533 data.setName( name );
1534 data.setDisplayName( displayName );
1535
1536 return stream;
1537}
1538
1540{
1541 return mShowAsGroupBox;
1542}
1543
1545{
1546 mShowAsGroupBox = showAsGroupBox;
1547}
1548
1553
1555{
1556 mLabelStyle = labelStyle;
1557}
1558
1560{
1561 return mShowLabel;
1562}
1563
1565{
1566 mShowLabel = showLabel;
1567}
1568
1573
1575{
1576 mVisibilityExpression = visibilityExpression;
1577}
1578
1583
1585{
1586 mCollapsedExpression = collapsedExpression;
1587}
1588
1593
1595{
1596 mRelationEditorConfiguration = relationEditorConfiguration;
1597}
1598
1603
1605{
1606 mQmlElementEditorConfiguration = qmlElementEditorConfiguration;
1607}
1608
1609
1614
1616{
1617 mHtmlElementEditorConfiguration = htmlElementEditorConfiguration;
1618}
1619
1621{
1622 return mBackgroundColor;
1623}
1624
1626{
1627 mBackgroundColor = backgroundColor;
1628}
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.
Definition qgsaction.h:35
Dialog to add a tab or group of attributes.
QPair< QString, QTreeWidgetItem * > TabPair
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.
virtual bool isGroupBox() const
Returns if this container is going to be a group box.
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 if this group box is collapsed.
void setCollapsedExpression(const QgsOptionalExpression &collapsedExpression)
The collapsed expression is used in the attribute form to set the collapsed status of the group box o...
virtual void setIsGroupBox(bool isGroupBox)
Determines if this container is rendered as collapsible group box or tab in a tabwidget.
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
QColor backgroundColor() const
backgroundColor
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.
LabelStyle labelStyle() const
Returns the label style.
void setLabelStyle(const LabelStyle &labelStyle)
Sets the labelStyle.
AttributeEditorType type() const
The type of this 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 setShowLabel(bool showLabel)
Controls if this element should be labeled with a title (field, relation or groupname).
@ AeTypeAction
A layer action element (since QGIS 3.22)
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.
This class overrides mime type handling to be able to work with the drag and drop attribute editor.
void setType(QgsAttributesDnDTree::Type value)
QTreeWidgetItem * addContainer(QTreeWidgetItem *parent, const QString &title, int columnCount)
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
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)
void setCodeSource(QgsEditFormConfig::PythonInitCodeSource initCodeSourceComboBoxIndex)
void setInitFilePath(const QString &initFilePath)
void setInitFunction(const QString &initFunction)
QgsEditFormConfig::PythonInitCodeSource codeSource() const
void setInitCode(const QString &initCode)
void setRelationEditorConfiguration(RelationEditorConfiguration relationEditorConfiguration)
void setLabelStyle(const QgsAttributeEditorElement::LabelStyle &labelStyle)
Sets the label style to labelStyle.
QmlElementEditorConfiguration qmlElementEditorConfiguration() const
void setQmlElementEditorConfiguration(QmlElementEditorConfiguration qmlElementEditorConfiguration)
const QgsAttributeEditorElement::LabelStyle labelStyle() const
Returns the label style.
void setVisibilityExpression(const QgsOptionalExpression &visibilityExpression)
Sets the optional visibilityExpression that dynamically controls the visibility status of a container...
QgsOptionalExpression collapsedExpression() const
Returns the optional expression that dynamically controls the collapsed status of a group box contain...
@ WidgetType
In the widget tree, the type of widget.
void setCollapsedExpression(const QgsOptionalExpression &collapsedExpression)
Sets the optional collapsedExpression that dynamically controls the collapsed status of a group box c...
HtmlElementEditorConfiguration htmlElementEditorConfiguration() const
void setHtmlElementEditorConfiguration(HtmlElementEditorConfiguration htmlElementEditorConfiguration)
bool collapsed() const
For group box containers returns if this group box is collapsed.
RelationEditorConfiguration relationEditorConfiguration() const
QgsAttributeFormContainerEdit * mAttributeContainerEdit
QgsAttributesFormProperties(QgsVectorLayer *layer, QWidget *parent=nullptr)
QgsAttributeTypeDialog * mAttributeTypeDialog
QgsAttributeEditorElement * createAttributeEditorWidget(QTreeWidgetItem *item, QgsAttributeEditorElement *parent, bool forceGroup=true)
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsAttributeWidgetEdit * mAttributeWidgetEdit
A HTML 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.
Contains configuration settings for an editor form.
bool reuseLastValue(int index) const
If this returns true, the widget at the given index will remember the previously entered value from t...
bool readOnly(int idx) const
This returns true if the field is manually set to read only or if the field does not support editing ...
QString initCode() const
Gets Python code for edit form initialization.
void setInitFunction(const QString &function)
Set Python function for edit form initialization.
void addTab(QgsAttributeEditorElement *data)
Adds a new element to the invisible root container in the layout.
QString initFilePath() const
Gets Python external file path for edit form initialization.
void setReadOnly(int idx, bool readOnly=true)
If set to false, the widget at the given index will be read-only.
QgsPropertyCollection dataDefinedFieldProperties(const QString &fieldName) const
Returns data defined properties for fieldName.
EditorLayout
The different types to layout the attribute editor.
@ TabLayout
Use a layout with tabs and group boxes. Needs to be configured.
@ UiFileLayout
Load a .ui file for the layout. Needs to be configured.
@ GeneratedLayout
Autogenerate a simple tabular layout for the form.
FeatureFormSuppress
Types of feature form suppression after feature creation.
FeatureFormSuppress suppress() const
Type of feature form pop-up suppression after feature creation (overrides app setting)
bool setWidgetConfig(const QString &widgetName, const QVariantMap &config)
Set the editor widget config for a widget which is not for a simple field.
void setLayout(EditorLayout editorLayout)
Sets the active layout style for the attribute editor for this layer.
void clearTabs()
Clears all the tabs for the attribute editor form with EditorLayout::TabLayout.
bool labelOnTop(int idx) const
If this returns true, the widget at the given index will receive its label on the previous line while...
QString uiForm() const
Returns the path or URL to the .ui form.
void setLabelOnTop(int idx, bool onTop)
If this is set to true, the widget at the given index will receive its label on the previous line whi...
PythonInitCodeSource initCodeSource() const
Returns Python code source for edit form initialization (if it shall be loaded from a file,...
void setDataDefinedFieldProperties(const QString &fieldName, const QgsPropertyCollection &properties)
Set data defined properties for fieldName to properties.
QString initFunction() const
Gets Python function for edit form initialization.
void setSuppress(FeatureFormSuppress s)
Sets type of feature form pop-up suppression after feature creation (overrides app setting)
QList< QgsAttributeEditorElement * > tabs() const
Returns a list of tabs for EditorLayout::TabLayout obtained from the invisible root container.
void setReuseLastValue(int index, bool reuse)
Sets whether the widget at the given index will remember the previously entered value from this QGIS ...
void setUiForm(const QString &ui)
Set path to the .ui form.
EditorLayout layout() const
Gets the active layout style for the attribute editor for this layer.
void setInitCodeSource(PythonInitCodeSource initCodeSource)
Sets if Python code shall be used for edit form initialization and its origin.
void setInitFilePath(const QString &filePath)
Set Python external file path for edit form initialization.
void setInitCode(const QString &code)
Set Python code for edit form initialization.
QgsEditorWidgetSetup findBest(const QgsVectorLayer *vl, const QString &fieldName) const
Find the best editor widget and its configuration for a given field.
Holder for the widget type and its configuration for a field.
QVariantMap config() const
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool nextFeature(QgsFeature &f)
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
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.
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
void setLayer(QgsMapLayer *layer)
Sets the layer used to display the fields and expression.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:51
QString name
Definition qgsfield.h:60
QString alias
Definition qgsfield.h:61
QString comment
Definition qgsfield.h:59
QgsFieldConstraints constraints
Definition qgsfield.h:63
Container of fields for a vector layer.
Definition qgsfields.h:45
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
@ OriginExpression
Field is calculated from an expression.
Definition qgsfields.h:54
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition qgsfields.h:52
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.
Definition qgsgui.cpp:83
Wraps a QQuickWidget to display HTML code.
void reinitWidget()
Clears the content and makes new initialization.
void setHtmlCode(const QString &htmlCode)
Sets the HTML code to htmlCode.
void setFeature(const QgsFeature &feature) override
An expression with an additional enabled flag.
QgsRelationManager * relationManager
Definition qgsproject.h:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
int count() const
Returns the number of properties contained within the collection.
Wraps a QQuickWidget to display QML code.
void setFeature(const QgsFeature &feature) override
void reinitWidget()
Clears the content and makes new initialization.
void setQmlCode(const QString &qmlCode)
writes the qmlCode into a temporary file
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.
QString name
Definition qgsrelation.h:48
QString id
Definition qgsrelation.h:45
A QScrollArea subclass with improved scrolling behavior.
static const QgsSettingsEntryBool settingsDigitizingDisableEnterAttributeValuesDialog
Settings entry digitizing disable enter attribute values dialog.
This class is a composition of two QSettings instances:
Definition qgssettings.h:62
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.
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
QWidget * widget()
Access the widget managed by this wrapper.
QDataStream & operator>>(QDataStream &stream, QgsAttributesFormProperties::DnDTreeItemData &data)
QDataStream & operator<<(QDataStream &stream, const QgsAttributesFormProperties::DnDTreeItemData &data)
const QgsField & field
Definition qgsfield.h:476
#define QgsDebugMsg(str)
Definition qgslogger.h:38
The TabStyle struct defines color and font overrides for form fields, tabs and groups labels.