QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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
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
197{
198 if ( state )
199 {
200 mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
201 if ( mNmRelation.isValid() )
202 mEditorContext.vectorLayerTools()->startEditing( mNmRelation.referencedLayer() );
203 }
204 else
205 {
206 mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
207 if ( mNmRelation.isValid() )
208 mEditorContext.vectorLayerTools()->stopEditing( mNmRelation.referencedLayer() );
209 }
210}
211
213{
214 mEditorContext.vectorLayerTools()->saveEdits( mRelation.referencingLayer() );
215 if ( mNmRelation.isValid() )
216 mEditorContext.vectorLayerTools()->saveEdits( mNmRelation.referencedLayer() );
217}
218
220{
221 QgsAttributeMap keyAttrs;
222
223 const QgsVectorLayerTools *vlTools = mEditorContext.vectorLayerTools();
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 {
235 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
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
247 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
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
258 QgsExpressionContext context = mRelation.referencingLayer()->createExpressionContext();
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
312 mRelation.referencingLayer()->addFeature( linkFeature );
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
339 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
340
341 layer = mNmRelation.referencedLayer();
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 = u"%1 IN (%2)"_s.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(
383 QMessageBox::Question,
384 tr( "Really delete entry?" ),
385 tr( "The entry on %1 is still linked to %2 features on %3. Do you want to delete it?" )
386 .arg( mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ),
387 QMessageBox::NoButton,
388 this
389 );
390 messageBox.addButton( QMessageBox::Cancel );
391 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
392
393 messageBox.exec();
394 if ( messageBox.clickedButton() != deleteButton )
395 deleteFeatures = false;
396 }
397 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
398 {
399 QMessageBox messageBox(
400 QMessageBox::Question,
401 tr( "Really delete entries?" ),
402 tr( "The %1 entries on %2 are still linked to %3 features on %4. Do you want to delete them?" )
403 .arg( QLocale().toString( deletedFeaturesPks.size() ), mNmRelation.referencedLayer()->name(), QLocale().toString( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ),
404 QMessageBox::NoButton,
405 this
406 );
407 messageBox.addButton( QMessageBox::Cancel );
408 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
409
410 messageBox.exec();
411 if ( messageBox.clickedButton() != deleteButton )
412 deleteFeatures = false;
413 }
414 }
415 }
416 else
417 {
418 layer = mRelation.referencingLayer();
419 }
420
422 if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
423 {
424 QString childrenInfo;
425 int childrenCount = 0;
426 const auto infoContextLayers = infoContext.layers();
427 for ( QgsVectorLayer *chl : infoContextLayers )
428 {
429 childrenCount += infoContext.duplicatedFeatures( chl ).size();
430 childrenInfo += ( tr( "%n feature(s) on layer \"%1\", ", nullptr, infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
431 }
432
433 // for extra safety to make sure we know that the delete can have impact on children and joins
434 const int res = QMessageBox::question(
435 this,
436 tr( "Delete at least %n feature(s) on other layer(s)", nullptr, childrenCount ),
437 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 ),
438 QMessageBox::Yes | QMessageBox::No
439 );
440 if ( res != QMessageBox::Yes )
441 deleteFeatures = false;
442 }
443
444 if ( deleteFeatures )
445 {
447 layer->deleteFeatures( fids, &context );
448 const auto contextLayers = context.handledLayers();
449 if ( contextLayers.size() > 1 )
450 {
451 int deletedCount = 0;
452 QString feedbackMessage;
453 for ( QgsVectorLayer *contextLayer : contextLayers )
454 {
455 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
456 deletedCount += context.handledFeatures( contextLayer ).size();
457 }
458 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
459 }
460
461 updateUi();
462
464 }
465}
466
467void QgsAbstractRelationEditorWidget::linkFeature( const QString &filterExpression )
468{
469 QgsVectorLayer *layer = nullptr;
470
471 if ( mNmRelation.isValid() )
472 {
473 // only normal relations support m:n relation
474 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
475
476 layer = mNmRelation.referencedLayer();
477 }
478 else
479 {
480 if ( multiEditModeActive() )
481 {
482 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
483 return;
484 }
485
486 layer = mRelation.referencingLayer();
487 }
488
489 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
490 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
491
492 const QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mRelation.referencedLayer(), mFeatureList.first() );
493 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
494 selectionDlg->setFilterExpression( filterExpression, QgsAttributeForm::ReplaceFilter );
495
496 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
497 selectionDlg->show();
498}
499
501{
502 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
503
504 if ( mNmRelation.isValid() )
505 {
506 // only normal relations support m:n relation
507 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
508
509 // Fields of the linking table
510 const QgsFields fields = mRelation.referencingLayer()->fields();
511
512 QgsAttributeMap linkAttributes;
513
514 switch ( mRelation.type() )
515 {
517 {
518 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
519 Q_ASSERT( polyRel.isValid() );
520
521 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
522 break;
523 }
525 break;
526 }
527
529 QgsFeature relatedFeature;
530 QgsFeatureIterator it = mNmRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( selectionDlg->selectedFeatures() ).setSubsetOfAttributes( mNmRelation.referencedFields() ) );
531 while ( it.nextFeature( relatedFeature ) )
532 {
533 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
534 {
535 {
536 const auto constFieldPairs = mRelation.fieldPairs();
537 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
538 {
539 const int index = fields.indexOf( fieldPair.first );
540 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
541 }
542 }
543
544 const auto constFieldPairs = mNmRelation.fieldPairs();
545 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
546 {
547 const int index = fields.indexOf( fieldPair.first );
548 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
549 }
550
551 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
552 }
553 }
554
555 // Expression context for the linking table
556 QgsExpressionContext context = mRelation.referencingLayer()->createExpressionContext();
557
558 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
559
560 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
561 QgsFeatureIds ids;
562 const auto constNewFeatures = linkFeaturesList;
563 for ( const QgsFeature &f : constNewFeatures )
564 ids << f.id();
565 mRelation.referencingLayer()->selectByIds( ids );
566 }
567 else
568 {
569 if ( multiEditModeActive() )
570 {
571 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
572 return;
573 }
574
575 QMap<int, QVariant> keys;
576 const auto constFieldPairs = mRelation.fieldPairs();
577 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
578 {
579 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
580 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
581 keys.insert( idx, val );
582 }
583
584 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
585 for ( const QgsFeatureId fid : constSelectedFeatures )
586 {
587 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
588 switch ( mRelation.type() )
589 {
591 {
592 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
593
594 Q_ASSERT( polyRel.isValid() );
595
596 mRelation.referencingLayer()->changeAttributeValue( fid, referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
597 break;
598 }
600 break;
601 }
602
603 QMapIterator<int, QVariant> it( keys );
604 while ( it.hasNext() )
605 {
606 it.next();
607 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
608 }
609 }
610 }
611
612 updateUi();
613
615}
616
621
623{
624 if ( mNmRelation.isValid() )
625 {
626 // only normal relations support m:n relation
627 Q_ASSERT( mNmRelation.type() == Qgis::RelationshipType::Normal );
628
629 QgsFeatureIterator selectedIterator = mNmRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ).setSubsetOfAttributes( mNmRelation.referencedFields() ) );
630
631 QgsFeature f;
632
633 QStringList filters;
634
635 while ( selectedIterator.nextFeature( f ) )
636 {
637 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
638 }
639
640 QStringList featureFilters;
641 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
642 {
643 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
644 }
645
646 const QString filter = u"(%1) AND (%2)"_s.arg( featureFilters.join( " OR "_L1 ), filters.join( " OR "_L1 ) );
647
648 QgsFeatureIterator linkedIterator = mRelation.referencingLayer()->getFeatures( QgsFeatureRequest().setNoAttributes().setFilterExpression( filter ) );
649
650 QgsFeatureIds fids;
651
652 while ( linkedIterator.nextFeature( f ) )
653 {
654 fids << f.id();
655 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
656 }
657
658 mRelation.referencingLayer()->deleteFeatures( fids );
659 }
660 else
661 {
662 QMap<int, QgsField> keyFields;
663 const auto constFieldPairs = mRelation.fieldPairs();
664 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
665 {
666 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
667 if ( idx < 0 )
668 {
669 QgsDebugError( u"referencing field %1 not found"_s.arg( fieldPair.referencingField() ) );
670 return;
671 }
672 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
673 keyFields.insert( idx, fld );
674 }
675
676 const auto constFeatureids = fids;
677 for ( const QgsFeatureId fid : constFeatureids )
678 {
679 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
680 switch ( mRelation.type() )
681 {
683 {
684 const QgsPolymorphicRelation polyRel = mRelation.polymorphicRelation();
685
686 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
687
688 mRelation.referencingLayer()->changeAttributeValue(
689 fid, referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ), QgsVariantUtils::createNullVariant( referencingLayer->fields().field( polyRel.referencedLayerField() ).type() )
690 );
691 break;
692 }
694 break;
695 }
696
697 QMapIterator<int, QgsField> it( keyFields );
698 while ( it.hasNext() )
699 {
700 it.next();
701 mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QgsVariantUtils::createNullVariant( it.value().type() ) );
702 }
703 }
704 }
705
706 updateUi();
707
709}
710
713
715{
716 Q_UNUSED( title )
717}
718
720{
721 Q_UNUSED( newRelation )
722 Q_UNUSED( newFeature )
723}
724
727
729{
730 Q_UNUSED( newRelation )
731 Q_UNUSED( newNmRelation )
732}
733
736
743
745{
746 QgsVectorLayer *layer = mRelation.referencingLayer();
747
748 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
749 QgsFeature f;
750 while ( fit.nextFeature( f ) )
751 {
753 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
754 }
755
757}
758
760{
761 updateUi();
762}
763
764
766
767
769 : QWidget( parent )
770 , mRelation( relation )
771{}
772
777
779{
780 return mRelation;
781}
782
787
789{
790 return mNmRelation;
791}
792
793
795
796
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2276
@ Success
Used for reporting a successful operation.
Definition qgis.h:164
@ Generated
A generated relation is a child of a polymorphic relation.
Definition qgis.h:4537
@ Normal
A normal relation.
Definition qgis.h:4536
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:124
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:71
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.