QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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
6  email : [email protected]
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 
20 #include "qgsfeatureiterator.h"
21 #include "qgsexpression.h"
22 #include "qgsfeature.h"
23 #include "qgsfeatureselectiondlg.h"
24 #include "qgsrelation.h"
25 #include "qgspolymorphicrelation.h"
26 #include "qgsvectorlayertools.h"
27 #include "qgsproject.h"
28 #include "qgstransactiongroup.h"
29 #include "qgsvectorlayerutils.h"
30 
31 #include <QMessageBox>
32 #include <QPushButton>
33 
34 
35 QgsAbstractRelationEditorWidget::QgsAbstractRelationEditorWidget( const QVariantMap &config, QWidget *parent )
36  : QWidget( parent )
37 {
38  Q_UNUSED( config );
39 }
40 
42 {
44 
46  mFeature = feature;
47 
48  setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
49 
50  updateTitle();
52  updateUi();
53 }
54 
55 void QgsAbstractRelationEditorWidget::setRelations( const QgsRelation &relation, const QgsRelation &nmrelation )
56 {
57 
58  beforeSetRelations( relation, nmrelation );
59 
61  mNmRelation = nmrelation;
62 
63  if ( !mRelation.isValid() )
64  {
66  return;
67  }
68 
70 
71  const auto transactionGroups = QgsProject::instance()->transactionGroups();
72  for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
73  {
74  if ( mNmRelation.isValid() )
75  {
76  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
77  it.value()->layers().contains( mRelation.referencingLayer() ) &&
78  it.value()->layers().contains( mNmRelation.referencedLayer() ) )
80  }
81  else
82  {
83  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
84  it.value()->layers().contains( mRelation.referencingLayer() ) )
86  }
87  }
88 
89  updateTitle();
90 
91  setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
92 
94  updateUi();
95 }
96 
98 {
99  mEditorContext = context;
100 }
101 
103 {
104  return mEditorContext;
105 }
106 
107 void QgsAbstractRelationEditorWidget::setFeature( const QgsFeature &feature, bool update )
108 {
109  mFeature = feature;
110 
112 
113  if ( update )
114  updateUi();
115 }
116 
117 void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
118 {
120 }
121 
123 {
124  return mNmRelationId;
125 }
126 
128 {
129  return mLabel;
130 }
131 
132 void QgsAbstractRelationEditorWidget::setLabel( const QString &label )
133 {
134  mLabel = label;
135 
136  updateTitle();
137 }
138 
140 {
141  return mShowLabel;
142 }
143 
145 {
147 
148  updateTitle();
149 }
150 
152 {
154 }
155 
157 {
159 }
160 
162 {
163  if ( mShowLabel && !mLabel.isEmpty() )
164  {
165  setTitle( mLabel );
166  }
167  else if ( mShowLabel && mRelation.isValid() )
168  {
169  setTitle( mRelation.name() );
170  }
171  else
172  {
173  setTitle( QString() );
174  }
175 }
176 
178 {
179  return mFeature;
180 }
181 
183 {
184  if ( state )
185  {
187  if ( mNmRelation.isValid() )
189  }
190  else
191  {
193  if ( mNmRelation.isValid() )
195  }
196 }
197 
199 {
201  if ( mNmRelation.isValid() )
203 }
204 
206 {
207  QgsAttributeMap keyAttrs;
208 
210 
211  if ( mNmRelation.isValid() )
212  {
213  // only normal relations support m:n relation
214  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
215 
216  // n:m Relation: first let the user create a new feature on the other table
217  // and autocreate a new linking feature.
218  QgsFeature f;
219  if ( vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &f ) )
220  {
221  // Fields of the linking table
222  const QgsFields fields = mRelation.referencingLayer()->fields();
223 
224  // Expression context for the linking table
226 
227  QgsAttributeMap linkAttributes;
228  const auto constFieldPairs = mRelation.fieldPairs();
229  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
230  {
231  int index = fields.indexOf( fieldPair.first );
232  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
233  }
234 
235  const auto constNmFieldPairs = mNmRelation.fieldPairs();
236  for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
237  {
238  int index = fields.indexOf( fieldPair.first );
239  linkAttributes.insert( index, f.attribute( fieldPair.second ) );
240  }
242 
244 
245  updateUi();
246  }
247  }
248  else
249  {
252  {
254  keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
255  }
256 
257  const auto constFieldPairs = mRelation.fieldPairs();
258  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
259  {
260  keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
261  }
262 
263  vlTools->addFeature( mRelation.referencingLayer(), keyAttrs, geometry );
264  }
265 }
266 
268 {
269  deleteFeatures( QgsFeatureIds() << fid );
270 }
271 
273 {
274  bool deleteFeatures = true;
275 
276  QgsVectorLayer *layer;
277  if ( mNmRelation.isValid() )
278  {
279  // only normal relations support m:n relation
280  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
281 
282  layer = mNmRelation.referencedLayer();
283 
284  // When deleting a linked feature within an N:M relation,
285  // check if the feature is linked to more than just one feature.
286  // In case it is linked more than just once, ask the user for confirmation
287  // as it is likely he was not aware of the implications and might delete
288  // there may be several linking entries deleted along.
289 
290  QgsFeatureRequest deletedFeaturesRequest;
291  deletedFeaturesRequest.setFilterFids( fids );
292  deletedFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
293  deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
294 
295  QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
296  QStringList deletedFeaturesPks;
298  while ( deletedFeatures.nextFeature( feature ) )
299  {
300  deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
301  }
302 
303  QgsFeatureRequest linkingFeaturesRequest;
304  linkingFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
305  linkingFeaturesRequest.setNoAttributes();
306 
307  QString linkingFeaturesRequestExpression;
308  if ( !deletedFeaturesPks.empty() )
309  {
310  linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
311  linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
312 
313  QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
314 
315  int relatedLinkingFeaturesCount = 0;
316  while ( relatedLinkingFeatures.nextFeature( feature ) )
317  {
318  relatedLinkingFeaturesCount++;
319  }
320 
321  if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
322  {
323  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(), QString::number( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ), QMessageBox::NoButton, this );
324  messageBox.addButton( QMessageBox::Cancel );
325  QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
326 
327  messageBox.exec();
328  if ( messageBox.clickedButton() != deleteButton )
329  deleteFeatures = false;
330  }
331  else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
332  {
333  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( QString::number( deletedFeaturesPks.size() ), mNmRelation.referencedLayer()->name(), QString::number( relatedLinkingFeaturesCount ), mRelation.referencedLayer()->name() ), QMessageBox::NoButton, this );
334  messageBox.addButton( QMessageBox::Cancel );
335  QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
336 
337  messageBox.exec();
338  if ( messageBox.clickedButton() != deleteButton )
339  deleteFeatures = false;
340  }
341  }
342  }
343  else
344  {
345  layer = mRelation.referencingLayer();
346  }
347 
349  if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
350  {
351  QString childrenInfo;
352  int childrenCount = 0;
353  const auto infoContextLayers = infoContext.layers();
354  for ( QgsVectorLayer *chl : infoContextLayers )
355  {
356  childrenCount += infoContext.duplicatedFeatures( chl ).size();
357  childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
358  }
359 
360  // for extra safety to make sure we know that the delete can have impact on children and joins
361  int res = QMessageBox::question( this, tr( "Delete at least %1 feature(s) on other layer(s)" ).arg( childrenCount ),
362  tr( "Delete %1 feature(s) on layer \"%2\", %3 as well\nand all of its other descendants.\nDelete these features?" ).arg( fids.count() ).arg( layer->name() ).arg( childrenInfo ),
363  QMessageBox::Yes | QMessageBox::No );
364  if ( res != QMessageBox::Yes )
365  deleteFeatures = false;
366  }
367 
368  if ( deleteFeatures )
369  {
371  layer->deleteFeatures( fids, &context );
372  const auto contextLayers = context.handledLayers();
373  if ( contextLayers.size() > 1 )
374  {
375  int deletedCount = 0;
376  QString feedbackMessage;
377  for ( QgsVectorLayer *contextLayer : contextLayers )
378  {
379  feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
380  deletedCount += context.handledFeatures( contextLayer ).size();
381  }
382  mEditorContext.mainMessageBar()->pushMessage( tr( "%1 features deleted: %2" ).arg( deletedCount ).arg( feedbackMessage ), Qgis::Success );
383  }
384 
385  updateUi();
386  }
387 }
388 
390 {
391  QgsVectorLayer *layer = nullptr;
392 
393  if ( mNmRelation.isValid() )
394  {
395  // only normal relations support m:n relation
396  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
397 
398  layer = mNmRelation.referencedLayer();
399  }
400  else
401  layer = mRelation.referencingLayer();
402 
403  QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
404  selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
405 
407  selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
408 
409  connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
410  selectionDlg->show();
411 }
412 
414 {
415  QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
416  if ( mNmRelation.isValid() )
417  {
418  // only normal relations support m:n relation
419  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
420 
423  .setFilterFids( selectionDlg->selectedFeatures() )
425 
426  QgsFeature relatedFeature;
427 
428  QgsFeatureList newFeatures;
429 
430  // Fields of the linking table
431  const QgsFields fields = mRelation.referencingLayer()->fields();
432 
433  // Expression context for the linking table
435 
436  QgsAttributeMap linkAttributes;
437  const auto constFieldPairs = mRelation.fieldPairs();
438  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
439  {
440  int index = fields.indexOf( fieldPair.first );
441  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
442  }
443 
444  while ( it.nextFeature( relatedFeature ) )
445  {
446  const auto constFieldPairs = mNmRelation.fieldPairs();
447  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
448  {
449  int index = fields.indexOf( fieldPair.first );
450  linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
451  }
453 
454  newFeatures << linkFeature;
455  }
456 
457  mRelation.referencingLayer()->addFeatures( newFeatures );
458  QgsFeatureIds ids;
459  const auto constNewFeatures = newFeatures;
460  for ( const QgsFeature &f : constNewFeatures )
461  ids << f.id();
463  }
464  else
465  {
466  QMap<int, QVariant> keys;
467  const auto constFieldPairs = mRelation.fieldPairs();
468  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
469  {
470  int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
471  QVariant val = mFeature.attribute( fieldPair.referencedField() );
472  keys.insert( idx, val );
473  }
474 
475  const auto constSelectedFeatures = selectionDlg->selectedFeatures();
476  for ( QgsFeatureId fid : constSelectedFeatures )
477  {
478  QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
480  {
482 
483  Q_ASSERT( mRelation.polymorphicRelation().isValid() );
484 
486  referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
488  }
489 
490  QMapIterator<int, QVariant> it( keys );
491  while ( it.hasNext() )
492  {
493  it.next();
494  referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
495  }
496  }
497  }
498 
499  updateUi();
500 }
501 
503 {
504  unlinkFeatures( QgsFeatureIds() << fid );
505 }
506 
508 {
509  if ( mNmRelation.isValid() )
510  {
511  // only normal relations support m:n relation
512  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
513 
516  .setFilterFids( fids )
517  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
518 
519  QgsFeature f;
520 
521  QStringList filters;
522 
523  while ( selectedIterator.nextFeature( f ) )
524  {
525  filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
526  }
527 
528  QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
530  filters.join( QLatin1String( " OR " ) ) );
531 
533  .setNoAttributes()
534  .setFilterExpression( filter ) );
535 
536  QgsFeatureIds fids;
537 
538  while ( linkedIterator.nextFeature( f ) )
539  {
540  fids << f.id();
541  QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
542  }
543 
545 
546  updateUi();
547  }
548  else
549  {
550  QMap<int, QgsField> keyFields;
551  const auto constFieldPairs = mRelation.fieldPairs();
552  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
553  {
554  int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
555  if ( idx < 0 )
556  {
557  QgsDebugMsg( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
558  return;
559  }
560  QgsField fld = mRelation.referencingLayer()->fields().at( idx );
561  keyFields.insert( idx, fld );
562  }
563 
564  const auto constFeatureids = fids;
565  for ( QgsFeatureId fid : constFeatureids )
566  {
567  QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
569  {
571 
572  Q_ASSERT( mRelation.polymorphicRelation().isValid() );
573 
575  referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
576  referencingLayer->fields().field( polyRel.referencedLayerField() ).type() );
577  }
578 
579  QMapIterator<int, QgsField> it( keyFields );
580  while ( it.hasNext() )
581  {
582  it.next();
583  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
584  }
585  }
586  }
587 }
588 
590 {}
591 
592 void QgsAbstractRelationEditorWidget::setTitle( const QString &title )
593 {
594  Q_UNUSED( title )
595 }
596 
598 {
599  Q_UNUSED( newRelation )
600  Q_UNUSED( newFeature )
601 }
602 
604 {}
605 
606 void QgsAbstractRelationEditorWidget::beforeSetRelations( const QgsRelation &newRelation, const QgsRelation &newNmRelation )
607 {
608  Q_UNUSED( newRelation )
609  Q_UNUSED( newNmRelation )
610 }
611 
613 {}
614 
616 {
617  duplicateFeatures( QgsFeatureIds() << fid );
618 }
619 
621 {
623 
624  QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
625  QgsFeature f;
626  while ( fit.nextFeature( f ) )
627  {
628  QgsVectorLayerUtils::QgsDuplicateFeatureContext duplicatedFeatureContext;
629  QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
630  }
631 }
632 
633 
635 
636 
638  : QWidget( parent )
639  , mRelation( relation )
640 {
641 }
642 
644 {
645  return mLayer;
646 }
647 
649 {
650  return mRelation;
651 }
652 
653 
655 
656 
658 {
659 }
@ Success
Definition: qgis.h:93
QgsRelation relation() const
Returns the 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 toggleEditing(bool state)
Toggles editing state of the widget.
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.
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 void setTitle(const QString &title)
Sets the title of the widget, if it is wrapped within a QgsCollapsibleGroupBox Check QgsRealationEdit...
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.
void linkFeature()
Links a new feature to the relation.
void updateTitle()
Updates the title contents to reflect the current state of the widget.
QgsAbstractRelationEditorWidget(const QVariantMap &config, QWidget *parent=nullptr)
Constructor.
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...
void addFeature(const QgsGeometry &geometry=QgsGeometry())
Adds a new feature with given geometry.
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.
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.
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.
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.
QgsMessageBar * mainMessageBar()
Returns the main message bar.
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
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)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsExpression * filterExpression() const
Returns the filter expression if set.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will 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.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
const QgsFeatureIds & selectedFeatures()
Gets the selected features.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:287
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QVariant::Type type
Definition: qgsfield.h:58
Container of fields for a vector layer.
Definition: qgsfields.h:45
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:168
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QString name
Definition: qgsmaplayer.h:88
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::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.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:501
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
Defines a relation between matching fields of the two involved tables of a relation.
Definition: qgsrelation.h:89
QString name
Definition: qgsrelation.h:49
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:48
@ Generated
A generated relation is a child of a polymorphic relation.
Definition: qgsrelation.h:62
@ Normal
A normal relation.
Definition: qgsrelation.h:61
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
RelationType type() const
Returns the type of the relation.
QgsPolymorphicRelation polymorphicRelation
Definition: qgsrelation.h:52
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:47
bool isValid
Definition: qgsrelation.h:50
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
Methods in this class are used to handle basic operations on vector layers.
virtual bool startEditing(QgsVectorLayer *layer) const =0
This will be called, whenever a vector layer should be switched to edit mode.
virtual bool saveEdits(QgsVectorLayer *layer) const =0
Should be called, when the features should be committed but the editing session is not ended.
virtual bool addFeature(QgsVectorLayer *layer, const QgsAttributeMap &defaultValues=QgsAttributeMap(), const QgsGeometry &defaultGeometry=QgsGeometry(), QgsFeature *feature=nullptr) const =0
This method should/will be called, whenever a new feature will be added to the layer.
virtual bool stopEditing(QgsVectorLayer *layer, bool allowCancel=true) const =0
Will be called, when an editing session is ended and the features should be committed.
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features.
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
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).
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects matching features using a list of feature IDs.
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:614
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(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.