QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsrelationeditorwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrelationeditor.cpp
3  --------------------------------------
4  Date : 17.5.2013
5  Copyright : (C) 2013 Matthias Kuhn
6  Email : matthias at opengis dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgsapplication.h"
19 #include "qgsdistancearea.h"
20 #include "qgsfeatureiterator.h"
21 #include "qgsvectordataprovider.h"
22 #include "qgsexpression.h"
23 #include "qgsfeature.h"
24 #include "qgsfeatureselectiondlg.h"
26 #include "qgsrelation.h"
27 #include "qgsvectorlayertools.h"
28 #include "qgsproject.h"
29 #include "qgstransactiongroup.h"
30 #include "qgslogger.h"
31 #include "qgsvectorlayerutils.h"
32 #include "qgsmapcanvas.h"
36 #include "qgsmessagebar.h"
37 #include "qgsmessagebaritem.h"
38 
39 #include <QHBoxLayout>
40 #include <QLabel>
41 #include <QMessageBox>
42 #include <QPushButton>
43 
46 QgsFilteredSelectionManager::QgsFilteredSelectionManager( QgsVectorLayer *layer, const QgsFeatureRequest &request, QObject *parent )
47  : QgsVectorLayerSelectionManager( layer, parent )
48  , mRequest( request )
49 {
50  if ( ! layer )
51  return;
52 
53  for ( auto fid : layer->selectedFeatureIds() )
54  if ( mRequest.acceptFeature( layer->getFeature( fid ) ) )
55  mSelectedFeatureIds << fid;
56 
57  connect( layer, &QgsVectorLayer::selectionChanged, this, &QgsFilteredSelectionManager::onSelectionChanged );
58 }
59 
60 const QgsFeatureIds &QgsFilteredSelectionManager::selectedFeatureIds() const
61 {
62  return mSelectedFeatureIds;
63 }
64 
65 int QgsFilteredSelectionManager::selectedFeatureCount()
66 {
67  return mSelectedFeatureIds.count();
68 }
69 
70 void QgsFilteredSelectionManager::onSelectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect )
71 {
72  QgsFeatureIds lselected = selected;
73  if ( clearAndSelect )
74  {
75  mSelectedFeatureIds.clear();
76  }
77  else
78  {
79  for ( auto fid : deselected )
80  mSelectedFeatureIds.remove( fid );
81  }
82 
83  for ( auto fid : selected )
84  if ( mRequest.acceptFeature( layer()->getFeature( fid ) ) )
85  mSelectedFeatureIds << fid;
86  else
87  lselected.remove( fid );
88 
89  emit selectionChanged( lselected, deselected, clearAndSelect );
90 }
91 
93 
95  : QgsCollapsibleGroupBox( parent )
96 {
97  QVBoxLayout *topLayout = new QVBoxLayout( this );
98  topLayout->setContentsMargins( 0, 9, 0, 0 );
99  setLayout( topLayout );
100 
101  // buttons
102  QHBoxLayout *buttonLayout = new QHBoxLayout();
103  buttonLayout->setContentsMargins( 0, 0, 0, 0 );
104  // toggle editing
105  mToggleEditingButton = new QToolButton( this );
106  mToggleEditingButton->setObjectName( QStringLiteral( "mToggleEditingButton" ) );
107  mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ) );
108  mToggleEditingButton->setText( tr( "Toggle Editing" ) );
109  mToggleEditingButton->setEnabled( false );
110  mToggleEditingButton->setCheckable( true );
111  mToggleEditingButton->setToolTip( tr( "Toggle editing mode for child layer" ) );
112  buttonLayout->addWidget( mToggleEditingButton );
113  // save Edits
114  mSaveEditsButton = new QToolButton( this );
115  mSaveEditsButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveEdits.svg" ) ) );
116  mSaveEditsButton->setText( tr( "Save Child Layer Edits" ) );
117  mSaveEditsButton->setToolTip( tr( "Save child layer edits" ) );
118  mSaveEditsButton->setEnabled( true );
119  buttonLayout->addWidget( mSaveEditsButton );
120  // add feature with geometry
121  mAddFeatureGeometryButton = new QToolButton( this );
122  mAddFeatureGeometryButton->setObjectName( QStringLiteral( "mAddFeatureGeometryButton" ) );
123  buttonLayout->addWidget( mAddFeatureGeometryButton );
124  // add feature
125  mAddFeatureButton = new QToolButton( this );
126  mAddFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewTableRow.svg" ) ) );
127  mAddFeatureButton->setText( tr( "Add Child Feature" ) );
128  mAddFeatureButton->setToolTip( tr( "Add child feature" ) );
129  mAddFeatureButton->setObjectName( QStringLiteral( "mAddFeatureButton" ) );
130  buttonLayout->addWidget( mAddFeatureButton );
131  // duplicate feature
132  mDuplicateFeatureButton = new QToolButton( this );
133  mDuplicateFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateFeature.svg" ) ) );
134  mDuplicateFeatureButton->setText( tr( "Duplicate Child Feature" ) );
135  mDuplicateFeatureButton->setToolTip( tr( "Duplicate child feature" ) );
136  mDuplicateFeatureButton->setObjectName( QStringLiteral( "mDuplicateFeatureButton" ) );
137  buttonLayout->addWidget( mDuplicateFeatureButton );
138  // delete feature
139  mDeleteFeatureButton = new QToolButton( this );
140  mDeleteFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ) );
141  mDeleteFeatureButton->setText( tr( "Delete Child Feature" ) );
142  mDeleteFeatureButton->setToolTip( tr( "Delete child feature" ) );
143  mDeleteFeatureButton->setObjectName( QStringLiteral( "mDeleteFeatureButton" ) );
144  buttonLayout->addWidget( mDeleteFeatureButton );
145  // link feature
146  mLinkFeatureButton = new QToolButton( this );
147  mLinkFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionLink.svg" ) ) );
148  mLinkFeatureButton->setText( tr( "Link Existing Features" ) );
149  mLinkFeatureButton->setToolTip( tr( "Link existing child features" ) );
150  mLinkFeatureButton->setObjectName( QStringLiteral( "mLinkFeatureButton" ) );
151  buttonLayout->addWidget( mLinkFeatureButton );
152  // unlink feature
153  mUnlinkFeatureButton = new QToolButton( this );
154  mUnlinkFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUnlink.svg" ) ) );
155  mUnlinkFeatureButton->setText( tr( "Unlink Feature" ) );
156  mUnlinkFeatureButton->setToolTip( tr( "Unlink child feature" ) );
157  mUnlinkFeatureButton->setObjectName( QStringLiteral( "mUnlinkFeatureButton" ) );
158  buttonLayout->addWidget( mUnlinkFeatureButton );
159  // zoom to linked feature
160  mZoomToFeatureButton = new QToolButton( this );
161  mZoomToFeatureButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToSelected.svg" ) ) );
162  mZoomToFeatureButton->setText( tr( "Zoom To Feature" ) );
163  mZoomToFeatureButton->setToolTip( tr( "Zoom to child feature" ) );
164  mZoomToFeatureButton->setObjectName( QStringLiteral( "mZoomToFeatureButton" ) );
165  buttonLayout->addWidget( mZoomToFeatureButton );
166  // spacer
167  buttonLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding ) );
168  // form view
169  mFormViewButton = new QToolButton( this );
170  mFormViewButton->setText( tr( "Form View" ) );
171  mFormViewButton->setToolTip( tr( "Switch to form view" ) );
172  mFormViewButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPropertyItem.svg" ) ) );
173  mFormViewButton->setCheckable( true );
174  mFormViewButton->setChecked( mViewMode == QgsDualView::AttributeEditor );
175  buttonLayout->addWidget( mFormViewButton );
176  // table view
177  mTableViewButton = new QToolButton( this );
178  mTableViewButton->setText( tr( "Table View" ) );
179  mTableViewButton->setToolTip( tr( "Switch to table view" ) );
180  mTableViewButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) );
181  mTableViewButton->setCheckable( true );
182  mTableViewButton->setChecked( mViewMode == QgsDualView::AttributeTable );
183  buttonLayout->addWidget( mTableViewButton );
184  // button group
185  mViewModeButtonGroup = new QButtonGroup( this );
186  mViewModeButtonGroup->addButton( mFormViewButton, QgsDualView::AttributeEditor );
187  mViewModeButtonGroup->addButton( mTableViewButton, QgsDualView::AttributeTable );
188 
189  // add buttons layout
190  topLayout->addLayout( buttonLayout );
191 
192  mRelationLayout = new QGridLayout();
193  mRelationLayout->setContentsMargins( 0, 0, 0, 0 );
194  topLayout->addLayout( mRelationLayout );
195 
196  mDualView = new QgsDualView( this );
197  mDualView->setView( mViewMode );
198 
199  mRelationLayout->addWidget( mDualView );
200 
201  connect( this, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsRelationEditorWidget::onCollapsedStateChanged );
202  connect( mViewModeButtonGroup, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ),
203  this, static_cast<void ( QgsRelationEditorWidget::* )( int )>( &QgsRelationEditorWidget::setViewMode ) );
204  connect( mToggleEditingButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::toggleEditing );
205  connect( mSaveEditsButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::saveEdits );
206  connect( mAddFeatureButton, &QAbstractButton::clicked, this, [this]() { addFeature(); } );
207  connect( mAddFeatureGeometryButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::addFeatureGeometry );
208  connect( mDuplicateFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::duplicateFeature );
209  connect( mDeleteFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::deleteSelectedFeatures );
210  connect( mLinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::linkFeature );
211  connect( mUnlinkFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::unlinkSelectedFeatures );
212  connect( mZoomToFeatureButton, &QAbstractButton::clicked, this, &QgsRelationEditorWidget::zoomToSelectedFeatures );
213 
214  connect( mDualView, &QgsDualView::showContextMenuExternally, this, &QgsRelationEditorWidget::showContextMenu );
215 
216  // Set initial state for add/remove etc. buttons
217  updateButtons();
218 }
219 
221 {
222  if ( mRelation.isValid() )
223  {
224  disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
225  disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
226  }
227 
228  mRelation = relation;
229  mFeature = feature;
230 
231  connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
232  connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
233 
234  updateTitle();
235 
236  QgsVectorLayer *lyr = relation.referencingLayer();
237 
238  bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
239  if ( canChangeAttributes && !lyr->readOnly() )
240  {
241  mToggleEditingButton->setEnabled( true );
242  updateButtons();
243  }
244  else
245  {
246  mToggleEditingButton->setEnabled( false );
247  }
248 
249  setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
250 
251  // If not yet initialized, it is not (yet) visible, so we don't load it to be faster (lazy loading)
252  // If it is already initialized, it has been set visible before and the currently shown feature is changing
253  // and the widget needs updating
254 
255  if ( mVisible )
256  {
257  QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
258  initDualView( mRelation.referencingLayer(), myRequest );
259  }
260 }
261 
262 void QgsRelationEditorWidget::initDualView( QgsVectorLayer *layer, const QgsFeatureRequest &request )
263 {
264  QgsAttributeEditorContext ctx { mEditorContext };
265  ctx.setParentFormFeature( mFeature );
266  mDualView->init( layer, mEditorContext.mapCanvas(), request, ctx );
267  mFeatureSelectionMgr = new QgsFilteredSelectionManager( layer, request, mDualView );
268  mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
269 
270  connect( mFeatureSelectionMgr, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsRelationEditorWidget::updateButtons );
271 
272  QIcon icon;
273  QString text;
274  if ( layer->geometryType() == QgsWkbTypes::PointGeometry )
275  {
276  icon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionCapturePoint.svg" ) );
277  text = tr( "Add Point child Feature" );
278  }
279  else if ( layer->geometryType() == QgsWkbTypes::LineGeometry )
280  {
281  icon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionCaptureLine.svg" ) );
282  text = tr( "Add Line child Feature" );
283  }
284  else if ( layer->geometryType() == QgsWkbTypes::PolygonGeometry )
285  {
286  icon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionCapturePolygon.svg" ) );
287  text = tr( "Add Polygon Feature" );
288  }
289 
290  mAddFeatureGeometryButton->setIcon( icon );
291  mAddFeatureGeometryButton->setText( text );
292  mAddFeatureGeometryButton->setToolTip( text );
293 
294  updateButtons();
295 }
296 
297 void QgsRelationEditorWidget::setRelations( const QgsRelation &relation, const QgsRelation &nmrelation )
298 {
299  if ( mRelation.isValid() )
300  {
301  disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
302  disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
303  }
304 
305  if ( mNmRelation.isValid() )
306  {
307  disconnect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
308  disconnect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
309  }
310 
311  mRelation = relation;
312  mNmRelation = nmrelation;
313 
314  if ( !mRelation.isValid() )
315  return;
316 
317  mLayerInSameTransactionGroup = false;
318 
319  const auto transactionGroups = QgsProject::instance()->transactionGroups();
320  for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
321  {
322  if ( mNmRelation.isValid() )
323  {
324  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
325  it.value()->layers().contains( mRelation.referencingLayer() ) &&
326  it.value()->layers().contains( mNmRelation.referencedLayer() ) )
327  mLayerInSameTransactionGroup = true;
328  }
329  else
330  {
331  if ( it.value()->layers().contains( mRelation.referencedLayer() ) &&
332  it.value()->layers().contains( mRelation.referencingLayer() ) )
333  mLayerInSameTransactionGroup = true;
334  }
335  }
336 
337  connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
338  connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
339 
340  if ( mNmRelation.isValid() )
341  {
342  connect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons );
343  connect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons );
344  }
345 
346  updateTitle();
347 
348  QgsVectorLayer *lyr = relation.referencingLayer();
349 
350  bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
351  if ( canChangeAttributes && !lyr->readOnly() )
352  {
353  mToggleEditingButton->setEnabled( true );
354  }
355  else
356  {
357  mToggleEditingButton->setEnabled( false );
358  }
359 
360  updateButtons();
361 
362  setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );
363 
364  updateUi();
365 }
366 
368 {
369  mEditorContext = context;
370 
371  if ( context.mapCanvas() && context.cadDockWidget() )
372  {
373  mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( context.mapCanvas(), context.cadDockWidget() ) );
374  mMapToolDigitize->setButton( mAddFeatureGeometryButton );
375  }
376 
377  updateButtons();
378 }
379 
381 {
382  return mEditorContext;
383 }
384 
386 {
387  return mFeatureSelectionMgr;
388 }
389 
391 {
392  mDualView->setView( mode );
393  mViewMode = mode;
394 }
395 
396 void QgsRelationEditorWidget::setFeature( const QgsFeature &feature, bool update )
397 {
398  mFeature = feature;
399 
400  mEditorContext.setFormFeature( feature );
401 
402  if ( update )
403  updateUi();
404 }
405 
406 void QgsRelationEditorWidget::updateButtons()
407 {
408  bool editable = false;
409  bool linkable = false;
410  bool spatial = false;
411  bool selectionNotEmpty = mFeatureSelectionMgr ? mFeatureSelectionMgr->selectedFeatureCount() : false;
412 
413  if ( mRelation.isValid() )
414  {
415  editable = mRelation.referencingLayer()->isEditable();
416  linkable = mRelation.referencingLayer()->isEditable();
417  spatial = mRelation.referencingLayer()->isSpatial();
418  }
419 
420  if ( mNmRelation.isValid() )
421  {
422  editable = mNmRelation.referencedLayer()->isEditable();
423  spatial = mNmRelation.referencedLayer()->isSpatial();
424  }
425 
426  mAddFeatureButton->setEnabled( editable );
427  mAddFeatureGeometryButton->setEnabled( editable );
428  mDuplicateFeatureButton->setEnabled( editable && selectionNotEmpty );
429  mLinkFeatureButton->setEnabled( linkable );
430  mDeleteFeatureButton->setEnabled( editable && selectionNotEmpty );
431  mUnlinkFeatureButton->setEnabled( linkable && selectionNotEmpty );
432  mZoomToFeatureButton->setEnabled( selectionNotEmpty );
433  mToggleEditingButton->setChecked( editable );
434  mSaveEditsButton->setEnabled( editable );
435 
436  mToggleEditingButton->setVisible( !mLayerInSameTransactionGroup );
437  mLinkFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::Link ) );
438  mUnlinkFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::Unlink ) );
439  mSaveEditsButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::SaveChildEdits ) && !mLayerInSameTransactionGroup );
440  mAddFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::AddChildFeature ) );
441  mAddFeatureGeometryButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::AddChildFeature ) && mEditorContext.mapCanvas() && mEditorContext.cadDockWidget() && spatial );
442  mDuplicateFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::DuplicateChildFeature ) );
443  mDeleteFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::DeleteChildFeature ) );
444  mZoomToFeatureButton->setVisible( mButtonsVisibility.testFlag( QgsAttributeEditorRelation::Button::ZoomToChildFeature ) && mEditorContext.mapCanvas() && spatial );
445 }
446 
447 void QgsRelationEditorWidget::addFeatureGeometry()
448 {
449  QgsVectorLayer *layer = nullptr;
450  if ( mNmRelation.isValid() )
451  layer = mNmRelation.referencedLayer();
452  else
453  layer = mRelation.referencingLayer();
454 
455  mMapToolDigitize->setLayer( layer );
456 
457  // window is always on top, so we hide it to digitize without seeing it
458  window()->setVisible( false );
459  setMapTool( mMapToolDigitize );
460 
461  connect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationEditorWidget::onDigitizingCompleted );
462  connect( mEditorContext.mapCanvas(), &QgsMapCanvas::keyPressed, this, &QgsRelationEditorWidget::onKeyPressed );
463 
464  if ( auto *lMainMessageBar = mEditorContext.mainMessageBar() )
465  {
466  QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( layer, mFeature );
467 
468  QString title = tr( "Create child feature for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString );
469  QString msg = tr( "Digitize the geometry for the new feature on layer %1. Press &lt;ESC&gt; to cancel." )
470  .arg( layer->name() );
471  mMessageBarItem = QgsMessageBar::createMessage( title, msg, this );
472  lMainMessageBar->pushItem( mMessageBarItem );
473  }
474 
475 }
476 
477 void QgsRelationEditorWidget::addFeature( const QgsGeometry &geometry )
478 {
479  QgsAttributeMap keyAttrs;
480 
481  const QgsVectorLayerTools *vlTools = mEditorContext.vectorLayerTools();
482 
483  if ( mNmRelation.isValid() )
484  {
485  // n:m Relation: first let the user create a new feature on the other table
486  // and autocreate a new linking feature.
487  QgsFeature f;
488  if ( vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), geometry, &f ) )
489  {
490  // Fields of the linking table
491  const QgsFields fields = mRelation.referencingLayer()->fields();
492 
493  // Expression context for the linking table
495 
496  QgsAttributeMap linkAttributes;
497  const auto constFieldPairs = mRelation.fieldPairs();
498  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
499  {
500  int index = fields.indexOf( fieldPair.first );
501  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
502  }
503 
504  const auto constNmFieldPairs = mNmRelation.fieldPairs();
505  for ( const QgsRelation::FieldPair &fieldPair : constNmFieldPairs )
506  {
507  int index = fields.indexOf( fieldPair.first );
508  linkAttributes.insert( index, f.attribute( fieldPair.second ) );
509  }
510  QgsFeature linkFeature = QgsVectorLayerUtils::createFeature( mRelation.referencingLayer(), QgsGeometry(), linkAttributes, &context );
511 
512  mRelation.referencingLayer()->addFeature( linkFeature );
513 
514  updateUi();
515  }
516  }
517  else
518  {
519  QgsFields fields = mRelation.referencingLayer()->fields();
520 
521  const auto constFieldPairs = mRelation.fieldPairs();
522  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
523  {
524  keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
525  }
526 
527  vlTools->addFeature( mDualView->masterModel()->layer(), keyAttrs, geometry );
528  }
529 }
530 
531 void QgsRelationEditorWidget::onDigitizingCompleted( const QgsFeature &feature )
532 {
533  addFeature( feature.geometry() );
534 
535  unsetMapTool();
536 }
537 
538 void QgsRelationEditorWidget::linkFeature()
539 {
540  QgsVectorLayer *layer = nullptr;
541 
542  if ( mNmRelation.isValid() )
543  layer = mNmRelation.referencedLayer();
544  else
545  layer = mRelation.referencingLayer();
546 
547  QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
548  selectionDlg->setAttribute( Qt::WA_DeleteOnClose );
549 
550  const QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mRelation.referencedLayer(), mFeature );
551  selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );
552 
553  connect( selectionDlg, &QDialog::accepted, this, &QgsRelationEditorWidget::onLinkFeatureDlgAccepted );
554  selectionDlg->show();
555 }
556 
557 void QgsRelationEditorWidget::onLinkFeatureDlgAccepted()
558 {
559  QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );
560  if ( mNmRelation.isValid() )
561  {
562  QgsFeatureIterator it = mNmRelation.referencedLayer()->getFeatures(
564  .setFilterFids( selectionDlg->selectedFeatures() )
565  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
566 
567  QgsFeature relatedFeature;
568 
569  QgsFeatureList newFeatures;
570 
571  // Fields of the linking table
572  const QgsFields fields = mRelation.referencingLayer()->fields();
573 
574  // Expression context for the linking table
576 
577  QgsAttributeMap linkAttributes;
578  const auto constFieldPairs = mRelation.fieldPairs();
579  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
580  {
581  int index = fields.indexOf( fieldPair.first );
582  linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
583  }
584 
585  while ( it.nextFeature( relatedFeature ) )
586  {
587  const auto constFieldPairs = mNmRelation.fieldPairs();
588  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
589  {
590  int index = fields.indexOf( fieldPair.first );
591  linkAttributes.insert( index, relatedFeature.attribute( fieldPair.second ) );
592  }
593  const QgsFeature linkFeature = QgsVectorLayerUtils::createFeature( mRelation.referencingLayer(), QgsGeometry(), linkAttributes, &context );
594 
595  newFeatures << linkFeature;
596  }
597 
598  mRelation.referencingLayer()->addFeatures( newFeatures );
599  QgsFeatureIds ids;
600  const auto constNewFeatures = newFeatures;
601  for ( const QgsFeature &f : constNewFeatures )
602  ids << f.id();
603  mRelation.referencingLayer()->selectByIds( ids );
604  }
605  else
606  {
607  QMap<int, QVariant> keys;
608  const auto constFieldPairs = mRelation.fieldPairs();
609  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
610  {
611  int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
612  QVariant val = mFeature.attribute( fieldPair.referencedField() );
613  keys.insert( idx, val );
614  }
615 
616  const auto constSelectedFeatures = selectionDlg->selectedFeatures();
617  for ( QgsFeatureId fid : constSelectedFeatures )
618  {
619  QMapIterator<int, QVariant> it( keys );
620  while ( it.hasNext() )
621  {
622  it.next();
623  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), it.value() );
624  }
625  }
626  }
627 
628  updateUi();
629 }
630 
631 void QgsRelationEditorWidget::duplicateFeature()
632 {
633  QgsVectorLayer *layer = mRelation.referencingLayer();
634 
635  QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterFids( mFeatureSelectionMgr->selectedFeatureIds() ) );
636  QgsFeature f;
637  while ( fit.nextFeature( f ) )
638  {
639  QgsVectorLayerUtils::QgsDuplicateFeatureContext duplicatedFeatureContext;
640  QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), 0, duplicatedFeatureContext );
641  }
642 }
643 
644 void QgsRelationEditorWidget::deleteFeature( const QgsFeatureId featureid )
645 {
646  deleteFeatures( QgsFeatureIds() << featureid );
647 }
648 
649 void QgsRelationEditorWidget::deleteSelectedFeatures()
650 {
651  QgsFeatureIds selectedFids = mFeatureSelectionMgr->selectedFeatureIds();
652  deleteFeatures( selectedFids );
653 }
654 
655 void QgsRelationEditorWidget::deleteFeatures( const QgsFeatureIds &featureids )
656 {
657  bool deleteFeatures = true;
658 
659  QgsVectorLayer *layer;
660  if ( mNmRelation.isValid() )
661  {
662  layer = mNmRelation.referencedLayer();
663 
664  // When deleting a linked feature within an N:M relation,
665  // check if the feature is linked to more than just one feature.
666  // In case it is linked more than just once, ask the user for confirmation
667  // as it is likely he was not aware of the implications and might delete
668  // there may be several linking entries deleted along.
669 
670  QgsFeatureRequest deletedFeaturesRequest;
671  deletedFeaturesRequest.setFilterFids( featureids );
672  deletedFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
673  deletedFeaturesRequest.setSubsetOfAttributes( QgsAttributeList() << mNmRelation.referencedFields().first() );
674 
675  QgsFeatureIterator deletedFeatures = layer->getFeatures( deletedFeaturesRequest );
676  QStringList deletedFeaturesPks;
678  while ( deletedFeatures.nextFeature( feature ) )
679  {
680  deletedFeaturesPks.append( QgsExpression::quotedValue( feature.attribute( mNmRelation.referencedFields().first() ) ) );
681  }
682 
683  QgsFeatureRequest linkingFeaturesRequest;
684  linkingFeaturesRequest.setFlags( QgsFeatureRequest::NoGeometry );
685  linkingFeaturesRequest.setNoAttributes();
686 
687  QString linkingFeaturesRequestExpression;
688  if ( !deletedFeaturesPks.empty() )
689  {
690  linkingFeaturesRequestExpression = QStringLiteral( "%1 IN (%2)" ).arg( QgsExpression::quotedColumnRef( mNmRelation.fieldPairs().first().first ), deletedFeaturesPks.join( ',' ) );
691  linkingFeaturesRequest.setFilterExpression( linkingFeaturesRequestExpression );
692 
693  QgsFeatureIterator relatedLinkingFeatures = mNmRelation.referencingLayer()->getFeatures( linkingFeaturesRequest );
694 
695  int relatedLinkingFeaturesCount = 0;
696  while ( relatedLinkingFeatures.nextFeature( feature ) )
697  {
698  relatedLinkingFeaturesCount++;
699  }
700 
701  if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
702  {
703  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 );
704  messageBox.addButton( QMessageBox::Cancel );
705  QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
706 
707  messageBox.exec();
708  if ( messageBox.clickedButton() != deleteButton )
709  deleteFeatures = false;
710  }
711  else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
712  {
713  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 );
714  messageBox.addButton( QMessageBox::Cancel );
715  QAbstractButton *deleteButton = messageBox.addButton( tr( "Delete" ), QMessageBox::AcceptRole );
716 
717  messageBox.exec();
718  if ( messageBox.clickedButton() != deleteButton )
719  deleteFeatures = false;
720  }
721  }
722  }
723  else
724  {
725  layer = mRelation.referencingLayer();
726  }
727 
729  if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, featureids, QgsProject::instance(), infoContext ) )
730  {
731  QString childrenInfo;
732  int childrenCount = 0;
733  const auto infoContextLayers = infoContext.layers();
734  for ( QgsVectorLayer *chl : infoContextLayers )
735  {
736  childrenCount += infoContext.duplicatedFeatures( chl ).size();
737  childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
738  }
739 
740  // for extra safety to make sure we know that the delete can have impact on children and joins
741  int res = QMessageBox::question( this, tr( "Delete at least %1 feature(s) on other layer(s)" ).arg( childrenCount ),
742  tr( "Delete %1 feature(s) on layer \"%2\", %3 as well\nand all of its other descendants.\nDelete these features?" ).arg( featureids.count() ).arg( layer->name() ).arg( childrenInfo ),
743  QMessageBox::Yes | QMessageBox::No );
744  if ( res != QMessageBox::Yes )
745  deleteFeatures = false;
746  }
747 
748  if ( deleteFeatures )
749  {
751  layer->deleteFeatures( featureids, &context );
752  const auto contextLayers = context.handledLayers();
753  if ( contextLayers.size() > 1 )
754  {
755  int deletedCount = 0;
756  QString feedbackMessage;
757  for ( QgsVectorLayer *contextLayer : contextLayers )
758  {
759  feedbackMessage += tr( "%1 on layer %2. " ).arg( context.handledFeatures( contextLayer ).size() ).arg( contextLayer->name() );
760  deletedCount += context.handledFeatures( contextLayer ).size();
761  }
762  mEditorContext.mainMessageBar()->pushMessage( tr( "%1 features deleted: %2" ).arg( deletedCount ).arg( feedbackMessage ), Qgis::Success );
763  }
764 
765  updateUi();
766  }
767 }
768 
769 void QgsRelationEditorWidget::unlinkFeature( const QgsFeatureId featureid )
770 {
771  unlinkFeatures( QgsFeatureIds() << featureid );
772 }
773 
774 void QgsRelationEditorWidget::unlinkSelectedFeatures()
775 {
776  unlinkFeatures( mFeatureSelectionMgr->selectedFeatureIds() );
777 }
778 
779 void QgsRelationEditorWidget::zoomToSelectedFeatures()
780 {
781  QgsMapCanvas *c = mEditorContext.mapCanvas();
782  if ( !c )
783  return;
784 
785  c->zoomToFeatureIds(
786  mNmRelation.isValid() ? mNmRelation.referencedLayer() : mRelation.referencingLayer(),
787  mFeatureSelectionMgr->selectedFeatureIds()
788  );
789 }
790 
791 void QgsRelationEditorWidget::unlinkFeatures( const QgsFeatureIds &featureids )
792 {
793  if ( mNmRelation.isValid() )
794  {
795  QgsFeatureIterator selectedIterator = mNmRelation.referencedLayer()->getFeatures(
797  .setFilterFids( featureids )
798  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
799 
800  QgsFeature f;
801 
802  QStringList filters;
803 
804  while ( selectedIterator.nextFeature( f ) )
805  {
806  filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
807  }
808 
809  QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
810  mRelation.getRelatedFeaturesRequest( mFeature ).filterExpression()->expression(),
811  filters.join( QLatin1String( " OR " ) ) );
812 
813  QgsFeatureIterator linkedIterator = mRelation.referencingLayer()->getFeatures( QgsFeatureRequest()
814  .setNoAttributes()
815  .setFilterExpression( filter ) );
816 
817  QgsFeatureIds fids;
818 
819  while ( linkedIterator.nextFeature( f ) )
820  {
821  fids << f.id();
822  QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
823  }
824 
825  mRelation.referencingLayer()->deleteFeatures( fids );
826 
827  updateUi();
828  }
829  else
830  {
831  QMap<int, QgsField> keyFields;
832  const auto constFieldPairs = mRelation.fieldPairs();
833  for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
834  {
835  int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
836  if ( idx < 0 )
837  {
838  QgsDebugMsg( QStringLiteral( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
839  return;
840  }
841  QgsField fld = mRelation.referencingLayer()->fields().at( idx );
842  keyFields.insert( idx, fld );
843  }
844 
845  const auto constFeatureids = featureids;
846  for ( QgsFeatureId fid : constFeatureids )
847  {
848  QMapIterator<int, QgsField> it( keyFields );
849  while ( it.hasNext() )
850  {
851  it.next();
852  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
853  }
854  }
855  }
856 }
857 
858 void QgsRelationEditorWidget::toggleEditing( bool state )
859 {
860  if ( state )
861  {
862  mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
863  if ( mNmRelation.isValid() )
864  mEditorContext.vectorLayerTools()->startEditing( mNmRelation.referencedLayer() );
865  }
866  else
867  {
868  mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
869  if ( mNmRelation.isValid() )
870  mEditorContext.vectorLayerTools()->stopEditing( mNmRelation.referencedLayer() );
871  }
872 
873  updateButtons();
874 }
875 
876 void QgsRelationEditorWidget::saveEdits()
877 {
878  mEditorContext.vectorLayerTools()->saveEdits( mRelation.referencingLayer() );
879  if ( mNmRelation.isValid() )
880  mEditorContext.vectorLayerTools()->saveEdits( mNmRelation.referencedLayer() );
881 }
882 
883 void QgsRelationEditorWidget::onCollapsedStateChanged( bool collapsed )
884 {
885  if ( !collapsed )
886  {
887  mVisible = true;
888  updateUi();
889  }
890 }
891 
892 void QgsRelationEditorWidget::updateUi()
893 {
894  // If not yet initialized, it is not (yet) visible, so we don't load it to be faster (lazy loading)
895  // If it is already initialized, it has been set visible before and the currently shown feature is changing
896  // and the widget needs updating
897 
898  if ( mVisible )
899  {
900  QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
901 
902  if ( mNmRelation.isValid() )
903  {
904  QgsFeatureIterator it = mRelation.referencingLayer()->getFeatures( myRequest );
905 
906  QgsFeature fet;
907 
908  QStringList filters;
909 
910  while ( it.nextFeature( fet ) )
911  {
912  QString filter = mNmRelation.getReferencedFeatureRequest( fet ).filterExpression()->expression();
913  filters << filter.prepend( '(' ).append( ')' );
914  }
915 
916  QgsFeatureRequest nmRequest;
917 
918  nmRequest.setFilterExpression( filters.join( QLatin1String( " OR " ) ) );
919 
920  initDualView( mNmRelation.referencedLayer(), nmRequest );
921  }
922  else if ( mRelation.referencingLayer() )
923  {
924  initDualView( mRelation.referencingLayer(), myRequest );
925  }
926  }
927 }
928 
930 {
931  return mLinkFeatureButton->isVisible();
932 }
933 
935 {
936  mLinkFeatureButton->setVisible( showLinkButton );
937 }
938 
940 {
941  return mUnlinkFeatureButton->isVisible();
942 }
943 
945 {
946  mSaveEditsButton->setVisible( showChildEdits );
947 }
948 
950 {
951  return mSaveEditsButton->isVisible();
952 }
953 
954 void QgsRelationEditorWidget::setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons )
955 {
956  mButtonsVisibility = buttons;
957  updateButtons();
958 }
959 
960 QgsAttributeEditorRelation::Buttons QgsRelationEditorWidget::visibleButtons() const
961 {
962  QgsAttributeEditorRelation::Buttons buttons;
963  if ( mLinkFeatureButton->isVisible() )
964  buttons |= QgsAttributeEditorRelation::Button::Link;
965  if ( mUnlinkFeatureButton->isVisible() )
966  buttons |= QgsAttributeEditorRelation::Button::Unlink;
967  if ( mSaveEditsButton->isVisible() )
968  buttons |= QgsAttributeEditorRelation::Button::SaveChildEdits;
969  if ( mAddFeatureButton->isVisible() )
970  buttons |= QgsAttributeEditorRelation::Button::AddChildFeature;
971  if ( mDuplicateFeatureButton->isVisible() )
972  buttons |= QgsAttributeEditorRelation::Button::DuplicateChildFeature;
973  if ( mDeleteFeatureButton->isVisible() )
974  buttons |= QgsAttributeEditorRelation::Button::DeleteChildFeature;
975  if ( mZoomToFeatureButton->isVisible() )
976  buttons |= QgsAttributeEditorRelation::Button::ZoomToChildFeature;
977  return buttons;
978 }
979 
980 void QgsRelationEditorWidget::setForceSuppressFormPopup( bool forceSuppressFormPopup )
981 {
982  mForceSuppressFormPopup = forceSuppressFormPopup;
983 }
984 
986 {
987  return mForceSuppressFormPopup;
988 }
989 
990 void QgsRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
991 {
992  mNmRelationId = nmRelationId;
993 }
994 
996 {
997  return mNmRelationId;
998 }
999 
1001 {
1002  return mLabel;
1003 }
1004 
1005 void QgsRelationEditorWidget::setLabel( const QString &label )
1006 {
1007  mLabel = label;
1008 
1009  updateTitle();
1010 }
1011 
1013 {
1014  mUnlinkFeatureButton->setVisible( showUnlinkButton );
1015 }
1016 
1017 void QgsRelationEditorWidget::parentFormValueChanged( const QString &attribute, const QVariant &newValue )
1018 {
1019  mDualView->parentFormValueChanged( attribute, newValue );
1020 }
1021 
1023 {
1024  return mShowLabel;
1025 }
1026 
1028 {
1029  mShowLabel = showLabel;
1030 
1031  updateTitle();
1032 }
1033 
1034 void QgsRelationEditorWidget::showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid )
1035 {
1036  if ( mRelation.referencingLayer()->isEditable() )
1037  {
1038  QAction *qAction = nullptr;
1039 
1040  qAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ), tr( "Delete Feature" ) );
1041  connect( qAction, &QAction::triggered, this, [this, fid]() { deleteFeature( fid ); } );
1042 
1043  qAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUnlink.svg" ) ), tr( "Unlink Feature" ) );
1044  connect( qAction, &QAction::triggered, this, [this, fid]() { unlinkFeature( fid ); } );
1045  }
1046 }
1047 
1048 void QgsRelationEditorWidget::setMapTool( QgsMapTool *mapTool )
1049 {
1050  QgsMapCanvas *mapCanvas = mEditorContext.mapCanvas();
1051 
1052  mapCanvas->setMapTool( mapTool );
1053  mapCanvas->window()->raise();
1054  mapCanvas->activateWindow();
1055  mapCanvas->setFocus();
1056  connect( mapTool, &QgsMapTool::deactivated, this, &QgsRelationEditorWidget::mapToolDeactivated );
1057 }
1058 
1059 void QgsRelationEditorWidget::unsetMapTool()
1060 {
1061  QgsMapCanvas *mapCanvas = mEditorContext.mapCanvas();
1062 
1063  // this will call mapToolDeactivated
1064  mapCanvas->unsetMapTool( mMapToolDigitize );
1065 
1066  disconnect( mapCanvas, &QgsMapCanvas::keyPressed, this, &QgsRelationEditorWidget::onKeyPressed );
1067  disconnect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationEditorWidget::onDigitizingCompleted );
1068 }
1069 
1070 void QgsRelationEditorWidget::updateTitle()
1071 {
1072  if ( mShowLabel && !mLabel.isEmpty() )
1073  {
1074  setTitle( mLabel );
1075  }
1076  else if ( mShowLabel && mRelation.isValid() )
1077  {
1078  setTitle( mRelation.name() );
1079  }
1080  else
1081  {
1082  setTitle( QString() );
1083  }
1084 }
1085 
1087 {
1088  return mFeature;
1089 }
1090 
1091 void QgsRelationEditorWidget::onKeyPressed( QKeyEvent *e )
1092 {
1093  if ( e->key() == Qt::Key_Escape )
1094  {
1095  unsetMapTool();
1096  }
1097 }
1098 
1099 void QgsRelationEditorWidget::mapToolDeactivated()
1100 {
1101  window()->setVisible( true );
1102  window()->raise();
1103  window()->activateWindow();
1104 
1105  if ( mEditorContext.mainMessageBar() && mMessageBarItem )
1106  {
1107  mEditorContext.mainMessageBar()->popWidget( mMessageBarItem );
1108  }
1109  mMessageBarItem = nullptr;
1110 }
QgsAttributeEditorContext::mapCanvas
QgsMapCanvas * mapCanvas() const
Returns the associated map canvas (e.g.
Definition: qgsattributeeditorcontext.h:140
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:81
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:993
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsVectorLayer::addFeatures
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
Definition: qgsvectorlayer.cpp:3492
QgsAttributeEditorContext::setParentFormFeature
void setParentFormFeature(const QgsFeature &feature)
Sets the feature of the currently edited parent form.
Definition: qgsattributeeditorcontext.h:258
QgsRelationEditorWidget::setForceSuppressFormPopup
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status with forceSuppressFormPopup configured for this widget.
Definition: qgsrelationeditorwidget.cpp:980
qgsexpressioncontextutils.h
QgsVectorLayerTools::addFeature
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.
QgsFeature::id
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QObjectUniquePtr::reset
void reset(T *p=nullptr)
Will reset the managed pointer to p.
Definition: qobjectuniqueptr.h:176
QgsVectorLayer::readOnly
bool readOnly
Definition: qgsvectorlayer.h:394
QgsAttributeEditorContext::cadDockWidget
QgsAdvancedDigitizingDockWidget * cadDockWidget() const
Returns the associated CAD dock widget (e.g.
Definition: qgsattributeeditorcontext.h:156
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
qgsmessagebaritem.h
QgsRelationEditorWidget::setFeature
void setFeature(const QgsFeature &feature, bool update=true)
Sets the feature being edited and updates the UI unless update is set to false.
Definition: qgsrelationeditorwidget.cpp:396
QgsRelationEditorWidget::parentFormValueChanged
void parentFormValueChanged(const QString &attribute, const QVariant &newValue)
Called when an attribute value in the parent widget has changed to newValue.
Definition: qgsrelationeditorwidget.cpp:1017
QgsRelationEditorWidget::feature
QgsFeature feature() const
Returns the widget's current feature.
Definition: qgsrelationeditorwidget.cpp:1086
qgsmapcanvas.h
QgsVectorLayerUtils::duplicateFeature
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext)
Duplicates a feature and it's children (one level deep).
Definition: qgsvectorlayerutils.cpp:625
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
qgsexpression.h
QgsVectorLayer::DeleteContext
Context for cascade delete features.
Definition: qgsvectorlayer.h:512
QgsRelation::name
QString name
Definition: qgsrelation.h:48
QgsDualView::setView
void setView(ViewMode view)
Change the current view mode.
Definition: qgsdualview.cpp:272
qgsfeatureiterator.h
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsProject::transactionGroups
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
Definition: qgsproject.cpp:3187
QgsRelationEditorWidget::showLinkButton
Q_DECL_DEPRECATED bool showLinkButton() const
Determines if the "link feature" button should be shown.
Definition: qgsrelationeditorwidget.cpp:929
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
qgsfeature.h
QgsRelationEditorWidget
Definition: qgsrelationeditorwidget.h:84
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsVectorLayerTools
Methods in this class are used to handle basic operations on vector layers.
Definition: qgsvectorlayertools.h:40
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsVectorLayer::isSpatial
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Definition: qgsvectorlayer.cpp:3599
QgsDualView::init
void init(QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsAttributeEditorContext &context=QgsAttributeEditorContext(), bool loadFeatures=true)
Has to be called to initialize the dual view.
Definition: qgsdualview.cpp:119
Qgis::Success
@ Success
Definition: qgis.h:93
QgsRelation::referencedFields
QgsAttributeList referencedFields() const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
Definition: qgsrelation.cpp:297
QgsVectorLayer::selectByIds
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects matching features using a list of feature IDs.
Definition: qgsvectorlayer.cpp:523
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:185
QgsDualView
This widget is used to show the attributes of a set of features of a QgsVectorLayer.
Definition: qgsdualview.h:42
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
FID_TO_STRING
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
QgsDualView::AttributeTable
@ AttributeTable
Shows the features and attributes in a table layout.
Definition: qgsdualview.h:58
QgsAttributeList
QList< int > QgsAttributeList
Definition: qgsfield.h:26
QgsCollapsibleGroupBox
A groupbox that collapses/expands when toggled and can save its collapsed and checked states.
Definition: qgscollapsiblegroupbox.h:179
QgsMessageBar::popWidget
bool popWidget(QgsMessageBarItem *item)
Remove the specified item from the bar, and display the next most recent one in the stack.
Definition: qgsmessagebar.cpp:160
qgsrelationeditorwidget.h
QgsVectorLayer::changeAttributeValue
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).
Definition: qgsvectorlayer.cpp:2966
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsVectorLayer::isEditable
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
Definition: qgsvectorlayer.cpp:3594
QgsRelation::referencingLayer
QgsVectorLayer * referencingLayer
Definition: qgsrelation.h:46
QgsFeatureRequest::setFilterExpression
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Definition: qgsfeaturerequest.cpp:124
qgsapplication.h
QgsDualView::masterModel
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered)
Definition: qgsdualview.h:182
QgsMapTool
Abstract base class for all map tools.
Definition: qgsmaptool.h:64
QgsExpression::quotedValue
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
Definition: qgsexpression.cpp:79
qgsmaptooldigitizefeature.h
QgsRelationEditorWidget::QgsRelationEditorWidget
QgsRelationEditorWidget(QWidget *parent=nullptr)
Definition: qgsrelationeditorwidget.cpp:94
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:76
QgsRelationEditorWidget::label
QString label() const
Determines the label of this element.
Definition: qgsrelationeditorwidget.cpp:1000
QgsVectorDataProvider::capabilities
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
Definition: qgsvectordataprovider.cpp:198
QgsVectorLayer::editingStarted
void editingStarted()
Emitted when editing on this layer has started.
QgsVectorLayerUtils::QgsDuplicateFeatureContext::layers
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Definition: qgsvectorlayerutils.cpp:814
QgsRelationEditorWidget::visibleButtons
QgsAttributeEditorRelation::Buttons visibleButtons
Definition: qgsrelationeditorwidget.h:100
QgsMapToolDigitizeFeature::digitizingCompleted
void digitizingCompleted(const QgsFeature &feature)
Emitted whenever the digitizing has been successfully completed.
qgsvectorlayertools.h
qgsvectorlayerselectionmanager.h
QgsRelationEditorWidget::setViewMode
void setViewMode(QgsDualView::ViewMode mode)
Define the view mode for the dual view.
Definition: qgsrelationeditorwidget.cpp:390
QgsVectorLayer::selectionChanged
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
QgsRelationEditorWidget::showLabel
bool showLabel
Definition: qgsrelationeditorwidget.h:99
QgsIFeatureSelectionManager::selectionChanged
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
QgsMapToolDigitizeFeature::setLayer
void setLayer(QgsMapLayer *vl)
Change the layer edited by the map tool.
Definition: qgsmaptooldigitizefeature.cpp:365
QgsVectorLayerTools::saveEdits
virtual bool saveEdits(QgsVectorLayer *layer) const =0
Should be called, when the features should be committed but the editing session is not ended.
QgsRelation::referencedLayer
QgsVectorLayer * referencedLayer
Definition: qgsrelation.h:47
QgsRelationEditorWidget::setShowUnlinkButton
Q_DECL_DEPRECATED void setShowUnlinkButton(bool showUnlinkButton)
Determines if the "unlink feature" button should be shown.
Definition: qgsrelationeditorwidget.cpp:1012
QgsVectorLayer::selectedFeatureIds
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Definition: qgsvectorlayer.cpp:3441
QgsFeatureRequest::filterExpression
QgsExpression * filterExpression() const
Returns the filter expression if set.
Definition: qgsfeaturerequest.h:412
QgsVectorLayerUtils::QgsDuplicateFeatureContext
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features.
Definition: qgsvectorlayerutils.h:48
QgsRelationEditorWidget::nmRelationId
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
Definition: qgsrelationeditorwidget.cpp:995
qgstransactiongroup.h
QgsDualView::AttributeEditor
@ AttributeEditor
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
Definition: qgsdualview.h:65
qgsvectordataprovider.h
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:583
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QgsRelationEditorWidget::setShowLinkButton
Q_DECL_DEPRECATED void setShowLinkButton(bool showLinkButton)
Determines if the "link feature" button should be shown.
Definition: qgsrelationeditorwidget.cpp:934
qgsvectorlayerutils.h
QgsActionMenu
This class is a menu that is populated automatically with the actions defined for a given layer.
Definition: qgsactionmenu.h:38
QgsMapToolDigitizeFeature
This tool digitizes geometry of new point/line/polygon features on already existing vector layers Onc...
Definition: qgsmaptooldigitizefeature.h:32
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:264
QgsRelationEditorWidget::setShowSaveChildEditsButton
Q_DECL_DEPRECATED void setShowSaveChildEditsButton(bool showChildEdits)
Determines if the "Save child layer edits" button should be shown.
Definition: qgsrelationeditorwidget.cpp:944
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:105
QgsRelation::getReferencedFeatureRequest
QgsFeatureRequest getReferencedFeatureRequest(const QgsAttributes &attributes) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
Definition: qgsrelation.cpp:214
qgsmessagebar.h
QgsAttributeTableModel::layer
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
Definition: qgsattributetablemodel.h:168
QgsVectorLayerSelectionManager
Definition: qgsvectorlayerselectionmanager.h:33
QgsMapTool::setButton
void setButton(QAbstractButton *button)
Use this to associate a button to this maptool.
Definition: qgsmaptool.cpp:136
QgsRelationEditorWidget::setLabel
void setLabel(const QString &label=QString())
Sets label for this element If it's empty it takes the relation id as label.
Definition: qgsrelationeditorwidget.cpp:1005
qgsrelation.h
QgsMapCanvas::setMapTool
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
Definition: qgsmapcanvas.cpp:2006
QgsFeatureRequest::setNoAttributes
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
Definition: qgsfeaturerequest.cpp:192
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsRelation::FieldPair
Defines a relation between matching fields of the two involved tables of a relation.
Definition: qgsrelation.h:75
QgsRelationEditorWidget::showSaveChildEditsButton
Q_DECL_DEPRECATED bool showSaveChildEditsButton() const
Determines if the "Save child layer edits" button should be shown.
Definition: qgsrelationeditorwidget.cpp:949
QgsDualView::ViewMode
ViewMode
The view modes, in which this widget can present information.
Definition: qgsdualview.h:53
QgsVectorLayerUtils::createFeature
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.
Definition: qgsvectorlayerutils.cpp:476
QgsRelation::fieldPairs
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
Definition: qgsrelation.cpp:292
QgsVectorLayerSelectionManager::selectedFeatureCount
int selectedFeatureCount() override
Returns the number of features that are selected in this layer.
Definition: qgsvectorlayerselectionmanager.cpp:27
QgsRelationEditorWidget::editorContext
QgsAttributeEditorContext editorContext() const
Returns the attribute editor context.
Definition: qgsrelationeditorwidget.cpp:380
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsVectorLayer::editingStopped
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
QgsRelation::getRelatedFeaturesRequest
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
Definition: qgsrelation.cpp:191
QgsRelationEditorWidget::setRelations
void setRelations(const QgsRelation &relation, const QgsRelation &nmrelation)
Set the relation(s) for this widget If only one relation is set, it will act as a simple 1:N relation...
Definition: qgsrelationeditorwidget.cpp:297
QgsRelationEditorWidget::setShowLabel
void setShowLabel(bool showLabel)
Defines if a title label should be shown for this widget.
Definition: qgsrelationeditorwidget.cpp:1027
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:374
QgsVectorLayer::deleteFeatures
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
Definition: qgsvectorlayer.cpp:3267
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsRelationEditorWidget::setRelationFeature
void setRelationFeature(const QgsRelation &relation, const QgsFeature &feature)
Sets the relation and the feature.
Definition: qgsrelationeditorwidget.cpp:220
QgsVectorDataProvider::ChangeAttributeValues
@ ChangeAttributeValues
Allows modification of attribute values.
Definition: qgsvectordataprovider.h:77
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsDualView::parentFormValueChanged
void parentFormValueChanged(const QString &attribute, const QVariant &value)
Called in embedded forms when an attribute value in the parent form has changed.
Definition: qgsdualview.cpp:740
QgsVectorLayerTools::stopEditing
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.
QgsRelation::isValid
bool isValid
Definition: qgsrelation.h:49
QgsCollapsibleGroupBoxBasic::collapsedStateChanged
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
QgsDualView::setFeatureSelectionManager
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
Definition: qgsdualview.cpp:1139
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:86
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:627
QgsExpression::quotedColumnRef
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Definition: qgsexpression.cpp:65
QgsMapCanvas::keyPressed
void keyPressed(QKeyEvent *e)
Emit key press event.
QgsRelationEditorWidget::featureSelectionManager
QgsIFeatureSelectionManager * featureSelectionManager()
The feature selection manager is responsible for the selected features which are currently being edit...
Definition: qgsrelationeditorwidget.cpp:385
QgsMapCanvas::unsetMapTool
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
Definition: qgsmapcanvas.cpp:2046
QgsRelation
Definition: qgsrelation.h:42
QgsVectorLayerUtils::impactsCascadeFeatures
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
Definition: qgsvectorlayerutils.cpp:987
QgsRelationEditorWidget::setVisibleButtons
void setVisibleButtons(const QgsAttributeEditorRelation::Buttons &buttons)
Defines the buttons which are shown.
Definition: qgsrelationeditorwidget.cpp:954
QgsRelationEditorWidget::setEditorContext
void setEditorContext(const QgsAttributeEditorContext &context)
Sets the editor context.
Definition: qgsrelationeditorwidget.cpp:367
QgsRelationEditorWidget::forceSuppressFormPopup
bool forceSuppressFormPopup() const
Determines the force suppress form popup status that is configured for this widget.
Definition: qgsrelationeditorwidget.cpp:985
qgsdistancearea.h
QgsRelationEditorWidget::setNmRelationId
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
Definition: qgsrelationeditorwidget.cpp:990
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsDualView::showContextMenuExternally
void showContextMenuExternally(QgsActionMenu *menu, QgsFeatureId fid)
Emitted when selecting context menu on the feature list to create the context menu individually.
qgsfeatureselectiondlg.h
QgsVectorLayer::getFeature
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Definition: qgsvectorlayer.h:1194
QgsIFeatureSelectionManager
Is an interface class to abstract feature selection handling.
Definition: qgsifeatureselectionmanager.h:32
QgsMessageBar::createMessage
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=nullptr)
Creates message bar item widget containing a message text to be displayed on the bar.
Definition: qgsmessagebar.cpp:363
qgslogger.h
QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicatedFeatures
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
Definition: qgsvectorlayerutils.cpp:823
QgsRelationEditorWidget::showUnlinkButton
Q_DECL_DEPRECATED bool showUnlinkButton() const
Determines if the "unlink feature" button should be shown.
Definition: qgsrelationeditorwidget.cpp:939
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QgsVectorLayer::createExpressionContext
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsvectorlayer.cpp:4952
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsAttributeEditorContext
This class contains context information for attribute editor widgets.
Definition: qgsattributeeditorcontext.h:41
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:265
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
QgsVectorLayer::addFeature
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
Definition: qgsvectorlayer.cpp:1011
QgsCollapsibleGroupBoxBasic::collapsed
bool collapsed
The collapsed state of this group box.
Definition: qgscollapsiblegroupbox.h:79
QgsAttributeEditorContext::mainMessageBar
QgsMessageBar * mainMessageBar()
Returns the main message bar.
Definition: qgsattributeeditorcontext.h:292
QgsVectorLayerTools::startEditing
virtual bool startEditing(QgsVectorLayer *layer) const =0
This will be called, whenever a vector layer should be switched to edit mode.
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:179
QgsExpression::expression
QString expression() const
Returns the original, unmodified expression string.
Definition: qgsexpression.cpp:57
QgsVectorLayerSelectionManager::selectedFeatureIds
const QgsFeatureIds & selectedFeatureIds() const override
Returns reference to identifiers of selected features.
Definition: qgsvectorlayerselectionmanager.cpp:47
qgsproject.h
QgsFields::indexFromName
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
QgsAttributeEditorContext::vectorLayerTools
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
Definition: qgsattributeeditorcontext.h:172
QgsMessageBar::pushMessage
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::Info, int duration=5)
A convenience method for pushing a message with the specified text to the bar.
Definition: qgsmessagebar.cpp:379
qgsgenericfeatureselectionmanager.h
QgsAttributeEditorContext::setFormFeature
void setFormFeature(const QgsFeature &feature)
Set current feature for the currently edited form or table row.
Definition: qgsattributeeditorcontext.h:244
QgsMapTool::deactivated
void deactivated()
signal emitted once the map tool is deactivated
QgsFields::indexOf
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsVectorLayerUtils::getFeatureDisplayString
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
Definition: qgsvectorlayerutils.cpp:975
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50