QGIS API Documentation 3.39.0-Master (d85f3c2a281)
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
20#include "qgsfeatureiterator.h"
21#include "qgsexpression.h"
23#include "qgsfeature.h"
25#include "qgsrelation.h"
26#include "qgsrelationmanager.h"
28#include "qgsvectorlayertools.h"
29#include "qgsproject.h"
30#include "qgstransactiongroup.h"
31#include "qgsvectorlayerutils.h"
32
33#include <QMessageBox>
34#include <QPushButton>
35
36QgsAbstractRelationEditorWidget::QgsAbstractRelationEditorWidget( const QVariantMap &config, QWidget *parent )
37 : QWidget( parent )
38{
39 Q_UNUSED( config );
40}
41
43{
45
47 mFeatureList.clear();
48 mFeatureList.append( feature );
49
50 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
51
53 updateUi();
54}
55
57{
58
59 beforeSetRelations( relation, nmrelation );
60
62 mNmRelation = nmrelation;
63
64 if ( !mRelation.isValid() )
65 {
67 return;
68 }
69
71
72 const auto transactionGroups = QgsProject::instance()->transactionGroups();
73 for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
74 {
75 if ( mNmRelation.isValid() )
76 {
77 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
78 it.value()->layers().contains( mRelation.referencingLayer() ) &&
79 it.value()->layers().contains( mNmRelation.referencedLayer() ) )
81 }
82 else
83 {
84 if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
85 it.value()->layers().contains( mRelation.referencingLayer() ) )
87 }
88 }
89
90 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
91
93 updateUi();
94}
95
100
105
107{
108 mFeatureList.clear();
109 mFeatureList.append( feature );
110
112
113 if ( update )
114 updateUi();
115}
116
118{
119 mFeatureList.clear();
120
121 QgsFeatureIterator featureIterator = mRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
123 while ( featureIterator.nextFeature( feature ) )
124 mFeatureList.append( feature );
125
126 if ( ! mFeatureList.isEmpty() )
128}
129
130void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
131{
132 const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
133 beforeSetRelations( mRelation, nmrelation );
134 mNmRelation = nmrelation;
136 updateUi();
137}
138
140{
141 return mNmRelation.id();
142}
143
145{
146 return QString();
147}
148
150{
151 Q_UNUSED( label )
152}
153
155{
156 return false;
157}
158
160{
161 Q_UNUSED( showLabel )
162}
163
168
173
177
179{
180 return mFeatureList.size() > 1;
181}
182
184{
185 if ( !mFeatureList.isEmpty() )
186 return mFeatureList.first();
187
188 return QgsFeature();
189}
190
192{
193 return mFeatureList;
194}
195
211
218
220{
221 QgsAttributeMap keyAttrs;
222
224
225 // Fields of the linking table
226 const QgsFields fields = mRelation.referencingLayer()->fields();
227
228 QgsFeatureIds addedFeatureIds;
229
230 // For generated relations insert the referenced layer field
231 switch ( mRelation.type() )
232 {
234 {
236 keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
237 break;
238 }
239
241 break;
242 }
243
244 if ( mNmRelation.isValid() )
245 {
246 // only normal relations support m:n relation
248
249 // n:m Relation: first let the user create a new feature on the other table
250 // and autocreate a new linking feature.
251 QgsFeature finalFeature;
252 if ( !vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &finalFeature, this, false, true ) )
253 return QgsFeatureIds();
254
255 addedFeatureIds.insert( finalFeature.id() );
256
257 // Expression context for the linking table
259
260 QgsAttributeMap linkAttributes = keyAttrs;
261 const auto constFieldPairs = mRelation.fieldPairs();
262
264 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
265 {
266 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
267 {
268 const int index = fields.indexOf( fieldPair.first );
269 linkAttributes.insert( index, editingFeature.attribute( fieldPair.second ) );
270 }
271
272 const auto constNmFieldPairs = mNmRelation.fieldPairs();
273 for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
274 {
275 const int index = fields.indexOf( fieldPair.first );
276 linkAttributes.insert( index, finalFeature.attribute( fieldPair.second ) );
277 }
278
279 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
280 }
281 QgsFeatureList linkFeatureList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
282 mRelation.referencingLayer()->addFeatures( linkFeatureList );
283 }
284 else
285 {
286 const auto constFieldPairs = mRelation.fieldPairs();
287 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
288 keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeatureList.first().attribute( fieldPair.referencedField() ) );
289
291 context.setParentWidget( this );
292 context.setShowModal( false );
293 context.setHideParent( true );
294 std::unique_ptr<QgsExpressionContextScope> scope( QgsExpressionContextUtils::parentFormScope( mFeatureList.first(), mEditorContext.attributeFormModeString() ) );
295 context.setAdditionalExpressionContextScope( scope.get() );
297 if ( !vlTools->addFeatureV2( mRelation.referencingLayer(), keyAttrs, geometry, &linkFeature, context ) )
298 return QgsFeatureIds();
299
300 addedFeatureIds.insert( linkFeature.id() );
301
302 // In multiedit add to other features to but without dialog
303 for ( const QgsFeature &feature : std::as_const( mFeatureList ) )
304 {
305 // First feature already added
306 if ( mFeatureList.first() == feature )
307 continue;
308
309 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
310 linkFeature.setAttribute( fields.indexFromName( fieldPair.referencingField() ), feature.attribute( fieldPair.referencedField() ) );
311
313 addedFeatureIds.insert( linkFeature.id() );
314 }
315 }
316
317 updateUi();
318
320
321 return addedFeatureIds;
322}
323
330
332{
333 bool deleteFeatures = true;
334
335 QgsVectorLayer *layer;
336 if ( mNmRelation.isValid() )
337 {
338 // only normal relations support m:n relation
340
342
343 // When deleting a linked feature within an N:M relation,
344 // check if the feature is linked to more than just one feature.
345 // In case it is linked more than just once, ask the user for confirmation
346 // as it is likely he was not aware of the implications and might delete
347 // there may be several linking entries deleted along.
348
349 QgsFeatureRequest deletedFeaturesRequest;
350 deletedFeaturesRequest.setFilterFids( fids );
351 deletedFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
352 deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
353
354 QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
355 QStringList deletedFeaturesPks;
357 while ( deletedFeatures.nextFeature( feature ) )
358 {
359 deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
360 }
361
362 QgsFeatureRequest linkingFeaturesRequest;
363 linkingFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
364 linkingFeaturesRequest.setNoAttributes();
365
366 QString linkingFeaturesRequestExpression;
367 if ( !deletedFeaturesPks.empty() )
368 {
369 linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
370 linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
371
372 QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
373
374 int relatedLinkingFeaturesCount = 0;
375 while ( relatedLinkingFeatures.nextFeature( feature ) )
376 {
377 relatedLinkingFeaturesCount++;
378 }
379
380 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
381 {
382 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 );
383 messageBox.addButton( QMessageBox::Cancel );
384 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
385
386 messageBox.exec();
387 if ( messageBox.clickedButton() != deleteButton )
388 deleteFeatures = false;
389 }
390 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
391 {
392 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 );
393 messageBox.addButton( QMessageBox::Cancel );
394 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
395
396 messageBox.exec();
397 if ( messageBox.clickedButton() != deleteButton )
398 deleteFeatures = false;
399 }
400 }
401 }
402 else
403 {
404 layer = mRelation.referencingLayer();
405 }
406
408 if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
409 {
410 QString childrenInfo;
411 int childrenCount = 0;
412 const auto infoContextLayers = infoContext.layers();
413 for ( QgsVectorLayer *chl : infoContextLayers )
414 {
415 childrenCount += infoContext.duplicatedFeatures( chl ).size();
416 childrenInfo += ( tr( "%n feature(s) on layer \"%1\", ", nullptr, infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
417 }
418
419 // for extra safety to make sure we know that the delete can have impact on children and joins
420 const int res = QMessageBox::question( this, tr( "Delete at least %1 feature(s) on other layer(s)" ).arg( childrenCount ),
421 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 ),
422 QMessageBox::Yes | QMessageBox::No );
423 if ( res != QMessageBox::Yes )
424 deleteFeatures = false;
425 }
426
427 if ( deleteFeatures )
428 {
430 layer->deleteFeatures( fids, &context );
431 const auto contextLayers = context.handledLayers();
432 if ( contextLayers.size() > 1 )
433 {
434 int deletedCount = 0;
435 QString feedbackMessage;
436 for ( QgsVectorLayer *contextLayer : contextLayers )
437 {
438 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
439 deletedCount += context.handledFeatures( contextLayer ).size();
440 }
441 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
442 }
443
444 updateUi();
445
447 }
448}
449
450void QgsAbstractRelationEditorWidget::linkFeature( const QString &filterExpression )
451{
452 QgsVectorLayer *layer = nullptr;
453
454 if ( mNmRelation.isValid() )
455 {
456 // only normal relations support m:n relation
458
460 }
461 else
462 {
463 if ( multiEditModeActive() )
464 {
465 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
466 return;
467 }
468
469 layer = mRelation.referencingLayer();
470 }
471
472 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
473 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
474
476 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
477 selectionDlg->setFilterExpression( filterExpression, QgsAttributeForm::ReplaceFilter );
478
479 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
480 selectionDlg->show();
481}
482
484{
485 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
486
487 if ( mNmRelation.isValid() )
488 {
489 // only normal relations support m:n relation
491
492 // Fields of the linking table
493 const QgsFields fields = mRelation.referencingLayer()->fields();
494
495 QgsAttributeMap linkAttributes;
496
497 switch ( mRelation.type() )
498 {
500 {
502 Q_ASSERT( polyRel.isValid() );
503
504 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ),
506 break;
507 }
509 break;
510 }
511
513 QgsFeature relatedFeature;
516 .setFilterFids( selectionDlg->selectedFeatures() )
518 while ( it.nextFeature( relatedFeature ) )
519 {
520 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
521 {
522 {
523 const auto constFieldPairs = mRelation.fieldPairs();
524 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
525 {
526 const int index = fields.indexOf( fieldPair.first );
527 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
528 }
529 }
530
531 const auto constFieldPairs = mNmRelation.fieldPairs();
532 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
533 {
534 const int index = fields.indexOf( fieldPair.first );
535 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
536 }
537
538 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
539 }
540 }
541
542 // Expression context for the linking table
544
545 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
546
547 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
548 QgsFeatureIds ids;
549 const auto constNewFeatures = linkFeaturesList;
550 for ( const QgsFeature &f : constNewFeatures )
551 ids << f.id();
553 }
554 else
555 {
556 if ( multiEditModeActive() )
557 {
558 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
559 return;
560 }
561
562 QMap<int, QVariant> keys;
563 const auto constFieldPairs = mRelation.fieldPairs();
564 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
565 {
566 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
567 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
568 keys.insert( idx, val );
569 }
570
571 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
572 for ( const QgsFeatureId fid : constSelectedFeatures )
573 {
574 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
575 switch ( mRelation.type() )
576 {
578 {
580
581 Q_ASSERT( polyRel.isValid() );
582
584 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
586 break;
587 }
589 break;
590 }
591
592 QMapIterator<int, QVariant> it( keys );
593 while ( it.hasNext() )
594 {
595 it.next();
596 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
597 }
598 }
599 }
600
601 updateUi();
602
604}
605
610
612{
613 if ( mNmRelation.isValid() )
614 {
615 // only normal relations support m:n relation
617
620 .setFilterFids( fids )
621 .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
622
623 QgsFeature f;
624
625 QStringList filters;
626
627 while ( selectedIterator.nextFeature( f ) )
628 {
629 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
630 }
631
632 QStringList featureFilters;
633 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
634 {
635 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
636 }
637
638 const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
639 featureFilters.join( QLatin1String( " OR " ) ),
640 filters.join( QLatin1String( " OR " ) ) );
641
643 .setNoAttributes()
644 .setFilterExpression( filter ) );
645
646 QgsFeatureIds fids;
647
648 while ( linkedIterator.nextFeature( f ) )
649 {
650 fids << f.id();
651 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
652 }
653
655 }
656 else
657 {
658 QMap<int, QgsField> keyFields;
659 const auto constFieldPairs = mRelation.fieldPairs();
660 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
661 {
662 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
663 if ( idx < 0 )
664 {
665 QgsDebugError( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
666 return;
667 }
668 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
669 keyFields.insert( idx, fld );
670 }
671
672 const auto constFeatureids = fids;
673 for ( const QgsFeatureId fid : constFeatureids )
674 {
675 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
676 switch ( mRelation.type() )
677 {
679 {
681
682 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
683
685 referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
686 QgsVariantUtils::createNullVariant( referencingLayer->fields().field( polyRel.referencedLayerField() ).type() ) );
687 break;
688 }
690 break;
691 }
692
693 QMapIterator<int, QgsField> it( keyFields );
694 while ( it.hasNext() )
695 {
696 it.next();
698 }
699 }
700 }
701
702 updateUi();
703
705}
706
709
711{
712 Q_UNUSED( title )
713}
714
716{
717 Q_UNUSED( newRelation )
718 Q_UNUSED( newFeature )
719}
720
723
725{
726 Q_UNUSED( newRelation )
727 Q_UNUSED( newNmRelation )
728}
729
732
739
741{
743
744 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
745 QgsFeature f;
746 while ( fit.nextFeature( f ) )
747 {
749 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
750 }
751
753}
754
756{
757 updateUi();
758}
759
760
762
763
765 : QWidget( parent )
766 , mRelation( relation )
767{
768}
769
774
776{
777 return mRelation;
778}
779
781{
782 mNmRelation = nmRelation;
783}
784
786{
787 return mNmRelation;
788}
789
790
792
793
@ 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.