QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 "qgsvectordataprovider.h"
21 #include "qgsexpression.h"
22 #include "qgsfeature.h"
23 #include "qgsfeatureselectiondlg.h"
25 #include "qgsrelation.h"
26 #include "qgsvectorlayertools.h"
27 #include "qgsproject.h"
28 #include "qgstransactiongroup.h"
29 
30 #include <QHBoxLayout>
31 #include <QLabel>
32 
34  : QgsCollapsibleGroupBox( parent )
35  , mViewMode( QgsDualView::AttributeEditor )
36  , mShowLabel( true )
37  , mVisible( false )
38 {
39  QVBoxLayout* topLayout = new QVBoxLayout( this );
40  topLayout->setContentsMargins( 0, 9, 0, 0 );
41  setLayout( topLayout );
42 
43  // buttons
44  QHBoxLayout* buttonLayout = new QHBoxLayout();
45  buttonLayout->setContentsMargins( 0, 0, 0, 0 );
46  // toogle editing
47  mToggleEditingButton = new QToolButton( this );
48  mToggleEditingButton->setObjectName( "mToggleEditingButton" );
49  mToggleEditingButton->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ) );
50  mToggleEditingButton->setText( tr( "Toggle editing" ) );
51  mToggleEditingButton->setEnabled( false );
52  mToggleEditingButton->setCheckable( true );
53  mToggleEditingButton->setToolTip( tr( "Toggle editing mode for child layer" ) );
54  buttonLayout->addWidget( mToggleEditingButton );
55  // save Edits
56  mSaveEditsButton = new QToolButton( this );
57  mSaveEditsButton->setIcon( QgsApplication::getThemeIcon( "/mActionSaveEdits.svg" ) );
58  mSaveEditsButton->setText( tr( "Save child layer edits" ) );
59  mSaveEditsButton->setToolTip( tr( "Save child layer edits" ) );
60  mSaveEditsButton->setEnabled( true );
61  buttonLayout->addWidget( mSaveEditsButton );
62  // add feature
63  mAddFeatureButton = new QToolButton( this );
64  mAddFeatureButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewTableRow.svg" ) );
65  mAddFeatureButton->setText( tr( "Add child feature" ) );
66  mAddFeatureButton->setToolTip( tr( "Add child feature" ) );
67  mAddFeatureButton->setObjectName( "mAddFeatureButton" );
68  buttonLayout->addWidget( mAddFeatureButton );
69  // delete feature
70  mDeleteFeatureButton = new QToolButton( this );
71  mDeleteFeatureButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) );
72  mDeleteFeatureButton->setText( tr( "Delete child feature" ) );
73  mDeleteFeatureButton->setToolTip( tr( "Delete child feature" ) );
74  mDeleteFeatureButton->setObjectName( "mDeleteFeatureButton" );
75  buttonLayout->addWidget( mDeleteFeatureButton );
76  // link feature
77  mLinkFeatureButton = new QToolButton( this );
78  mLinkFeatureButton->setIcon( QgsApplication::getThemeIcon( "/mActionLink.svg" ) );
79  mLinkFeatureButton->setText( tr( "Link existing features" ) );
80  mLinkFeatureButton->setToolTip( tr( "Link existing child features" ) );
81  mLinkFeatureButton->setObjectName( "mLinkFeatureButton" );
82  buttonLayout->addWidget( mLinkFeatureButton );
83  // unlink feature
84  mUnlinkFeatureButton = new QToolButton( this );
85  mUnlinkFeatureButton->setIcon( QgsApplication::getThemeIcon( "/mActionUnlink.svg" ) );
86  mUnlinkFeatureButton->setText( tr( "Unlink feature" ) );
87  mUnlinkFeatureButton->setToolTip( tr( "Unlink child feature" ) );
88  mUnlinkFeatureButton->setObjectName( "mUnlinkFeatureButton" );
89  buttonLayout->addWidget( mUnlinkFeatureButton );
90  // spacer
91  buttonLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding ) );
92  // form view
93  mFormViewButton = new QToolButton( this );
94  mFormViewButton->setText( tr( "Form view" ) );
95  mFormViewButton->setToolTip( tr( "Switch to form view" ) );
96  mFormViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionPropertyItem.svg" ) );
97  mFormViewButton->setCheckable( true );
98  mFormViewButton->setChecked( mViewMode == QgsDualView::AttributeEditor );
99  buttonLayout->addWidget( mFormViewButton );
100  // table view
101  mTableViewButton = new QToolButton( this );
102  mTableViewButton->setText( tr( "Table view" ) );
103  mTableViewButton->setToolTip( tr( "Switch to table view" ) );
104  mTableViewButton->setIcon( QgsApplication::getThemeIcon( "/mActionOpenTable.svg" ) );
105  mTableViewButton->setCheckable( true );
106  mTableViewButton->setChecked( mViewMode == QgsDualView::AttributeTable );
107  buttonLayout->addWidget( mTableViewButton );
108  // button group
109  mViewModeButtonGroup = new QButtonGroup( this );
110  mViewModeButtonGroup->addButton( mFormViewButton, QgsDualView::AttributeEditor );
111  mViewModeButtonGroup->addButton( mTableViewButton, QgsDualView::AttributeTable );
112 
113  // add buttons layout
114  topLayout->addLayout( buttonLayout );
115 
116  mRelationLayout = new QGridLayout();
117  mRelationLayout->setContentsMargins( 0, 0, 0, 0 );
118  topLayout->addLayout( mRelationLayout );
119 
120  mDualView = new QgsDualView( this );
121  mDualView->setView( mViewMode );
122  mFeatureSelectionMgr = new QgsGenericFeatureSelectionManager( mDualView );
123  mDualView->setFeatureSelectionManager( mFeatureSelectionMgr );
124 
125  mRelationLayout->addWidget( mDualView );
126 
127  connect( this, SIGNAL( collapsedStateChanged( bool ) ), this, SLOT( onCollapsedStateChanged( bool ) ) );
128  connect( mViewModeButtonGroup, SIGNAL( buttonClicked( int ) ), this, SLOT( setViewMode( int ) ) );
129  connect( mToggleEditingButton, SIGNAL( clicked( bool ) ), this, SLOT( toggleEditing( bool ) ) );
130  connect( mSaveEditsButton, SIGNAL( clicked() ), this, SLOT( saveEdits() ) );
131  connect( mAddFeatureButton, SIGNAL( clicked() ), this, SLOT( addFeature() ) );
132  connect( mDeleteFeatureButton, SIGNAL( clicked() ), this, SLOT( deleteFeature() ) );
133  connect( mLinkFeatureButton, SIGNAL( clicked() ), this, SLOT( linkFeature() ) );
134  connect( mUnlinkFeatureButton, SIGNAL( clicked() ), this, SLOT( unlinkFeature() ) );
135  connect( mFeatureSelectionMgr, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SLOT( updateButtons() ) );
136 
137  // Set initial state for add/remove etc. buttons
138  updateButtons();
139 }
140 
142 {
143  if ( mRelation.isValid() )
144  {
145  disconnect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
146  disconnect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
147  }
148 
149  mRelation = relation;
150  mFeature = feature;
151 
152  connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
153  connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
154 
155  if ( mShowLabel )
156  setTitle( relation.name() );
157 
158  QgsVectorLayer* lyr = relation.referencingLayer();
159 
160  bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
161  if ( canChangeAttributes && !lyr->readOnly() )
162  {
163  mToggleEditingButton->setEnabled( true );
164  updateButtons();
165  }
166  else
167  {
168  mToggleEditingButton->setEnabled( false );
169  }
170 
171  setObjectName( mRelation.name() );
172  loadState();
173 
174  // If not yet initialized, it is not (yet) visible, so we don't load it to be faster (lazy loading)
175  // If it is already initialized, it has been set visible before and the currently shown feature is changing
176  // and the widget needs updating
177 
178  if ( mVisible )
179  {
180  QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
181 
182  mDualView->init( mRelation.referencingLayer(), nullptr, myRequest, mEditorContext );
183  }
184 }
185 
186 void QgsRelationEditorWidget::setRelations( const QgsRelation& relation, const QgsRelation& nmrelation )
187 {
188  if ( mRelation.isValid() )
189  {
190  disconnect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
191  disconnect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
192  }
193 
194  if ( mNmRelation.isValid() )
195  {
196  disconnect( mNmRelation.referencedLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
197  disconnect( mNmRelation.referencedLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
198  }
199 
200  mRelation = relation;
201  mNmRelation = nmrelation;
202 
203  if ( !mRelation.isValid() )
204  return;
205 
206  connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
207  connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
208 
209  if ( mNmRelation.isValid() )
210  {
211  connect( mNmRelation.referencedLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) );
212  connect( mNmRelation.referencedLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) );
213  }
214 
215  setTitle( relation.name() );
216 
217  QgsVectorLayer* lyr = relation.referencingLayer();
218 
219  bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
220  if ( canChangeAttributes && !lyr->readOnly() )
221  {
222  mToggleEditingButton->setEnabled( true );
223  updateButtons();
224  }
225  else
226  {
227  mToggleEditingButton->setEnabled( false );
228  }
229 
230  setObjectName( mRelation.name() );
231  loadState();
232 
233  updateUi();
234 }
235 
237 {
238  mEditorContext = context;
239 }
240 
242 {
243  return mFeatureSelectionMgr;
244 }
245 
247 {
248  mDualView->setView( mode );
249  mViewMode = mode;
250 }
251 
252 
254 {
255  mFeature = feature;
256 
257  updateUi();
258 }
259 
260 void QgsRelationEditorWidget::updateButtons()
261 {
262  bool editable = false;
263  bool linkable = false;
264  bool selectionNotEmpty = mFeatureSelectionMgr->selectedFeatureCount();
265 
266  if ( mRelation.isValid() )
267  {
268  editable = mRelation.referencingLayer()->isEditable();
269  linkable = mRelation.referencingLayer()->isEditable();
270  }
271 
272  if ( mNmRelation.isValid() )
273  {
274  editable = mNmRelation.referencedLayer()->isEditable();
275  }
276 
277  mAddFeatureButton->setEnabled( editable );
278  mLinkFeatureButton->setEnabled( linkable );
279  mDeleteFeatureButton->setEnabled( editable && selectionNotEmpty );
280  mUnlinkFeatureButton->setEnabled( linkable && selectionNotEmpty );
281  mToggleEditingButton->setChecked( editable );
282  mSaveEditsButton->setEnabled( editable );
283 }
284 
285 void QgsRelationEditorWidget::addFeature()
286 {
287  QgsAttributeMap keyAttrs;
288 
289  const QgsVectorLayerTools* vlTools = mEditorContext.vectorLayerTools();
290 
291  if ( mNmRelation.isValid() )
292  {
293  // n:m Relation: first let the user create a new feature on the other table
294  // and autocreate a new linking feature.
295  QgsFeature f;
296  if ( vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), QgsGeometry(), &f ) )
297  {
298  QgsFields fields = mRelation.referencingLayer()->fields();
299  QgsFeature flink( fields ); // Linking feature
300  int attrCount = fields.size();
301 
302  int firstIdx = fields.indexFromName( mRelation.fieldPairs().at( 0 ).first );
303  int secondIdx = mNmRelation.referencingFields().at( 0 );
304 
305  for ( int i = 0; i < attrCount; ++i )
306  {
307  if ( i == firstIdx )
308  flink.setAttribute( i, mFeature.attribute( mRelation.fieldPairs().at( 0 ).second ) );
309  else if ( i == secondIdx )
310  flink.setAttribute( i, f.attribute( mNmRelation.referencedFields().at( 0 ) ) );
311  else
312  flink.setAttribute( i, mRelation.referencingLayer()->defaultValue( i ) );
313  }
314 
315  mRelation.referencingLayer()->addFeature( flink );
316 
317  updateUi();
318  }
319  }
320  else
321  {
322  QgsFields fields = mRelation.referencingLayer()->fields();
323 
324  Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() )
325  {
326  keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
327  }
328 
329  vlTools->addFeature( mDualView->masterModel()->layer(), keyAttrs );
330  }
331 }
332 
333 void QgsRelationEditorWidget::linkFeature()
334 {
335  QgsVectorLayer* layer;
336 
337  if ( mNmRelation.isValid() )
338  layer = mNmRelation.referencedLayer();
339  else
340  layer = mRelation.referencingLayer();
341 
342  QgsFeatureSelectionDlg selectionDlg( layer, mEditorContext , this );
343 
344  if ( selectionDlg.exec() )
345  {
346  if ( mNmRelation.isValid() )
347  {
348  QgsFeatureIterator it = mNmRelation.referencedLayer()->getFeatures(
350  .setFilterFids( selectionDlg.selectedFeatures() )
351  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
352 
353  QgsFields fields = mRelation.referencingLayer()->fields();
354  int attrCount = fields.size();
355  int firstIdx = fields.indexFromName( mRelation.fieldPairs().at( 0 ).first );
356  int secondIdx = mNmRelation.referencingFields().at( 0 );
357  QgsFeature relatedFeature;
358 
359  QgsFeatureList newFeatures;
360  QgsFeature linkFeature( fields );
361 
362  Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() )
363  {
364  linkFeature.setAttribute( fieldPair.first, mFeature.attribute( fieldPair.second ) );
365  }
366 
367  while ( it.nextFeature( relatedFeature ) )
368  {
369  for ( int i = 0; i < attrCount; ++i )
370  {
371  if ( i == firstIdx )
372  linkFeature.setAttribute( i, mFeature.attribute( mRelation.fieldPairs().at( 0 ).second ) );
373  else if ( i == secondIdx )
374  linkFeature.setAttribute( i, relatedFeature.attribute( mNmRelation.referencedFields().at( 0 ) ) );
375  else
376  linkFeature.setAttribute( i, mRelation.referencingLayer()->defaultValue( i ) );
377  }
378 
379  newFeatures << linkFeature;
380  }
381 
382  // TODO: what to do in case of addFeature fail?
383  mRelation.referencingLayer()->addFeatures( newFeatures );
384 
385  updateUi();
386  }
387  else
388  {
389  QMap<int, QVariant> keys;
390  Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() )
391  {
392  int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
393  QVariant val = mFeature.attribute( fieldPair.referencedField() );
394  keys.insert( idx, val );
395  }
396 
397  Q_FOREACH ( QgsFeatureId fid, selectionDlg.selectedFeatures() )
398  {
399  QMapIterator<int, QVariant> it( keys );
400  while ( it.hasNext() )
401  {
402  it.next();
403  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), it.value() );
404  }
405  }
406  }
407  }
408 }
409 
410 void QgsRelationEditorWidget::deleteFeature()
411 {
412  QgsVectorLayer* layer;
413 
414  if ( mNmRelation.isValid() )
415  // So far we expect the database to take care of cleaning up the linking table or restricting
416  // TODO: add more options for the behavior here
417  layer = mNmRelation.referencedLayer();
418  else
419  layer = mRelation.referencingLayer();
420  QgsDebugMsg( QString( "Delete %1" ).arg( mFeatureSelectionMgr->selectedFeaturesIds().size() ) );
421  layer->deleteFeatures( mFeatureSelectionMgr->selectedFeaturesIds() );
422 }
423 
424 void QgsRelationEditorWidget::unlinkFeature()
425 {
426  if ( mNmRelation.isValid() )
427  {
428  QgsFeatureIterator selectedIterator = mNmRelation.referencedLayer()->getFeatures(
430  .setFilterFids( mFeatureSelectionMgr->selectedFeaturesIds() )
431  .setSubsetOfAttributes( mNmRelation.referencedFields() ) );
432 
433  QgsFeature f;
434 
435  QStringList filters;
436 
437  while ( selectedIterator.nextFeature( f ) )
438  {
439  filters << '(' + mNmRelation.getRelatedFeaturesRequest( f ).filterExpression()->expression() + ')';
440  }
441 
442  QString filter = QString( "(%1) AND (%2)" ).arg(
443  mRelation.getRelatedFeaturesRequest( mFeature ).filterExpression()->expression(),
444  filters.join( " OR " ) );
445 
446  QgsFeatureIterator linkedIterator = mRelation.referencingLayer()->getFeatures( QgsFeatureRequest()
447  .setSubsetOfAttributes( QgsAttributeList() )
448  .setFilterExpression( filter ) );
449 
450  QgsFeatureIds fids;
451 
452  while ( linkedIterator.nextFeature( f ) )
453  fids << f.id();
454 
455  mRelation.referencingLayer()->deleteFeatures( fids );
456 
457  updateUi();
458  }
459  else
460  {
461  QMap<int, QgsField> keyFields;
462  Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() )
463  {
464  int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
465  if ( idx < 0 )
466  {
467  QgsDebugMsg( QString( "referencing field %1 not found" ).arg( fieldPair.referencingField() ) );
468  return;
469  }
470  QgsField fld = mRelation.referencingLayer()->fields().at( idx );
471  keyFields.insert( idx, fld );
472  }
473 
474  Q_FOREACH ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
475  {
476  QMapIterator<int, QgsField> it( keyFields );
477  while ( it.hasNext() )
478  {
479  it.next();
480  mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
481  }
482  }
483  }
484 }
485 
486 void QgsRelationEditorWidget::toggleEditing( bool state )
487 {
488  if ( state )
489  {
490  mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
491  if ( mNmRelation.isValid() )
492  mEditorContext.vectorLayerTools()->startEditing( mNmRelation.referencedLayer() );
493  }
494  else
495  {
496  mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
497  if ( mNmRelation.isValid() )
498  mEditorContext.vectorLayerTools()->stopEditing( mNmRelation.referencedLayer() );
499  }
500 }
501 
502 void QgsRelationEditorWidget::saveEdits()
503 {
504  mEditorContext.vectorLayerTools()->saveEdits( mRelation.referencingLayer() );
505  if ( mNmRelation.isValid() )
506  mEditorContext.vectorLayerTools()->saveEdits( mNmRelation.referencedLayer() );
507 }
508 
509 void QgsRelationEditorWidget::onCollapsedStateChanged( bool collapsed )
510 {
511 
512  if ( !collapsed )
513  {
514  mVisible = true;
515  updateUi();
516  }
517 }
518 
519 void QgsRelationEditorWidget::updateUi()
520 {
521  // If not yet initialized, it is not (yet) visible, so we don't load it to be faster (lazy loading)
522  // If it is already initialized, it has been set visible before and the currently shown feature is changing
523  // and the widget needs updating
524 
525  if ( mVisible )
526  {
527  QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature );
528 
529  if ( mNmRelation.isValid() )
530  {
531  QgsFeatureIterator it = mRelation.referencingLayer()->getFeatures( myRequest );
532 
533  QgsFeature fet;
534 
535  QStringList filters;
536 
537  while ( it.nextFeature( fet ) )
538  {
539  QString filter = mNmRelation.getReferencedFeatureRequest( fet ).filterExpression()->expression();
540  filters << filter.prepend( '(' ).append( ')' );
541  }
542 
543  QgsFeatureRequest nmRequest;
544 
545  nmRequest.setFilterExpression( filters.join( " OR " ) );
546 
547  mDualView->init( mNmRelation.referencedLayer(), nullptr, nmRequest, mEditorContext );
548  }
549  else
550  {
551  mDualView->init( mRelation.referencingLayer(), nullptr, myRequest, mEditorContext );
552  }
553  }
554 
555  mToggleEditingButton->setVisible( true );
556 
557  Q_FOREACH ( QgsTransactionGroup* tg, QgsProject::instance()->transactionGroups().values() )
558  {
559  if ( tg->layers().contains( mRelation.referencingLayer() ) )
560  {
561  mToggleEditingButton->setVisible( false );
562  mSaveEditsButton->setVisible( false );
563  }
564  }
565 }
566 
568 {
569  return mLinkFeatureButton->isVisible();
570 }
571 
573 {
574  mLinkFeatureButton->setVisible( showLinkButton );
575 }
576 
578 {
579  return mUnlinkFeatureButton->isVisible();
580 }
581 
583 {
584  mUnlinkFeatureButton->setVisible( showUnlinkButton );
585 }
586 
588 {
589  return mShowLabel;
590 }
591 
593 {
594  mShowLabel = showLabel;
595 
596  if ( mShowLabel && mRelation.isValid() )
597  setTitle( mRelation.name() );
598  else
599  setTitle( QString() );
600 }
Methods in this class are used to handle basic operations on vector layers.
const QgsVectorLayerTools * vectorLayerTools() const
bool showUnlinkButton() const
Determines if the "unlink feature" button should be shown.
Wrapper for iterator of features from vector data provider or vector layer.
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
bool isValid() const
Returns the validity of this relation.
virtual bool saveEdits(QgsVectorLayer *layer) const =0
Should be called, when the features should be commited but the editing session is not ended...
QString & append(QChar ch)
void setContentsMargins(int left, int top, int right, int bottom)
int size() const
Return number of items.
Definition: qgsfield.cpp:407
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:71
bool collapsed
The collapsed state of this group box.
QgsAttributeList referencingFields() const
Returns a list of attributes used to form the referencing fields (foreign key) on the referencing (ch...
virtual bool startEditing(QgsVectorLayer *layer) const =0
This will be called, whenever a vector layer should be switched to edit mode.
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered) ...
Definition: qgsdualview.h:159
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:104
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
void addButton(QAbstractButton *button)
virtual int selectedFeatureCount() override
The number of features that are selected in this layer.
void clicked(bool checked)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
This class contains context information for attribute editor widgets.
int size() const
QString & prepend(QChar ch)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
const T & at(int i) const
ViewMode
The view modes, in which this widget can present information.
Definition: qgsdualview.h:55
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
virtual void setVisible(bool visible)
QSet< QgsVectorLayer * > layers() const
Get the set of layers currently managed by this transaction group.
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
int exec()
Container of fields for a vector layer.
Definition: qgsfield.h:252
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:222
bool showLinkButton() const
Determines if the "link feature" button should be shown.
virtual bool stopEditing(QgsVectorLayer *layer, bool allowCancel=true) const =0
Will be called, when an editing session is ended and the features should be commited.
QString join(const QString &separator) const
virtual const QgsFeatureIds & selectedFeaturesIds() const override
Return reference to identifiers of selected features.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
bool addFeature(QgsFeature &feature, bool alsoUpdateExtent=true)
Adds a feature.
void setViewMode(QgsDualView::ViewMode mode)
Define the view mode for the dual view.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
void setIcon(const QIcon &icon)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setView(ViewMode view)
Change the current view mode.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
const QgsFeatureIds & selectedFeatures()
Get the selected features.
QgsFields fields() const
Returns the list of fields of this layer.
QgsExpression * filterExpression() const
Returns the filter expression if set.
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
Definition: qgsdualview.h:66
void setShowLinkButton(bool showLinkButton)
Determines if the "link feature" button should be shown.
QgsAttributeList referencedFields() const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
void setEnabled(bool)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest getReferencedFeatureRequest(const QgsAttributes &attributes) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
Defines a relation between matching fields of the two involved tables of a relation.
Definition: qgsrelation.h:42
void setLayout(QLayout *layout)
Shows the features and attributes in a table layout.
Definition: qgsdualview.h:60
void setShowUnlinkButton(bool showUnlinkButton)
Determines if the "unlink feature" button should be shown.
virtual void addItem(QLayoutItem *item)
void setObjectName(const QString &name)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
QgsRelationEditorWidget(QWidget *parent=nullptr)
void setCheckable(bool)
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
const Key & key() const
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
const T & value() const
bool addFeatures(QgsFeatureList features, bool makeSelected=true)
Insert a copy of the given features into the layer (but does not commit it)
Q_DECL_DEPRECATED bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &value, bool emitSignal)
Changes an attribute value (but does not commit it)
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
QList< FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
QgsVectorLayer * referencedLayer() const
Access the referenced (parent) layer.
QString expression() const
Return the original, unmodified expression string.
This selection manager synchronizes a local set of selected features with an attribute table...
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...
bool contains(const T &value) const
void setChecked(bool)
void setRelationFeature(const QgsRelation &relation, const QgsFeature &feature)
QgsVectorLayer * referencingLayer() const
Access the referencing (child) layer This is the layer which has the field(s) which point to another ...
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:461
QgsIFeatureSelectionManager * featureSelectionManager()
The feature selection manager is responsible for the selected features which are currently being edit...
void setTitle(const QString &title)
void setShowLabel(bool showLabel)
Defines if a title label should be shown for this widget.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
void setEditorContext(const QgsAttributeEditorContext &context)
QString referencedField() const
Get the name of the referenced (parent) field.
Definition: qgsrelation.h:56
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.
void loadState()
Will load the collapsed and checked state.
qint64 QgsFeatureId
Definition: qgsfeature.h:31
void setText(const QString &text)
iterator insert(const Key &key, const T &value)
void setToolTip(const QString &)
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Is an interface class to abstract feature selection handling.
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
QString referencingField() const
Get the name of the referencing (child) field.
Definition: qgsrelation.h:54
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Allows modification of attribute values.
void setFeature(const QgsFeature &feature)
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QString name() const
Returns a human readable name for this relation.
This widget is used to show the attributes of a set of features of a QgsVectorLayer.
Definition: qgsdualview.h:43
bool hasNext() const
bool showLabel() const
Defines if a title label should be shown for this widget.
void addLayout(QLayout *layout, int stretch)
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.