QGIS API Documentation 3.99.0-Master (d270888f95f)
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 "qgsexpression.h"
22#include "qgsfeature.h"
23#include "qgsfeatureiterator.h"
26#include "qgsproject.h"
27#include "qgsrelation.h"
28#include "qgsrelationmanager.h"
29#include "qgstransactiongroup.h"
30#include "qgsvectorlayertools.h"
31#include "qgsvectorlayerutils.h"
32
33#include <QMessageBox>
34#include <QPushButton>
35#include <QString>
36
37#include "moc_qgsabstractrelationeditorwidget.cpp"
38
39using namespace Qt::StringLiterals;
40
42 : QWidget( parent )
43{
44 Q_UNUSED( config );
45}
46
48{
50
52 mFeatureList.clear();
53 mFeatureList.append( feature );
54
55 setObjectName( u"referenced/"_s + mRelation.name() );
56
58 updateUi();
59}
60
62{
63 beforeSetRelations( relation, nmrelation );
64
66 mNmRelation = nmrelation;
67
68 if ( !mRelation.isValid() )
69 {
71 return;
72 }
73
75
76 const auto transactionGroups = QgsProject::instance()->transactionGroups();
77 for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
78 {
79 if ( mNmRelation.isValid() )
80 {
81 if ( it.value()->layers().contains( mRelation.referencedLayer() ) && it.value()->layers().contains( mRelation.referencingLayer() ) && it.value()->layers().contains( mNmRelation.referencedLayer() ) )
83 }
84 else
85 {
86 if ( it.value()->layers().contains( mRelation.referencedLayer() ) && it.value()->layers().contains( mRelation.referencingLayer() ) )
88 }
89 }
90
91 setObjectName( u"referenced/"_s + mRelation.name() );
92
94 updateUi();
95}
96
101
106
108{
109 mFeatureList.clear();
110 mFeatureList.append( feature );
111
112 mEditorContext.setFormFeature( feature );
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() )
128 mEditorContext.setFormFeature( mFeatureList.first() );
129}
130
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
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
198{
199 if ( state )
200 {
201 mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
202 if ( mNmRelation.isValid() )
203 mEditorContext.vectorLayerTools()->startEditing( mNmRelation.referencedLayer() );
204 }
205 else
206 {
207 mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
208 if ( mNmRelation.isValid() )
209 mEditorContext.vectorLayerTools()->stopEditing( mNmRelation.referencedLayer() );
210 }
211}
212
214{
215 mEditorContext.vectorLayerTools()->saveEdits( mRelation.referencingLayer() );
216 if ( mNmRelation.isValid() )
217 mEditorContext.vectorLayerTools()->saveEdits( mNmRelation.referencedLayer() );
218}
219
221{
222 QgsAttributeMap keyAttrs;
223
224 const QgsVectorLayerTools *vlTools = mEditorContext.vectorLayerTools();
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 {
236 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
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
248 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
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
259 QgsExpressionContext context = mRelation.referencingLayer()->createExpressionContext();
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
313 mRelation.referencingLayer()->addFeature( linkFeature );
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
340 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
341
342 layer = mNmRelation.referencedLayer();
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 = u"%1 IN (%2)"_s.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 ), tr( "Delete %n feature(s) on layer \"%1\", %2 as well and all of its other descendants.\nDelete these features?", nullptr, fids.count() ).arg( layer->name() ).arg( childrenInfo ), QMessageBox::Yes | QMessageBox::No );
422 if ( res != QMessageBox::Yes )
423 deleteFeatures = false;
424 }
425
426 if ( deleteFeatures )
427 {
429 layer->deleteFeatures( fids, &context );
430 const auto contextLayers = context.handledLayers();
431 if ( contextLayers.size() > 1 )
432 {
433 int deletedCount = 0;
434 QString feedbackMessage;
435 for ( QgsVectorLayer *contextLayer : contextLayers )
436 {
437 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
438 deletedCount += context.handledFeatures( contextLayer ).size();
439 }
440 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
441 }
442
443 updateUi();
444
446 }
447}
448
449void QgsAbstractRelationEditorWidget::linkFeature( const QString &filterExpression )
450{
451 QgsVectorLayer *layer = nullptr;
452
453 if ( mNmRelation.isValid() )
454 {
455 // only normal relations support m:n relation
456 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
457
458 layer = mNmRelation.referencedLayer();
459 }
460 else
461 {
462 if ( multiEditModeActive() )
463 {
464 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
465 return;
466 }
467
468 layer = mRelation.referencingLayer();
469 }
470
471 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
472 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
473
474 const QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mRelation.referencedLayer(), mFeatureList.first() );
475 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
476 selectionDlg->setFilterExpression( filterExpression, QgsAttributeForm::ReplaceFilter );
477
478 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
479 selectionDlg->show();
480}
481
483{
484 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
485
486 if ( mNmRelation.isValid() )
487 {
488 // only normal relations support m:n relation
489 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
490
491 // Fields of the linking table
492 const QgsFields fields = mRelation.referencingLayer()->fields();
493
494 QgsAttributeMap linkAttributes;
495
496 switch ( mRelation.type() )
497 {
499 {
500 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
501 Q_ASSERT( polyRel.isValid() );
502
503 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
504 break;
505 }
507 break;
508 }
509
511 QgsFeature relatedFeature;
512 QgsFeatureIterator it = mNmRelation.referencedLayer()->getFeatures(
514 .setFilterFids( selectionDlg->selectedFeatures() )
515 .setSubsetOfAttributes( mNmRelation.referencedFields() )
516 );
517 while ( it.nextFeature( relatedFeature ) )
518 {
519 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
520 {
521 {
522 const auto constFieldPairs = mRelation.fieldPairs();
523 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
524 {
525 const int index = fields.indexOf( fieldPair.first );
526 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
527 }
528 }
529
530 const auto constFieldPairs = mNmRelation.fieldPairs();
531 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
532 {
533 const int index = fields.indexOf( fieldPair.first );
534 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
535 }
536
537 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
538 }
539 }
540
541 // Expression context for the linking table
542 QgsExpressionContext context = mRelation.referencingLayer()->createExpressionContext();
543
544 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
545
546 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
547 QgsFeatureIds ids;
548 const auto constNewFeatures = linkFeaturesList;
549 for ( const QgsFeature &f : constNewFeatures )
550 ids << f.id();
551 mRelation.referencingLayer()->selectByIds( ids );
552 }
553 else
554 {
555 if ( multiEditModeActive() )
556 {
557 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
558 return;
559 }
560
561 QMap<int, QVariant> keys;
562 const auto constFieldPairs = mRelation.fieldPairs();
563 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
564 {
565 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
566 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
567 keys.insert( idx, val );
568 }
569
570 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
571 for ( const QgsFeatureId fid : constSelectedFeatures )
572 {
573 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
574 switch ( mRelation.type() )
575 {
577 {
578 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
579
580 Q_ASSERT( polyRel.isValid() );
581
582 mRelation.referencingLayer()->changeAttributeValue( fid, referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
583 break;
584 }
586 break;
587 }
588
589 QMapIterator<int, QVariant> it( keys );
590 while ( it.hasNext() )
591 {
592 it.next();
593 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
594 }
595 }
596 }
597
598 updateUi();
599
601}
602
607
609{
610 if ( mNmRelation.isValid() )
611 {
612 // only normal relations support m:n relation
613 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
614
615 QgsFeatureIterator selectedIterator = mNmRelation.referencedLayer()->getFeatures(
617 .setFilterFids( fids )
618 .setSubsetOfAttributes( mNmRelation.referencedFields() )
619 );
620
621 QgsFeature f;
622
623 QStringList filters;
624
625 while ( selectedIterator.nextFeature( f ) )
626 {
627 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
628 }
629
630 QStringList featureFilters;
631 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
632 {
633 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
634 }
635
636 const QString filter = u"(%1) AND (%2)"_s.arg( featureFilters.join( " OR "_L1 ), filters.join( " OR "_L1 ) );
637
638 QgsFeatureIterator linkedIterator = mRelation.referencingLayer()->getFeatures( QgsFeatureRequest()
639 .setNoAttributes()
640 .setFilterExpression( filter ) );
641
642 QgsFeatureIds fids;
643
644 while ( linkedIterator.nextFeature( f ) )
645 {
646 fids << f.id();
647 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
648 }
649
650 mRelation.referencingLayer()->deleteFeatures( fids );
651 }
652 else
653 {
654 QMap<int, QgsField> keyFields;
655 const auto constFieldPairs = mRelation.fieldPairs();
656 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
657 {
658 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
659 if ( idx < 0 )
660 {
661 QgsDebugError( u"referencing field %1 not found"_s.arg( fieldPair.referencingField() ) );
662 return;
663 }
664 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
665 keyFields.insert( idx, fld );
666 }
667
668 const auto constFeatureids = fids;
669 for ( const QgsFeatureId fid : constFeatureids )
670 {
671 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
672 switch ( mRelation.type() )
673 {
675 {
676 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
677
678 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
679
680 mRelation.referencingLayer()->changeAttributeValue( fid, referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ), QgsVariantUtils::createNullVariant( referencingLayer->fields().field( polyRel.referencedLayerField() ).type() ) );
681 break;
682 }
684 break;
685 }
686
687 QMapIterator<int, QgsField> it( keyFields );
688 while ( it.hasNext() )
689 {
690 it.next();
691 mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QgsVariantUtils::createNullVariant( it.value().type() ) );
692 }
693 }
694 }
695
696 updateUi();
697
699}
700
703
705{
706 Q_UNUSED( title )
707}
708
710{
711 Q_UNUSED( newRelation )
712 Q_UNUSED( newFeature )
713}
714
717
719{
720 Q_UNUSED( newRelation )
721 Q_UNUSED( newNmRelation )
722}
723
726
733
735{
736 QgsVectorLayer *layer = mRelation.referencingLayer();
737
738 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
739 QgsFeature f;
740 while ( fit.nextFeature( f ) )
741 {
743 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
744 }
745
747}
748
750{
751 updateUi();
752}
753
754
756
757
759 : QWidget( parent )
760 , mRelation( relation )
761{
762}
763
768
770{
771 return mRelation;
772}
773
778
780{
781 return mNmRelation;
782}
783
784
786
787
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2254
@ Success
Used for reporting a successful operation.
Definition qgis.h:163
@ Generated
A generated relation is a child of a polymorphic relation.
Definition qgis.h:4452
@ Normal
A normal relation.
Definition qgis.h:4451
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 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.
void showEvent(QShowEvent *) override
Refresh the UI when the widget becomes visible.
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.
Contains context information for attribute editor widgets.
@ 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...
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.
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.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
A dialog for selecting features from a vector layer.
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:60
QgsFeatureId id
Definition qgsfeature.h:68
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:56
QMetaType::Type type
Definition qgsfield.h:63
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).
A geometry is the spatial representation of a feature.
static void warning(const QString &msg)
Goes to qWarning.
QString name
Definition qgsmaplayer.h:87
A relation where the referenced (parent) layer is calculated based on fields from the referencing (ch...
QString layerRepresentation(const QgsVectorLayer *layer) const
Returns layer representation as evaluated string.
QgsRelationManager * relationManager
Definition qgsproject.h:123
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:72
Represents a relationship between two vector layers.
Definition qgsrelation.h:42
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 be considere...
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.
Used to handle basic editing operations on vector layers.
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.
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds which 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)
Returns a descriptive string for a feature, suitable for displaying to the user.
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())
Returns true if at least one feature of the fids on layer is connected as parent in at least one comp...
Represents a vector layer which manages a vector based dataset.
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.
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:30
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59
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.