QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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 "qgsrelationmanager.h"
26 #include "qgspolymorphicrelation.h"
27 #include "qgsvectorlayertools.h"
28 #include "qgsproject.h"
29 #include "qgstransactiongroup.h"
30 #include "qgsvectorlayerutils.h"
31 
32 #include <QMessageBox>
33 #include <QPushButton>
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 
51  updateUi();
52 }
53 
54 void QgsAbstractRelationEditorWidget::setRelations( const QgsRelation &relation, const QgsRelation &nmrelation )
55 {
56 
57  beforeSetRelations( relation, nmrelation );
58 
60  mNmRelation = nmrelation;
61 
62  if ( !mRelation.isValid() )
63  {
65  return;
66  }
67 
69 
70  const auto transactionGroups = QgsProject::instance()->transactionGroups();
71  for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
72  {
73  if ( mNmRelation.isValid() )
74  {
75  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
76  it.value()->layers().contains( mRelation.referencingLayer() ) &&
77  it.value()->layers().contains( mNmRelation.referencedLayer() ) )
79  }
80  else
81  {
82  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
83  it.value()->layers().contains( mRelation.referencingLayer() ) )
85  }
86  }
87 
88  setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
89 
91  updateUi();
92 }
93 
95 {
96  mEditorContext = context;
97 }
98 
100 {
101  return mEditorContext;
102 }
103 
104 void QgsAbstractRelationEditorWidget::setFeature( const QgsFeature &feature, bool update )
105 {
106  mFeature = feature;
107 
109 
110  if ( update )
111  updateUi();
112 }
113 
114 void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
115 {
116  const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
117  beforeSetRelations( mRelation, nmrelation );
118  mNmRelation = nmrelation;
120  updateUi();
121 }
122 
124 {
125  return mNmRelation.id();
126 }
127 
129 {
130  return QString();
131 }
132 
133 void QgsAbstractRelationEditorWidget::setLabel( const QString &label )
134 {
135  Q_UNUSED( label )
136 }
137 
139 {
140  return false;
141 }
142 
144 {
145  Q_UNUSED( showLabel )
146 }
147 
149 {
151 }
152 
154 {
156 }
157 
159 {
160 }
161 
163 {
164  return mFeature;
165 }
166 
168 {
169  if ( state )
170  {
172  if ( mNmRelation.isValid() )
174  }
175  else
176  {
178  if ( mNmRelation.isValid() )
180  }
181 }
182 
184 {
186  if ( mNmRelation.isValid() )
188 }
189 
191 {
192  QgsAttributeMap keyAttrs;
193 
195 
196  // Fields of the linking table
197  const QgsFields fields = mRelation.referencingLayer()->fields();
198 
199  // For generated relations insert the referenced layer field
201  {
203  keyAttrs.insert( fields.indexFromName( polyRel.referencedLayerField() ), polyRel.layerRepresentation( mRelation.referencedLayer() ) );
204  }
205 
206  if ( mNmRelation.isValid() )
207  {
208  // only normal relations support m:n relation
209  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
210 
211  // n:m Relation: first let the user create a new feature on the other table
212  // and autocreate a new linking feature.
213  QgsFeature f;
214  if ( !vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &f ) )
215  return;
216 
217  // Expression context for the linking table
219 
220  QgsAttributeMap linkAttributes = keyAttrs;
221  const auto constFieldPairs = mRelation.fieldPairs();
222  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
223  {
224  const int index = fields.indexOf( fieldPair.first );
225  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
226  }
227 
228  const auto constNmFieldPairs = mNmRelation.fieldPairs();
229  for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
230  {
231  const int index = fields.indexOf( fieldPair.first );
232  linkAttributes.insert( index, f.attribute( fieldPair.second ) );
233  }
235 
237  }
238  else
239  {
240  const auto constFieldPairs = mRelation.fieldPairs();
241  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
242  {
243  keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
244  }
245 
246  if ( !vlTools->addFeature( mRelation.referencingLayer(), keyAttrs, geometry ) )
247  return;
248  }
249 
250  updateUi();
251 
252  emit relatedFeaturesChanged();
253 }
254 
256 {
257  deleteFeatures( QgsFeatureIds() << fid );
258 
259  emit relatedFeaturesChanged();
260 }
261 
263 {
264  bool deleteFeatures = true;
265 
266  QgsVectorLayer *layer;
267  if ( mNmRelation.isValid() )
268  {
269  // only normal relations support m:n relation
270  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
271 
272  layer = mNmRelation.referencedLayer();
273 
274  // When deleting a linked feature within an N:M relation,
275  // check if the feature is linked to more than just one feature.
276  // In case it is linked more than just once, ask the user for confirmation
277  // as it is likely he was not aware of the implications and might delete
278  // there may be several linking entries deleted along.
279 
280  QgsFeatureRequest deletedFeaturesRequest;
281  deletedFeaturesRequest.setFilterFids( fids );
282  deletedFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
283  deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
284 
285  QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
286  QStringList deletedFeaturesPks;
288  while ( deletedFeatures.nextFeature( feature ) )
289  {
290  deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
291  }
292 
293  QgsFeatureRequest linkingFeaturesRequest;
294  linkingFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
295  linkingFeaturesRequest.setNoAttributes();
296 
297  QString linkingFeaturesRequestExpression;
298  if ( !deletedFeaturesPks.empty() )
299  {
300  linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
301  linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
302 
303  QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
304 
305  int relatedLinkingFeaturesCount = 0;
306  while ( relatedLinkingFeatures.nextFeature( feature ) )
307  {
308  relatedLinkingFeaturesCount++;
309  }
310 
311  if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
312  {
313  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 );
314  messageBox.addButton( QMessageBox::Cancel );
315  QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
316 
317  messageBox.exec();
318  if ( messageBox.clickedButton() != deleteButton )
319  deleteFeatures = false;
320  }
321  else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
322  {
323  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 );
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  }
332  }
333  else
334  {
335  layer = mRelation.referencingLayer();
336  }
337 
339  if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, fids, QgsProject::instance(), infoContext ) )
340  {
341  QString childrenInfo;
342  int childrenCount = 0;
343  const auto infoContextLayers = infoContext.layers();
344  for ( QgsVectorLayer *chl : infoContextLayers )
345  {
346  childrenCount += infoContext.duplicatedFeatures( chl ).size();
347  childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
348  }
349 
350  // for extra safety to make sure we know that the delete can have impact on children and joins
351  const int res = QMessageBox::question( this, tr( "Delete at least %1 feature(s) on other layer(s)" ).arg( childrenCount ),
352  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 ),
353  QMessageBox::Yes | QMessageBox::No );
354  if ( res != QMessageBox::Yes )
355  deleteFeatures = false;
356  }
357 
358  if ( deleteFeatures )
359  {
361  layer->deleteFeatures( fids, &context );
362  const auto contextLayers = context.handledLayers();
363  if ( contextLayers.size() > 1 )
364  {
365  int deletedCount = 0;
366  QString feedbackMessage;
367  for ( QgsVectorLayer *contextLayer : contextLayers )
368  {
369  feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
370  deletedCount += context.handledFeatures( contextLayer ).size();
371  }
372  mEditorContext.mainMessageBar()->pushMessage( tr( "%1 features deleted: %2" ).arg( deletedCount ).arg( feedbackMessage ), Qgis::MessageLevel::Success );
373  }
374 
375  updateUi();
376 
377  emit relatedFeaturesChanged();
378  }
379 }
380 
382 {
383  QgsVectorLayer *layer = nullptr;
384 
385  if ( mNmRelation.isValid() )
386  {
387  // only normal relations support m:n relation
388  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
389 
390  layer = mNmRelation.referencedLayer();
391  }
392  else
393  layer = mRelation.referencingLayer();
394 
395  QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
396  selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
397 
399  selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
400 
401  connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
402  selectionDlg->show();
403 }
404 
406 {
407  QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
408  if ( mNmRelation.isValid() )
409  {
410  // only normal relations support m:n relation
411  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
412 
415  .setFilterFids( selectionDlg->selectedFeatures() )
417 
418  QgsFeature relatedFeature;
419 
420  QgsFeatureList newFeatures;
421 
422  // Fields of the linking table
423  const QgsFields fields = mRelation.referencingLayer()->fields();
424 
425  // Expression context for the linking table
427 
428  QgsAttributeMap linkAttributes;
429 
431  {
433  Q_ASSERT( polyRel.isValid() );
434 
435  linkAttributes.insert( fields.indexFromName( polyRel.referencedLayerField() ),
437  }
438 
439  const auto constFieldPairs = mRelation.fieldPairs();
440  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
441  {
442  const int index = fields.indexOf( fieldPair.first );
443  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
444  }
445 
446  while ( it.nextFeature( relatedFeature ) )
447  {
448  const auto constFieldPairs = mNmRelation.fieldPairs();
449  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
450  {
451  const int index = fields.indexOf( fieldPair.first );
452  linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
453  }
455 
456  newFeatures << linkFeature;
457  }
458 
459  mRelation.referencingLayer()->addFeatures( newFeatures );
460  QgsFeatureIds ids;
461  const auto constNewFeatures = newFeatures;
462  for ( const QgsFeature &f : constNewFeatures )
463  ids << f.id();
465  }
466  else
467  {
468  QMap<int, QVariant> keys;
469  const auto constFieldPairs = mRelation.fieldPairs();
470  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
471  {
472  const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
473  const QVariant val = mFeature.attribute( fieldPair.referencedField() );
474  keys.insert( idx, val );
475  }
476 
477  const auto constSelectedFeatures = selectionDlg->selectedFeatures();
478  for ( const QgsFeatureId fid : constSelectedFeatures )
479  {
480  QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
482  {
484 
485  Q_ASSERT( polyRel.isValid() );
486 
488  referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
490  }
491 
492  QMapIterator<int, QVariant> it( keys );
493  while ( it.hasNext() )
494  {
495  it.next();
496  referencingLayer->changeAttributeValue( fid, it.key(), it.value() );
497  }
498  }
499  }
500 
501  updateUi();
502 
503  emit relatedFeaturesChanged();
504 }
505 
507 {
508  unlinkFeatures( QgsFeatureIds() << fid );
509 }
510 
512 {
513  if ( mNmRelation.isValid() )
514  {
515  // only normal relations support m:n relation
516  Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );
517 
520  .setFilterFids( fids )
521  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
522 
523  QgsFeature f;
524 
525  QStringList filters;
526 
527  while ( selectedIterator.nextFeature( f ) )
528  {
529  filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
530  }
531 
532  const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
534  filters.join( QLatin1String( " OR " ) ) );
535 
537  .setNoAttributes()
538  .setFilterExpression( filter ) );
539 
540  QgsFeatureIds fids;
541 
542  while ( linkedIterator.nextFeature( f ) )
543  {
544  fids << f.id();
545  QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
546  }
547 
549  }
550  else
551  {
552  QMap<int, QgsField> keyFields;
553  const auto constFieldPairs = mRelation.fieldPairs();
554  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
555  {
556  const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
557  if ( idx < 0 )
558  {
559  QgsDebugMsg( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
560  return;
561  }
562  const QgsField fld = mRelation.referencingLayer()->fields().at( idx );
563  keyFields.insert( idx, fld );
564  }
565 
566  const auto constFeatureids = fids;
567  for ( const QgsFeatureId fid : constFeatureids )
568  {
569  QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
571  {
573 
574  Q_ASSERT( mRelation.polymorphicRelation().isValid() );
575 
577  referencingLayer->fields().indexFromName( polyRel.referencedLayerField() ),
578  referencingLayer->fields().field( polyRel.referencedLayerField() ).type() );
579  }
580 
581  QMapIterator<int, QgsField> it( keyFields );
582  while ( it.hasNext() )
583  {
584  it.next();
585  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
586  }
587  }
588  }
589 
590  updateUi();
591 
592  emit relatedFeaturesChanged();
593 }
594 
596 {}
597 
598 void QgsAbstractRelationEditorWidget::setTitle( const QString &title )
599 {
600  Q_UNUSED( title )
601 }
602 
604 {
605  Q_UNUSED( newRelation )
606  Q_UNUSED( newFeature )
607 }
608 
610 {}
611 
612 void QgsAbstractRelationEditorWidget::beforeSetRelations( const QgsRelation &newRelation, const QgsRelation &newNmRelation )
613 {
614  Q_UNUSED( newRelation )
615  Q_UNUSED( newNmRelation )
616 }
617 
619 {}
620 
622 {
623  duplicateFeatures( QgsFeatureIds() << fid );
624 
625  emit relatedFeaturesChanged();
626 }
627 
629 {
631 
632  QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
633  QgsFeature f;
634  while ( fit.nextFeature( f ) )
635  {
636  QgsVectorLayerUtils::QgsDuplicateFeatureContext duplicatedFeatureContext;
637  QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
638  }
639 
640  emit relatedFeaturesChanged();
641 }
642 
644 {
645  updateUi();
646 }
647 
648 
650 
651 
653  : QWidget( parent )
654  , mRelation( relation )
655 {
656 }
657 
659 {
660  return mLayer;
661 }
662 
664 {
665  return mRelation;
666 }
667 
669 {
670  mNmRelation = nmRelation;
671 }
672 
674 {
675  return mNmRelation;
676 }
677 
678 
680 
681 
683 {
684 }
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 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 Q_DECL_DEPRECATED void setTitle(const QString &title)
Sets the title of the widget, if it is wrapped within a QgsCollapsibleGroupBox.
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.
void linkFeature()
Links a new feature to the relation.
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...
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.
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.
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.
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.
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 the 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 unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:320
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
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
QgsField at(int i) const
Returns the 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:125
QString name
Definition: qgsmaplayer.h:76
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:111
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
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: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...
Q_GADGET QString id
Definition: qgsrelation.h:46
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...
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
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.
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
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.