QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
Loading...
Searching...
No Matches
qgsabstractrelationeditorwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsabstractrelationeditorwidget.cpp
3 ----------------------
4 begin : October 2020
5 copyright : (C) 2020 by Ivan Ivanov
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "moc_qgsabstractrelationeditorwidget.cpp"
20
21#include "qgsfeatureiterator.h"
22#include "qgsexpression.h"
24#include "qgsfeature.h"
26#include "qgsrelation.h"
27#include "qgsrelationmanager.h"
29#include "qgsvectorlayertools.h"
30#include "qgsproject.h"
31#include "qgstransactiongroup.h"
32#include "qgsvectorlayerutils.h"
33
34#include <QMessageBox>
35#include <QPushButton>
36
37QgsAbstractRelationEditorWidget::QgsAbstractRelationEditorWidget( const QVariantMap &config, QWidget *parent )
38 : QWidget( parent )
39{
40 Q_UNUSED( config );
41}
42
44{
46
48 mFeatureList.clear();
49 mFeatureList.append( feature );
50
51 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
52
54 updateUi();
55}
56
58{
59
60 beforeSetRelations( relation, nmrelation );
61
63 mNmRelation = nmrelation;
64
65 if ( !mRelation.isValid() )
66 {
68 return;
69 }
70
72
73 const auto transactionGroups = QgsProject::instance()->transactionGroups();
74 for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
75 {
76 if ( mNmRelation.isValid() )
77 {
78 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
79 it.value()->layers().contains( mRelation.referencingLayer() ) &&
80 it.value()->layers().contains( mNmRelation.referencedLayer() ) )
82 }
83 else
84 {
85 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
86 it.value()->layers().contains( mRelation.referencingLayer() ) )
88 }
89 }
90
91 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
92
94 updateUi();
95}
96
101
106
108{
109 mFeatureList.clear();
110 mFeatureList.append( feature );
111
113
114 if ( update )
115 updateUi();
116}
117
119{
120 mFeatureList.clear();
121
122 QgsFeatureIterator featureIterator = mRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
124 while ( featureIterator.nextFeature( feature ) )
125 mFeatureList.append( feature );
126
127 if ( ! mFeatureList.isEmpty() )
129}
130
131void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
132{
133 const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
134 beforeSetRelations( mRelation, nmrelation );
135 mNmRelation = nmrelation;
137 updateUi();
138}
139
141{
142 return mNmRelation.id();
143}
144
146{
147 return QString();
148}
149
151{
152 Q_UNUSED( label )
153}
154
156{
157 return false;
158}
159
161{
162 Q_UNUSED( showLabel )
163}
164
169
174
178
180{
181 return mFeatureList.size() > 1;
182}
183
185{
186 if ( !mFeatureList.isEmpty() )
187 return mFeatureList.first();
188
189 return QgsFeature();
190}
191
193{
194 return mFeatureList;
195}
196
212
219
221{
222 QgsAttributeMap keyAttrs;
223
225
226 // Fields of the linking table
227 const QgsFields fields = mRelation.referencingLayer()->fields();
228
229 QgsFeatureIds addedFeatureIds;
230
231 // For generated relations insert the referenced layer field
232 switch ( mRelation.type() )
233 {
235 {
237 keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
238 break;
239 }
240
242 break;
243 }
244
245 if ( mNmRelation.isValid() )
246 {
247 // only normal relations support m:n relation
249
250 // n:m Relation: first let the user create a new feature on the other table
251 // and autocreate a new linking feature.
252 QgsFeature finalFeature;
253 if ( !vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &finalFeature, this, false, true ) )
254 return QgsFeatureIds();
255
256 addedFeatureIds.insert( finalFeature.id() );
257
258 // Expression context for the linking table
260
261 QgsAttributeMap linkAttributes = keyAttrs;
262 const auto constFieldPairs = mRelation.fieldPairs();
263
265 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
266 {
267 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
268 {
269 const int index = fields.indexOf( fieldPair.first );
270 linkAttributes.insert( index, editingFeature.attribute( fieldPair.second ) );
271 }
272
273 const auto constNmFieldPairs = mNmRelation.fieldPairs();
274 for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
275 {
276 const int index = fields.indexOf( fieldPair.first );
277 linkAttributes.insert( index, finalFeature.attribute( fieldPair.second ) );
278 }
279
280 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
281 }
282 QgsFeatureList linkFeatureList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
283 mRelation.referencingLayer()->addFeatures( linkFeatureList );
284 }
285 else
286 {
287 const auto constFieldPairs = mRelation.fieldPairs();
288 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
289 keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeatureList.first().attribute( fieldPair.referencedField() ) );
290
292 context.setParentWidget( this );
293 context.setShowModal( false );
294 context.setHideParent( true );
295 std::unique_ptr<QgsExpressionContextScope> scope( QgsExpressionContextUtils::parentFormScope( mFeatureList.first(), mEditorContext.attributeFormModeString() ) );
296 context.setAdditionalExpressionContextScope( scope.get() );
298 if ( !vlTools->addFeatureV2( mRelation.referencingLayer(), keyAttrs, geometry, &linkFeature, context ) )
299 return QgsFeatureIds();
300
301 addedFeatureIds.insert( linkFeature.id() );
302
303 // In multiedit add to other features to but without dialog
304 for ( const QgsFeature &feature : std::as_const( mFeatureList ) )
305 {
306 // First feature already added
307 if ( mFeatureList.first() == feature )
308 continue;
309
310 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
311 linkFeature.setAttribute( fields.indexFromName( fieldPair.referencingField() ), feature.attribute( fieldPair.referencedField() ) );
312
314 addedFeatureIds.insert( linkFeature.id() );
315 }
316 }
317
318 updateUi();
319
321
322 return addedFeatureIds;
323}
324
331
333{
334 bool deleteFeatures = true;
335
336 QgsVectorLayer *layer;
337 if ( mNmRelation.isValid() )
338 {
339 // only normal relations support m:n relation
341
343
344 // When deleting a linked feature within an N:M relation,
345 // check if the feature is linked to more than just one feature.
346 // In case it is linked more than just once, ask the user for confirmation
347 // as it is likely he was not aware of the implications and might delete
348 // there may be several linking entries deleted along.
349
350 QgsFeatureRequest deletedFeaturesRequest;
351 deletedFeaturesRequest.setFilterFids( fids );
352 deletedFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
353 deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
354
355 QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
356 QStringList deletedFeaturesPks;
358 while ( deletedFeatures.nextFeature( feature ) )
359 {
360 deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
361 }
362
363 QgsFeatureRequest linkingFeaturesRequest;
364 linkingFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
365 linkingFeaturesRequest.setNoAttributes();
366
367 QString linkingFeaturesRequestExpression;
368 if ( !deletedFeaturesPks.empty() )
369 {
370 linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
371 linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
372
373 QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
374
375 int relatedLinkingFeaturesCount = 0;
376 while ( relatedLinkingFeatures.nextFeature( feature ) )
377 {
378 relatedLinkingFeaturesCount++;
379 }
380
381 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
382 {
383 QMessageBox messageBox( QMessageBox::Question, tr( "Really delete entry?" ), tr( "The entry on %1 is still linked to %2 features on %3. Do you want to delete it?" ).arg( mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ), QMessageBox::NoButton, this );
384 messageBox.addButton( QMessageBox::Cancel );
385 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
386
387 messageBox.exec();
388 if ( messageBox.clickedButton() != deleteButton )
389 deleteFeatures = false;
390 }
391 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
392 {
393 QMessageBox messageBox( QMessageBox::Question, tr( "Really delete entries?" ), tr( "The %1 entries on %2 are still linked to %3 features on %4. Do you want to delete them?" ).arg( QLocale().toString( deletedFeaturesPks.size() ), mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ), QMessageBox::NoButton, this );
394 messageBox.addButton( QMessageBox::Cancel );
395 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
396
397 messageBox.exec();
398 if ( messageBox.clickedButton() != deleteButton )
399 deleteFeatures = false;
400 }
401 }
402 }
403 else
404 {
405 layer = mRelation.referencingLayer();
406 }
407
409 if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
410 {
411 QString childrenInfo;
412 int childrenCount = 0;
413 const auto infoContextLayers = infoContext.layers();
414 for ( QgsVectorLayer *chl : infoContextLayers )
415 {
416 childrenCount += infoContext.duplicatedFeatures( chl ).size();
417 childrenInfo += ( tr( "%n feature(s) on layer \"%1\", ", nullptr, infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
418 }
419
420 // for extra safety to make sure we know that the delete can have impact on children and joins
421 const int res = QMessageBox::question( this, tr( "Delete at least %n feature(s) on other layer(s)", nullptr, childrenCount ),
422 tr( "Delete %n feature(s) on layer \"%1\", %2 as well and all of its other descendants.\nDelete these features?", nullptr, fids.count() )
423 .arg( layer->name() ).arg( childrenInfo ),
424 QMessageBox::Yes | QMessageBox::No );
425 if ( res != QMessageBox::Yes )
426 deleteFeatures = false;
427 }
428
429 if ( deleteFeatures )
430 {
432 layer->deleteFeatures( fids, &context );
433 const auto contextLayers = context.handledLayers();
434 if ( contextLayers.size() > 1 )
435 {
436 int deletedCount = 0;
437 QString feedbackMessage;
438 for ( QgsVectorLayer *contextLayer : contextLayers )
439 {
440 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
441 deletedCount += context.handledFeatures( contextLayer ).size();
442 }
443 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
444 }
445
446 updateUi();
447
449 }
450}
451
452void QgsAbstractRelationEditorWidget::linkFeature( const QString &filterExpression )
453{
454 QgsVectorLayer *layer = nullptr;
455
456 if ( mNmRelation.isValid() )
457 {
458 // only normal relations support m:n relation
460
462 }
463 else
464 {
465 if ( multiEditModeActive() )
466 {
467 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
468 return;
469 }
470
471 layer = mRelation.referencingLayer();
472 }
473
474 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
475 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
476
478 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
479 selectionDlg->setFilterExpression( filterExpression, QgsAttributeForm::ReplaceFilter );
480
481 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
482 selectionDlg->show();
483}
484
486{
487 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
488
489 if ( mNmRelation.isValid() )
490 {
491 // only normal relations support m:n relation
493
494 // Fields of the linking table
495 const QgsFields fields = mRelation.referencingLayer()->fields();
496
497 QgsAttributeMap linkAttributes;
498
499 switch ( mRelation.type() )
500 {
502 {
504 Q_ASSERT( polyRel.isValid() );
505
506 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ),
508 break;
509 }
511 break;
512 }
513
515 QgsFeature relatedFeature;
518 .setFilterFids( selectionDlg->selectedFeatures() )
520 while ( it.nextFeature( relatedFeature ) )
521 {
522 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
523 {
524 {
525 const auto constFieldPairs = mRelation.fieldPairs();
526 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
527 {
528 const int index = fields.indexOf( fieldPair.first );
529 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
530 }
531 }
532
533 const auto constFieldPairs = mNmRelation.fieldPairs();
534 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
535 {
536 const int index = fields.indexOf( fieldPair.first );
537 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
538 }
539
540 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
541 }
542 }
543
544 // Expression context for the linking table
546
547 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
548
549 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
550 QgsFeatureIds ids;
551 const auto constNewFeatures = linkFeaturesList;
552 for ( const QgsFeature &f : constNewFeatures )
553 ids << f.id();
555 }
556 else
557 {
558 if ( multiEditModeActive() )
559 {
560 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
561 return;
562 }
563
564 QMap<int, QVariant> keys;
565 const auto constFieldPairs = mRelation.fieldPairs();
566 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
567 {
568 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
569 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
570 keys.insert( idx, val );
571 }
572
573 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
574 for ( const QgsFeatureId fid : constSelectedFeatures )
575 {
576 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
577 switch ( mRelation.type() )
578 {
580 {
582
583 Q_ASSERT( polyRel.isValid() );
584
586 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
588 break;
589 }
591 break;
592 }
593
594 QMapIterator<int, QVariant> it( keys );
595 while ( it.hasNext() )
596 {
597 it.next();
598 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
599 }
600 }
601 }
602
603 updateUi();
604
606}
607
612
614{
615 if ( mNmRelation.isValid() )
616 {
617 // only normal relations support m:n relation
619
622 .setFilterFids( fids )
623 .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
624
625 QgsFeature f;
626
627 QStringList filters;
628
629 while ( selectedIterator.nextFeature( f ) )
630 {
631 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
632 }
633
634 QStringList featureFilters;
635 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
636 {
637 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
638 }
639
640 const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
641 featureFilters.join( QLatin1String( " OR " ) ),
642 filters.join( QLatin1String( " OR " ) ) );
643
645 .setNoAttributes()
646 .setFilterExpression( filter ) );
647
648 QgsFeatureIds fids;
649
650 while ( linkedIterator.nextFeature( f ) )
651 {
652 fids << f.id();
653 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
654 }
655
657 }
658 else
659 {
660 QMap<int, QgsField> keyFields;
661 const auto constFieldPairs = mRelation.fieldPairs();
662 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
663 {
664 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
665 if ( idx < 0 )
666 {
667 QgsDebugError( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
668 return;
669 }
670 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
671 keyFields.insert( idx, fld );
672 }
673
674 const auto constFeatureids = fids;
675 for ( const QgsFeatureId fid : constFeatureids )
676 {
677 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
678 switch ( mRelation.type() )
679 {
681 {
683
684 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
685
687 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
688 QgsVariantUtils::createNullVariant( referencingLayer->fields().field( polyRel.referencedLayerField() ).type() ) );
689 break;
690 }
692 break;
693 }
694
695 QMapIterator<int, QgsField> it( keyFields );
696 while ( it.hasNext() )
697 {
698 it.next();
700 }
701 }
702 }
703
704 updateUi();
705
707}
708
711
713{
714 Q_UNUSED( title )
715}
716
718{
719 Q_UNUSED( newRelation )
720 Q_UNUSED( newFeature )
721}
722
725
727{
728 Q_UNUSED( newRelation )
729 Q_UNUSED( newNmRelation )
730}
731
734
741
743{
745
746 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
747 QgsFeature f;
748 while ( fit.nextFeature( f ) )
749 {
751 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
752 }
753
755}
756
758{
759 updateUi();
760}
761
762
764
765
767 : QWidget( parent )
768 , mRelation( relation )
769{
770}
771
776
778{
779 return mRelation;
780}
781
783{
784 mNmRelation = nmRelation;
785}
786
788{
789 return mNmRelation;
790}
791
792
794
795
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ Success
Used for reporting a successful operation.
Definition qgis.h:158
@ Generated
A generated relation is a child of a polymorphic relation.
@ Normal
A normal relation.
virtual void setNmRelation(const QgsRelation &nmRelation)
Set the nm relation for this widget.
QgsRelation relation() const
Returns the relation for which this configuration widget applies.
virtual QgsRelation nmRelation() const
Returns the nm relation for which this configuration widget applies.
QgsAbstractRelationEditorConfigWidget(const QgsRelation &relation, QWidget *parent)
Create a new configuration widget.
QgsVectorLayer * layer()
Returns the layer for which this configuration widget applies.
QgsAbstractRelationEditorWidgetFactory()
Creates a new relation widget factory with given name.
void setMultiEditFeatureIds(const QgsFeatureIds &fids)
Set multiple feature to edit simultaneously.
void toggleEditing(bool state)
Toggles editing state of the widget.
QgsFeatureIds addFeature(const QgsGeometry &geometry=QgsGeometry())
Adds new features with given geometry Returns the Id of added features.
void deleteFeatures(const QgsFeatureIds &fids)
Deletes the features with fids.
void onLinkFeatureDlgAccepted()
Called when the link feature dialog is confirmed by the user.
bool forceSuppressFormPopup() const
Determines the force suppress form popup status that is configured for this widget.
virtual void afterSetRelations()
A hook called right after setRelations() is executed, but before updateUi() is called.
QList< QgsFeature > features() const
Returns the widget's current features.
void setRelationFeature(const QgsRelation &relation, const QgsFeature &feature)
Sets the relation and the feature.
virtual void setEditorContext(const QgsAttributeEditorContext &context)
Sets the editor context.
virtual Q_DECL_DEPRECATED void setTitle(const QString &title)
Sets the title of the widget, if it is wrapped within a QgsCollapsibleGroupBox.
void linkFeature(const QString &filterExpression=QString())
Links a new feature to the relation.
Q_DECL_DEPRECATED QString label() const
Determines the label of this element.
void showEvent(QShowEvent *)
Refresh the UI when the widget becomes visible.
void setLabel(const QString &label=QString())
Sets label for this element If it's empty it takes the relation id as label.
Q_DECL_DEPRECATED void updateTitle()
Updates the title contents to reflect the current state of the widget.
QgsAbstractRelationEditorWidget(const QVariantMap &config, QWidget *parent=nullptr)
Constructor.
void relatedFeaturesChanged()
Emit this signal, whenever the related features changed.
void setRelations(const QgsRelation &relation, const QgsRelation &nmrelation)
Sets the relation(s) for this widget If only one relation is set, it will act as a simple 1:N relatio...
virtual void beforeSetRelations(const QgsRelation &newRelation, const QgsRelation &newNmRelation)
A hook called right before setRelations() is executed.
QgsAttributeEditorContext editorContext() const
Returns the attribute editor context.
Q_DECL_DEPRECATED bool showLabel() const
Defines if a title label should be shown for this widget.
virtual void updateUi()
A hook called every time the state of the relation editor widget has changed via calling its set* met...
QgsRelation relation() const
Returns the relation.
virtual QVariantMap config() const =0
Returns the widget configuration.
virtual void beforeSetRelationFeature(const QgsRelation &newRelation, const QgsFeature &newFeature)
A hook called right before setRelationFeature() is executed.
void setFeature(const QgsFeature &feature, bool update=true)
Sets the feature being edited and updates the UI unless update is set to false.
void unlinkFeatures(const QgsFeatureIds &fids)
Unlinks the features with fids.
void deleteFeature(QgsFeatureId fid=QgsFeatureId())
Delete a feature with given fid.
QgsFeature feature() const
Returns the widget's current feature If the widget is in multiedit mode only the first is returned.
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
virtual void afterSetRelationFeature()
A hook called right after setRelationFeature() is executed, but before updateUi() is called.
bool multiEditModeActive() const
Returns true if editing multiple features at a time.
Q_DECL_DEPRECATED void setShowLabel(bool showLabel)
Defines if a title label should be shown for this widget.
void saveEdits()
Saves the current modifications in the relation.
void unlinkFeature(QgsFeatureId fid=QgsFeatureId())
Unlinks a feature with given fid.
void duplicateFeature(const QgsFeatureId &fid)
Duplicates a feature.
void duplicateFeatures(const QgsFeatureIds &fids)
Duplicates features.
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status with forceSuppressFormPopup configured for this widget.
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
This class contains context information for attribute editor widgets.
void setFormFeature(const QgsFeature &feature)
Set current feature for the currently edited form or table row.
QString attributeFormModeString() const
Returns given attributeFormMode as string.
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
QgsMessageBar * mainMessageBar()
Returns the main message bar.
@ ReplaceFilter
Filter should replace any existing filter.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QString expression() const
Returns the original, unmodified expression string.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsExpression * filterExpression() const
Returns the filter expression (if set).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
const QgsFeatureIds & selectedFeatures()
Gets the selected features.
void setFilterExpression(const QString &filter, QgsAttributeForm::FilterType type)
Set form filter expression.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QMetaType::Type type
Definition qgsfield.h:60
Container of fields for a vector layer.
Definition qgsfields.h:46
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
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).
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.
A geometry is the spatial representation of a feature.
static void warning(const QString &msg)
Goes to qWarning.
QString name
Definition qgsmaplayer.h:80
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
A polymorphic relation consists of the same properties like a normal relation except for the referenc...
QString layerRepresentation(const QgsVectorLayer *layer) const
Returns layer representation as evaluated string.
QgsRelationManager * relationManager
Definition qgsproject.h:117
static QgsProject * instance()
Returns the QgsProject singleton instance.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Defines a relation between matching fields of the two involved tables of a relation.
Definition qgsrelation.h:69
Represents a relationship between two vector layers.
Definition qgsrelation.h:44
QString name
Definition qgsrelation.h:50
QgsVectorLayer * referencedLayer
Definition qgsrelation.h:49
Qgis::RelationshipType type() const
Returns the type of the relation.
QString id
Definition qgsrelation.h:47
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
QgsPolymorphicRelation polymorphicRelation
Definition qgsrelation.h:53
QgsAttributeList referencedFields() const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
QgsVectorLayer * referencingLayer
Definition qgsrelation.h:48
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Contains settings which reflect the context in which vector layer tool operations should consider.
void setParentWidget(QWidget *parent)
Sets the widget which should be parented to tools' dialogues.
void setHideParent(bool hide)
Sets whether the parent widget should be hidden when showing tools' dialogues.
void setAdditionalExpressionContextScope(const QgsExpressionContextScope *scope)
Sets an additional expression context scope to be made available when calculating expressions.
void setShowModal(bool modal)
Sets whether tools' dialogues should be modal.
Methods in this class are used to handle basic operations on vector layers.
virtual bool startEditing(QgsVectorLayer *layer) const =0
This will be called, whenever a vector layer should be switched to edit mode.
virtual bool saveEdits(QgsVectorLayer *layer) const =0
Should be called, when the features should be committed but the editing session is not ended.
virtual bool addFeature(QgsVectorLayer *layer, const QgsAttributeMap &defaultValues=QgsAttributeMap(), const QgsGeometry &defaultGeometry=QgsGeometry(), QgsFeature *feature=nullptr, QWidget *parentWidget=nullptr, bool showModal=true, bool hideParent=false) const
This method should/will be called, whenever a new feature will be added to the layer.
virtual bool addFeatureV2(QgsVectorLayer *layer, const QgsAttributeMap &defaultValues=QgsAttributeMap(), const QgsGeometry &defaultGeometry=QgsGeometry(), QgsFeature *feature=nullptr, const QgsVectorLayerToolsContext &context=QgsVectorLayerToolsContext()) const
This method should/will be called, whenever a new feature will be added to the layer.
virtual bool stopEditing(QgsVectorLayer *layer, bool allowCancel=true) const =0
Will be called, when an editing session is ended and the features should be committed.
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features.
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth=0, int depth=0, QList< QgsVectorLayer * > referencedLayersBranch=QList< QgsVectorLayer * >())
Duplicates a feature and it's children (one level deep).
QList< QgsVectorLayerUtils::QgsFeatureData > QgsFeaturesDataList
Alias for list of QgsFeatureData.
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
static QgsFeatureList createFeatures(const QgsVectorLayer *layer, const QgsFeaturesDataList &featuresData, QgsExpressionContext *context=nullptr)
Creates a set of new features ready for insertion into a layer.
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE bool deleteFeatures(const QgsFeatureIds &fids, QgsVectorLayer::DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
Q_INVOKABLE bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes an attribute value for a feature (but does not immediately commit the changes).
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
QMap< int, QVariant > QgsAttributeMap
QList< QgsFeature > QgsFeatureList
QSet< QgsFeatureId > QgsFeatureIds
#define FID_TO_STRING(fid)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
Definition qgsfield.h:27
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
#define QgsDebugError(str)
Definition qgslogger.h:38
Context for cascade delete features.
QList< QgsVectorLayer * > handledLayers(bool includeAuxiliaryLayers=true) const
Returns a list of all layers affected by the delete operation.
QgsFeatureIds handledFeatures(QgsVectorLayer *layer) const
Returns a list of feature IDs from the specified layer affected by the delete operation.