QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsabstractrelationeditorwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsabstractrelationeditorwidget.cpp
3 ----------------------
4 begin : October 2020
5 copyright : (C) 2020 by Ivan Ivanov
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "moc_qgsabstractrelationeditorwidget.cpp"
20
21#include "qgsfeatureiterator.h"
22#include "qgsexpression.h"
24#include "qgsfeature.h"
26#include "qgsrelation.h"
27#include "qgsrelationmanager.h"
29#include "qgsvectorlayertools.h"
30#include "qgsproject.h"
31#include "qgstransactiongroup.h"
32#include "qgsvectorlayerutils.h"
33
34#include <QMessageBox>
35#include <QPushButton>
36
37QgsAbstractRelationEditorWidget::QgsAbstractRelationEditorWidget( const QVariantMap &config, QWidget *parent )
38 : QWidget( parent )
39{
40 Q_UNUSED( config );
41}
42
44{
46
48 mFeatureList.clear();
49 mFeatureList.append( feature );
50
51 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
52
54 updateUi();
55}
56
58{
59 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() ) && it.value()->layers().contains( mRelation.referencingLayer() ) && it.value()->layers().contains( mNmRelation.referencedLayer() ) )
79 }
80 else
81 {
82 if ( it.value()->layers().contains( mRelation.referencedLayer() ) && it.value()->layers().contains( mRelation.referencingLayer() ) )
84 }
85 }
86
87 setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
88
90 updateUi();
91}
92
97
102
104{
105 mFeatureList.clear();
106 mFeatureList.append( feature );
107
109
110 if ( update )
111 updateUi();
112}
113
115{
116 mFeatureList.clear();
117
118 QgsFeatureIterator featureIterator = mRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
120 while ( featureIterator.nextFeature( feature ) )
121 mFeatureList.append( feature );
122
123 if ( !mFeatureList.isEmpty() )
125}
126
127void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
128{
129 const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
130 beforeSetRelations( mRelation, nmrelation );
131 mNmRelation = nmrelation;
133 updateUi();
134}
135
137{
138 return mNmRelation.id();
139}
140
142{
143 return QString();
144}
145
147{
148 Q_UNUSED( label )
149}
150
152{
153 return false;
154}
155
157{
158 Q_UNUSED( showLabel )
159}
160
165
170
174
176{
177 return mFeatureList.size() > 1;
178}
179
181{
182 if ( !mFeatureList.isEmpty() )
183 return mFeatureList.first();
184
185 return QgsFeature();
186}
187
189{
190 return mFeatureList;
191}
192
208
215
217{
218 QgsAttributeMap keyAttrs;
219
221
222 // Fields of the linking table
223 const QgsFields fields = mRelation.referencingLayer()->fields();
224
225 QgsFeatureIds addedFeatureIds;
226
227 // For generated relations insert the referenced layer field
228 switch ( mRelation.type() )
229 {
231 {
233 keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
234 break;
235 }
236
238 break;
239 }
240
241 if ( mNmRelation.isValid() )
242 {
243 // only normal relations support m:n relation
245
246 // n:m Relation: first let the user create a new feature on the other table
247 // and autocreate a new linking feature.
248 QgsFeature finalFeature;
249 if ( !vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &finalFeature, this, false, true ) )
250 return QgsFeatureIds();
251
252 addedFeatureIds.insert( finalFeature.id() );
253
254 // Expression context for the linking table
256
257 QgsAttributeMap linkAttributes = keyAttrs;
258 const auto constFieldPairs = mRelation.fieldPairs();
259
261 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
262 {
263 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
264 {
265 const int index = fields.indexOf( fieldPair.first );
266 linkAttributes.insert( index, editingFeature.attribute( fieldPair.second ) );
267 }
268
269 const auto constNmFieldPairs = mNmRelation.fieldPairs();
270 for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
271 {
272 const int index = fields.indexOf( fieldPair.first );
273 linkAttributes.insert( index, finalFeature.attribute( fieldPair.second ) );
274 }
275
276 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
277 }
278 QgsFeatureList linkFeatureList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
279 mRelation.referencingLayer()->addFeatures( linkFeatureList );
280 }
281 else
282 {
283 const auto constFieldPairs = mRelation.fieldPairs();
284 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
285 keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeatureList.first().attribute( fieldPair.referencedField() ) );
286
288 context.setParentWidget( this );
289 context.setShowModal( false );
290 context.setHideParent( true );
291 std::unique_ptr<QgsExpressionContextScope> scope( QgsExpressionContextUtils::parentFormScope( mFeatureList.first(), mEditorContext.attributeFormModeString() ) );
292 context.setAdditionalExpressionContextScope( scope.get() );
294 if ( !vlTools->addFeatureV2( mRelation.referencingLayer(), keyAttrs, geometry, &linkFeature, context ) )
295 return QgsFeatureIds();
296
297 addedFeatureIds.insert( linkFeature.id() );
298
299 // In multiedit add to other features to but without dialog
300 for ( const QgsFeature &feature : std::as_const( mFeatureList ) )
301 {
302 // First feature already added
303 if ( mFeatureList.first() == feature )
304 continue;
305
306 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
307 linkFeature.setAttribute( fields.indexFromName( fieldPair.referencingField() ), feature.attribute( fieldPair.referencedField() ) );
308
310 addedFeatureIds.insert( linkFeature.id() );
311 }
312 }
313
314 updateUi();
315
317
318 return addedFeatureIds;
319}
320
327
329{
330 bool deleteFeatures = true;
331
332 QgsVectorLayer *layer;
333 if ( mNmRelation.isValid() )
334 {
335 // only normal relations support m:n relation
337
339
340 // When deleting a linked feature within an N:M relation,
341 // check if the feature is linked to more than just one feature.
342 // In case it is linked more than just once, ask the user for confirmation
343 // as it is likely he was not aware of the implications and might delete
344 // there may be several linking entries deleted along.
345
346 QgsFeatureRequest deletedFeaturesRequest;
347 deletedFeaturesRequest.setFilterFids( fids );
348 deletedFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
349 deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
350
351 QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
352 QStringList deletedFeaturesPks;
354 while ( deletedFeatures.nextFeature( feature ) )
355 {
356 deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
357 }
358
359 QgsFeatureRequest linkingFeaturesRequest;
360 linkingFeaturesRequest.setFlags( Qgis::FeatureRequestFlag::NoGeometry );
361 linkingFeaturesRequest.setNoAttributes();
362
363 QString linkingFeaturesRequestExpression;
364 if ( !deletedFeaturesPks.empty() )
365 {
366 linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
367 linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
368
369 QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
370
371 int relatedLinkingFeaturesCount = 0;
372 while ( relatedLinkingFeatures.nextFeature( feature ) )
373 {
374 relatedLinkingFeaturesCount++;
375 }
376
377 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
378 {
379 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 );
380 messageBox.addButton( QMessageBox::Cancel );
381 QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
382
383 messageBox.exec();
384 if ( messageBox.clickedButton() != deleteButton )
385 deleteFeatures = false;
386 }
387 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
388 {
389 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 );
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 }
398 }
399 else
400 {
401 layer = mRelation.referencingLayer();
402 }
403
405 if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
406 {
407 QString childrenInfo;
408 int childrenCount = 0;
409 const auto infoContextLayers = infoContext.layers();
410 for ( QgsVectorLayer *chl : infoContextLayers )
411 {
412 childrenCount += infoContext.duplicatedFeatures( chl ).size();
413 childrenInfo += ( tr( "%n feature(s) on layer \"%1\", ", nullptr, infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
414 }
415
416 // for extra safety to make sure we know that the delete can have impact on children and joins
417 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 );
418 if ( res != QMessageBox::Yes )
419 deleteFeatures = false;
420 }
421
422 if ( deleteFeatures )
423 {
425 layer->deleteFeatures( fids, &context );
426 const auto contextLayers = context.handledLayers();
427 if ( contextLayers.size() > 1 )
428 {
429 int deletedCount = 0;
430 QString feedbackMessage;
431 for ( QgsVectorLayer *contextLayer : contextLayers )
432 {
433 feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
434 deletedCount += context.handledFeatures( contextLayer ).size();
435 }
436 mEditorContext.mainMessageBar()->pushMessage( tr( "%n feature(s) deleted: %2", nullptr, deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
437 }
438
439 updateUi();
440
442 }
443}
444
445void QgsAbstractRelationEditorWidget::linkFeature( const QString &filterExpression )
446{
447 QgsVectorLayer *layer = nullptr;
448
449 if ( mNmRelation.isValid() )
450 {
451 // only normal relations support m:n relation
453
455 }
456 else
457 {
458 if ( multiEditModeActive() )
459 {
460 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
461 return;
462 }
463
464 layer = mRelation.referencingLayer();
465 }
466
467 QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
468 selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
469
471 selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
472 selectionDlg->setFilterExpression( filterExpression, QgsAttributeForm::ReplaceFilter );
473
474 connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
475 selectionDlg->show();
476}
477
479{
480 QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
481
482 if ( mNmRelation.isValid() )
483 {
484 // only normal relations support m:n relation
486
487 // Fields of the linking table
488 const QgsFields fields = mRelation.referencingLayer()->fields();
489
490 QgsAttributeMap linkAttributes;
491
492 switch ( mRelation.type() )
493 {
495 {
497 Q_ASSERT( polyRel.isValid() );
498
499 linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
500 break;
501 }
503 break;
504 }
505
507 QgsFeature relatedFeature;
510 .setFilterFids( selectionDlg->selectedFeatures() )
512 );
513 while ( it.nextFeature( relatedFeature ) )
514 {
515 for ( const QgsFeature &editFeature : std::as_const( mFeatureList ) )
516 {
517 {
518 const auto constFieldPairs = mRelation.fieldPairs();
519 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
520 {
521 const int index = fields.indexOf( fieldPair.first );
522 linkAttributes.insert( index, editFeature.attribute( fieldPair.second ) );
523 }
524 }
525
526 const auto constFieldPairs = mNmRelation.fieldPairs();
527 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
528 {
529 const int index = fields.indexOf( fieldPair.first );
530 linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
531 }
532
533 linkFeatureDataList.append( QgsVectorLayerUtils::QgsFeatureData( QgsGeometry(), linkAttributes ) );
534 }
535 }
536
537 // Expression context for the linking table
539
540 QgsFeatureList linkFeaturesList = QgsVectorLayerUtils::createFeatures( mRelation.referencingLayer(), linkFeatureDataList, &context );
541
542 mRelation.referencingLayer()->addFeatures( linkFeaturesList );
543 QgsFeatureIds ids;
544 const auto constNewFeatures = linkFeaturesList;
545 for ( const QgsFeature &f : constNewFeatures )
546 ids << f.id();
548 }
549 else
550 {
551 if ( multiEditModeActive() )
552 {
553 QgsLogger::warning( tr( "For 1:n relations is not possible to link to multiple features" ) );
554 return;
555 }
556
557 QMap<int, QVariant> keys;
558 const auto constFieldPairs = mRelation.fieldPairs();
559 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
560 {
561 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
562 const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
563 keys.insert( idx, val );
564 }
565
566 const auto constSelectedFeatures = selectionDlg->selectedFeatures();
567 for ( const QgsFeatureId fid : constSelectedFeatures )
568 {
569 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
570 switch ( mRelation.type() )
571 {
573 {
575
576 Q_ASSERT( polyRel.isValid() );
577
579 break;
580 }
582 break;
583 }
584
585 QMapIterator<int, QVariant> it( keys );
586 while ( it.hasNext() )
587 {
588 it.next();
589 referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
590 }
591 }
592 }
593
594 updateUi();
595
597}
598
603
605{
606 if ( mNmRelation.isValid() )
607 {
608 // only normal relations support m:n relation
610
613 .setFilterFids( fids )
614 .setSubsetOfAttributes( mNmRelation.referencedFields() )
615 );
616
617 QgsFeature f;
618
619 QStringList filters;
620
621 while ( selectedIterator.nextFeature( f ) )
622 {
623 filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
624 }
625
626 QStringList featureFilters;
627 for ( const QgsFeature &editingFeature : std::as_const( mFeatureList ) )
628 {
629 featureFilters.append( mRelation.getRelatedFeaturesRequest( editingFeature ).filterExpression()->expression() );
630 }
631
632 const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg( featureFilters.join( QLatin1String( " OR " ) ), filters.join( QLatin1String( " OR " ) ) );
633
635 .setNoAttributes()
636 .setFilterExpression( filter ) );
637
638 QgsFeatureIds fids;
639
640 while ( linkedIterator.nextFeature( f ) )
641 {
642 fids << f.id();
643 QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
644 }
645
647 }
648 else
649 {
650 QMap<int, QgsField> keyFields;
651 const auto constFieldPairs = mRelation.fieldPairs();
652 for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
653 {
654 const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
655 if ( idx < 0 )
656 {
657 QgsDebugError( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
658 return;
659 }
660 const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
661 keyFields.insert( idx, fld );
662 }
663
664 const auto constFeatureids = fids;
665 for ( const QgsFeatureId fid : constFeatureids )
666 {
667 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
668 switch ( mRelation.type() )
669 {
671 {
673
674 Q_ASSERT( mRelation.polymorphicRelation().isValid() );
675
677 break;
678 }
680 break;
681 }
682
683 QMapIterator<int, QgsField> it( keyFields );
684 while ( it.hasNext() )
685 {
686 it.next();
688 }
689 }
690 }
691
692 updateUi();
693
695}
696
699
701{
702 Q_UNUSED( title )
703}
704
706{
707 Q_UNUSED( newRelation )
708 Q_UNUSED( newFeature )
709}
710
713
715{
716 Q_UNUSED( newRelation )
717 Q_UNUSED( newNmRelation )
718}
719
722
729
731{
733
734 QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
735 QgsFeature f;
736 while ( fit.nextFeature( f ) )
737 {
739 QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
740 }
741
743}
744
746{
747 updateUi();
748}
749
750
752
753
755 : QWidget( parent )
756 , mRelation( relation )
757{
758}
759
764
766{
767 return mRelation;
768}
769
771{
772 mNmRelation = nmRelation;
773}
774
776{
777 return mNmRelation;
778}
779
780
782
783
@ 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.