QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
20#include "qgsfeatureiterator.h"
21#include "qgsexpression.h"
22#include "qgsfeature.h"
24#include "qgsrelation.h"
25#include "qgsrelationmanager.h"
27#include "qgsvectorlayertools.h"
28#include "qgsproject.h"
29#include "qgstransactiongroup.h"
30#include "qgsvectorlayerutils.h"
31
32#include <QMessageBox>
33#include <QPushButton>
34
35QgsAbstractRelationEditorWidget::QgsAbstractRelationEditorWidget( const QVariantMap &config, QWidget *parent )
36 : QWidget( parent )
37{
38 Q_UNUSED( config );
39}
40
42{
44
46 mFeatureList.clear();
47 mFeatureList.append( feature );
48
49 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
50
52 updateUi();
53}
54
56{
57
58 beforeSetRelations( relation, nmrelation );
59
61 mNmRelation = nmrelation;
62
63 if ( !mRelation.isValid() )
64 {
66 return;
67 }
68
70
71 const auto transactionGroups = QgsProject::instance()->transactionGroups();
72 for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
73 {
74 if ( mNmRelation.isValid() )
75 {
76 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
77 it.value()->layers().contains( mRelation.referencingLayer() ) &&
78 it.value()->layers().contains( mNmRelation.referencedLayer() ) )
80 }
81 else
82 {
83 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
84 it.value()->layers().contains( mRelation.referencingLayer() ) )
86 }
87 }
88
89 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
90
92 updateUi();
93}
94
96{
97 mEditorContext = context;
98}
99
101{
102 return mEditorContext;
103}
104
106{
107 mFeatureList.clear();
108 mFeatureList.append( feature );
109
111
112 if ( update )
113 updateUi();
114}
115
117{
118 mFeatureList.clear();
119
120 QgsFeatureIterator featureIterator = mRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
122 while ( featureIterator.nextFeature( feature ) )
123 mFeatureList.append( feature );
124
125 if ( ! mFeatureList.isEmpty() )
127}
128
129void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
130{
131 const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
132 beforeSetRelations( mRelation, nmrelation );
133 mNmRelation = nmrelation;
135 updateUi();
136}
137
139{
140 return mNmRelation.id();
141}
142
144{
145 return QString();
146}
147
149{
150 Q_UNUSED( label )
151}
152
154{
155 return false;
156}
157
159{
160 Q_UNUSED( showLabel )
161}
162
164{
166}
167
169{
171}
172
174{
175}
176
178{
179 return mFeatureList.size() > 1;
180}
181
183{
184 if ( !mFeatureList.isEmpty() )
185 return mFeatureList.first();
186
187 return QgsFeature();
188}
189
191{
192 return mFeatureList;
193}
194
196{
197 if ( state )
198 {
200 if ( mNmRelation.isValid() )
202 }
203 else
204 {
206 if ( mNmRelation.isValid() )
208 }
209}
210
212{
214 if ( mNmRelation.isValid() )
216}
217
219{
220 QgsAttributeMap keyAttrs;
221
223
224 // Fields of the linking table
225 const QgsFields fields = mRelation.referencingLayer()->fields();
226
227 QgsFeatureIds addedFeatureIds;
228
229 // For generated relations insert the referenced layer field
230 switch ( mRelation.type() )
231 {
233 {
235 keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
236 break;
237 }
238
240 break;
241 }
242
243 if ( mNmRelation.isValid() )
244 {
245 // only normal relations support m:n relation
247
248 // n:m Relation: first let the user create a new feature on the other table
249 // and autocreate a new linking feature.
250 QgsFeature finalFeature;
251 if ( !vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &finalFeature, this, false, true ) )
252 return QgsFeatureIds();
253
254 addedFeatureIds.insert( finalFeature.id() );
255
256 // Expression context for the linking table
258
259 QgsAttributeMap linkAttributes = keyAttrs;
260 const auto constFieldPairs = mRelation.fieldPairs();
261
263 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
264 {
265 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
266 {
267 const int index = fields.indexOf( fieldPair.first );
268 linkAttributes.insert( index, editingFeature.attribute( fieldPair.second ) );
269 }
270
271 const auto constNmFieldPairs = mNmRelation.fieldPairs();
272 for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
273 {
274 const int index = fields.indexOf( fieldPair.first );
275 linkAttributes.insert( index, finalFeature.attribute( fieldPair.second ) );
276 }
277
278 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
279 }
280 QgsFeatureList linkFeatureList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
281 mRelation.referencingLayer()->addFeatures( linkFeatureList );
282 }
283 else
284 {
285 const auto constFieldPairs = mRelation.fieldPairs();
286 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
287 keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeatureList.first().attribute( fieldPair.referencedField() ) );
288
290 if ( !vlTools->addFeature( mRelation.referencingLayer(), keyAttrs, geometry, &linkFeature, this, true, true ) )
291 return QgsFeatureIds();
292
293 addedFeatureIds.insert( linkFeature.id() );
294
295 // In multiedit add to other features to but without dialog
296 for ( const QgsFeature &feature : std::as_const( mFeatureList ) )
297 {
298 // First feature already added
299 if ( mFeatureList.first() == feature )
300 continue;
301
302 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
303 linkFeature.setAttribute( fields.indexFromName( fieldPair.referencingField() ), feature.attribute( fieldPair.referencedField() ) );
304
306 addedFeatureIds.insert( linkFeature.id() );
307 }
308 }
309
310 updateUi();
311
313
314 return addedFeatureIds;
315}
316
318{
319 deleteFeatures( QgsFeatureIds() << fid );
320
322}
323
325{
326 bool deleteFeatures = true;
327
328 QgsVectorLayer *layer;
329 if ( mNmRelation.isValid() )
330 {
331 // only normal relations support m:n relation
333
335
336 // When deleting a linked feature within an N:M relation,
337 // check if the feature is linked to more than just one feature.
338 // In case it is linked more than just once, ask the user for confirmation
339 // as it is likely he was not aware of the implications and might delete
340 // there may be several linking entries deleted along.
341
342 QgsFeatureRequest deletedFeaturesRequest;
343 deletedFeaturesRequest.setFilterFids( fids );
344 deletedFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
345 deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
346
347 QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
348 QStringList deletedFeaturesPks;
350 while ( deletedFeatures.nextFeature( feature ) )
351 {
352 deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
353 }
354
355 QgsFeatureRequest linkingFeaturesRequest;
356 linkingFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
357 linkingFeaturesRequest.setNoAttributes();
358
359 QString linkingFeaturesRequestExpression;
360 if ( !deletedFeaturesPks.empty() )
361 {
362 linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
363 linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
364
365 QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
366
367 int relatedLinkingFeaturesCount = 0;
368 while ( relatedLinkingFeatures.nextFeature( feature ) )
369 {
370 relatedLinkingFeaturesCount++;
371 }
372
373 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
374 {
375 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 );
376 messageBox.addButton( QMessageBox::Cancel );
377 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
378
379 messageBox.exec();
380 if ( messageBox.clickedButton() != deleteButton )
381 deleteFeatures = false;
382 }
383 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
384 {
385 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 );
386 messageBox.addButton( QMessageBox::Cancel );
387 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
388
389 messageBox.exec();
390 if ( messageBox.clickedButton() != deleteButton )
391 deleteFeatures = false;
392 }
393 }
394 }
395 else
396 {
397 layer = mRelation.referencingLayer();
398 }
399
401 if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
402 {
403 QString childrenInfo;
404 int childrenCount = 0;
405 const auto infoContextLayers = infoContext.layers();
406 for ( QgsVectorLayer *chl : infoContextLayers )
407 {
408 childrenCount += infoContext.duplicatedFeatures( chl ).size();
409 childrenInfo += ( tr( "%n feature(s) on layer \"%1\", ", nullptr, infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
410 }
411
412 // for extra safety to make sure we know that the delete can have impact on children and joins
413 const int res = QMessageBox::question( this, tr( "Delete at least %1 feature(s) on other layer(s)" ).arg( childrenCount ),
414 tr( "Delete %1 feature(s) on layer \"%2\", %3 as well\nand all of its other descendants.\nDelete these features?" ).arg( fids.count() ).arg( layer->name() ).arg( childrenInfo ),
415 QMessageBox::Yes | QMessageBox::No );
416 if ( res != QMessageBox::Yes )
417 deleteFeatures = false;
418 }
419
420 if ( deleteFeatures )
421 {
423 layer->deleteFeatures( fids, &context );
424 const auto contextLayers = context.handledLayers();
425 if ( contextLayers.size() > 1 )
426 {
427 int deletedCount = 0;
428 QString feedbackMessage;
429 for ( QgsVectorLayer *contextLayer : contextLayers )
430 {
431 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
432 deletedCount += context.handledFeatures( contextLayer ).size();
433 }
434 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
435 }
436
437 updateUi();
438
440 }
441}
442
444{
445 QgsVectorLayer *layer = nullptr;
446
447 if ( mNmRelation.isValid() )
448 {
449 // only normal relations support m:n relation
451
453 }
454 else
455 {
456 if ( multiEditModeActive() )
457 {
458 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
459 return;
460 }
461
462 layer = mRelation.referencingLayer();
463 }
464
465 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
466 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
467
469 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
470
471 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
472 selectionDlg->show();
473}
474
476{
477 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
478
479 if ( mNmRelation.isValid() )
480 {
481 // only normal relations support m:n relation
483
484 // Fields of the linking table
485 const QgsFields fields = mRelation.referencingLayer()->fields();
486
487 QgsAttributeMap linkAttributes;
488
489 switch ( mRelation.type() )
490 {
492 {
494 Q_ASSERT( polyRel.isValid() );
495
496 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ),
498 break;
499 }
501 break;
502 }
503
505 QgsFeature relatedFeature;
508 .setFilterFids( selectionDlg->selectedFeatures() )
510 while ( it.nextFeature( relatedFeature ) )
511 {
512 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
513 {
514 {
515 const auto constFieldPairs = mRelation.fieldPairs();
516 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
517 {
518 const int index = fields.indexOf( fieldPair.first );
519 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
520 }
521 }
522
523 const auto constFieldPairs = mNmRelation.fieldPairs();
524 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
525 {
526 const int index = fields.indexOf( fieldPair.first );
527 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
528 }
529
530 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
531 }
532 }
533
534 // Expression context for the linking table
536
537 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
538
539 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
540 QgsFeatureIds ids;
541 const auto constNewFeatures = linkFeaturesList;
542 for ( const QgsFeature &f : constNewFeatures )
543 ids << f.id();
545 }
546 else
547 {
548 if ( multiEditModeActive() )
549 {
550 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
551 return;
552 }
553
554 QMap<int, QVariant> keys;
555 const auto constFieldPairs = mRelation.fieldPairs();
556 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
557 {
558 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
559 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
560 keys.insert( idx, val );
561 }
562
563 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
564 for ( const QgsFeatureId fid : constSelectedFeatures )
565 {
566 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
567 switch ( mRelation.type() )
568 {
570 {
572
573 Q_ASSERT( polyRel.isValid() );
574
576 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
578 break;
579 }
581 break;
582 }
583
584 QMapIterator<int, QVariant> it( keys );
585 while ( it.hasNext() )
586 {
587 it.next();
588 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
589 }
590 }
591 }
592
593 updateUi();
594
596}
597
599{
600 unlinkFeatures( QgsFeatureIds() << fid );
601}
602
604{
605 if ( mNmRelation.isValid() )
606 {
607 // only normal relations support m:n relation
609
612 .setFilterFids( fids )
613 .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
614
615 QgsFeature f;
616
617 QStringList filters;
618
619 while ( selectedIterator.nextFeature( f ) )
620 {
621 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
622 }
623
624 QStringList featureFilters;
625 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
626 {
627 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
628 }
629
630 const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
631 featureFilters.join( QLatin1String( " OR " ) ),
632 filters.join( QLatin1String( " OR " ) ) );
633
635 .setNoAttributes()
636 .setFilterExpression( filter ) );
637
638 QgsFeatureIds fids;
639
640 while ( linkedIterator.nextFeature( f ) )
641 {
642 fids << f.id();
643 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
644 }
645
647 }
648 else
649 {
650 QMap<int, QgsField> keyFields;
651 const auto constFieldPairs = mRelation.fieldPairs();
652 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
653 {
654 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
655 if ( idx < 0 )
656 {
657 QgsDebugError( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
658 return;
659 }
660 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
661 keyFields.insert( idx, fld );
662 }
663
664 const auto constFeatureids = fids;
665 for ( const QgsFeatureId fid : constFeatureids )
666 {
667 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
668 switch ( mRelation.type() )
669 {
671 {
673
674 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
675
677 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
678 referencingLayer->fields().field( polyRel.referencedLayerField() ).type() );
679 break;
680 }
682 break;
683 }
684
685 QMapIterator<int, QgsField> it( keyFields );
686 while ( it.hasNext() )
687 {
688 it.next();
689 mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
690 }
691 }
692 }
693
694 updateUi();
695
697}
698
700{}
701
703{
704 Q_UNUSED( title )
705}
706
708{
709 Q_UNUSED( newRelation )
710 Q_UNUSED( newFeature )
711}
712
714{}
715
717{
718 Q_UNUSED( newRelation )
719 Q_UNUSED( newNmRelation )
720}
721
723{}
724
726{
728
730}
731
733{
735
736 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
737 QgsFeature f;
738 while ( fit.nextFeature( f ) )
739 {
741 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
742 }
743
745}
746
748{
749 updateUi();
750}
751
752
754
755
757 : QWidget( parent )
758 , mRelation( relation )
759{
760}
761
763{
764 return mLayer;
765}
766
768{
769 return mRelation;
770}
771
773{
774 mNmRelation = nmRelation;
775}
776
778{
779 return mNmRelation;
780}
781
782
784
785
787{
788}
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ 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.
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.
void linkFeature()
Links a new feature to the relation.
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.
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
QgsMessageBar * mainMessageBar()
Returns the main message bar.
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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:335
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
QVariant::Type type
Definition: qgsfield.h:60
Container of fields for a vector layer.
Definition: qgsfields.h:45
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:359
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:131
QString name
Definition: qgsmaplayer.h:78
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.
Definition: qgsproject.cpp:481
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:67
QString name
Definition: qgsrelation.h:48
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:47
Qgis::RelationshipType type() const
Returns the type of the relation.
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
Q_GADGET QString id
Definition: qgsrelation.h:45
QgsPolymorphicRelation polymorphicRelation
Definition: qgsrelation.h:51
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:46
bool isValid
Definition: qgsrelation.h:49
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
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 =0
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.
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.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
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 changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:42
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
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.