QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsrelationreferencewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrelationreferencewidget.cpp
3  --------------------------------------
4  Date : 20.4.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 <QPushButton>
19 #include <QDialog>
20 #include <QHBoxLayout>
21 #include <QTimer>
22 #include <QCompleter>
23 
24 #include "qgsattributeform.h"
26 #include "qgsattributedialog.h"
27 #include "qgsapplication.h"
28 #include "qgscollapsiblegroupbox.h"
29 #include "qgseditorwidgetfactory.h"
30 #include "qgsexpression.h"
31 #include "qgsfeaturelistmodel.h"
32 #include "qgsfields.h"
33 #include "qgsgeometry.h"
34 #include "qgshighlight.h"
35 #include "qgsmapcanvas.h"
36 #include "qgsmessagebar.h"
38 #include "qgsvectorlayer.h"
39 #include "qgsattributetablemodel.h"
42 #include "qgsfeatureiterator.h"
43 #include "qgsfeaturelistcombobox.h"
45 #include "qgsfeaturefiltermodel.h"
46 #include "qgsidentifymenu.h"
47 #include "qgsvectorlayerutils.h"
48 
49 
50 bool qVariantListIsNull( const QVariantList &list )
51 {
52  if ( list.isEmpty() )
53  return true;
54 
55  for ( int i = 0; i < list.size(); ++i )
56  {
57  if ( !list.at( i ).isNull() )
58  return false;
59  }
60  return true;
61 }
62 
63 
65  : QWidget( parent )
66 {
67  mTopLayout = new QVBoxLayout( this );
68  mTopLayout->setContentsMargins( 0, 0, 0, 0 );
69 
70  setSizePolicy( sizePolicy().horizontalPolicy(), QSizePolicy::Fixed );
71 
72  setLayout( mTopLayout );
73 
74  QHBoxLayout *editLayout = new QHBoxLayout();
75  editLayout->setContentsMargins( 0, 0, 0, 0 );
76  editLayout->setSpacing( 2 );
77 
78  // Prepare the container and layout for the filter comboboxes
79  mChooserContainer = new QWidget;
80  editLayout->addWidget( mChooserContainer );
81  QHBoxLayout *chooserLayout = new QHBoxLayout;
82  chooserLayout->setContentsMargins( 0, 0, 0, 0 );
83  mFilterLayout = new QHBoxLayout;
84  mFilterLayout->setContentsMargins( 0, 0, 0, 0 );
85  mFilterContainer = new QWidget;
86  mFilterContainer->setLayout( mFilterLayout );
87  mChooserContainer->setLayout( chooserLayout );
88  chooserLayout->addWidget( mFilterContainer );
89 
90  mComboBox = new QgsFeatureListComboBox();
91  mChooserContainer->layout()->addWidget( mComboBox );
92 
93  // read-only line edit
94  mLineEdit = new QLineEdit();
95  mLineEdit->setReadOnly( true );
96  editLayout->addWidget( mLineEdit );
97 
98  // open form button
99  mOpenFormButton = new QToolButton();
100  mOpenFormButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPropertyItem.svg" ) ) );
101  mOpenFormButton->setText( tr( "Open Related Feature Form" ) );
102  editLayout->addWidget( mOpenFormButton );
103 
104  mAddEntryButton = new QToolButton();
105  mAddEntryButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAdd.svg" ) ) );
106  mAddEntryButton->setText( tr( "Add New Entry" ) );
107  editLayout->addWidget( mAddEntryButton );
108 
109  // highlight button
110  mHighlightFeatureButton = new QToolButton( this );
111  mHighlightFeatureButton->setPopupMode( QToolButton::MenuButtonPopup );
112  mHighlightFeatureAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHighlightFeature.svg" ) ), tr( "Highlight feature" ), this );
113  mScaleHighlightFeatureAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionScaleHighlightFeature.svg" ) ), tr( "Scale and highlight feature" ), this );
114  mPanHighlightFeatureAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPanHighlightFeature.svg" ) ), tr( "Pan and highlight feature" ), this );
115  mHighlightFeatureButton->addAction( mHighlightFeatureAction );
116  mHighlightFeatureButton->addAction( mScaleHighlightFeatureAction );
117  mHighlightFeatureButton->addAction( mPanHighlightFeatureAction );
118  mHighlightFeatureButton->setDefaultAction( mHighlightFeatureAction );
119  editLayout->addWidget( mHighlightFeatureButton );
120 
121  // map identification button
122  mMapIdentificationButton = new QToolButton( this );
123  mMapIdentificationButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapIdentification.svg" ) ) );
124  mMapIdentificationButton->setText( tr( "Select on Map" ) );
125  mMapIdentificationButton->setCheckable( true );
126  editLayout->addWidget( mMapIdentificationButton );
127 
128  // remove foreign key button
129  mRemoveFKButton = new QToolButton( this );
130  mRemoveFKButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemove.svg" ) ) );
131  mRemoveFKButton->setText( tr( "No Selection" ) );
132  editLayout->addWidget( mRemoveFKButton );
133 
134  // add line to top layout
135  mTopLayout->addLayout( editLayout );
136 
137  // embed form
138  mAttributeEditorFrame = new QgsCollapsibleGroupBox( this );
139  mAttributeEditorLayout = new QVBoxLayout( mAttributeEditorFrame );
140  mAttributeEditorFrame->setLayout( mAttributeEditorLayout );
141  mAttributeEditorFrame->setSizePolicy( mAttributeEditorFrame->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
142  mTopLayout->addWidget( mAttributeEditorFrame );
143 
144  // invalid label
145  mInvalidLabel = new QLabel( tr( "The relation is not valid. Please make sure your relation definitions are OK." ) );
146  mInvalidLabel->setWordWrap( true );
147  QFont font = mInvalidLabel->font();
148  font.setItalic( true );
149  mInvalidLabel->setStyleSheet( QStringLiteral( "QLabel { color: red; } " ) );
150  mInvalidLabel->setFont( font );
151  mTopLayout->addWidget( mInvalidLabel );
152 
153  // default mode is combobox, no geometric relation and no embed form
154  mLineEdit->hide();
155  mMapIdentificationButton->hide();
156  mHighlightFeatureButton->hide();
157  mAttributeEditorFrame->hide();
158  mInvalidLabel->hide();
159  mAddEntryButton->hide();
160 
161  // connect buttons
162  connect( mOpenFormButton, &QAbstractButton::clicked, this, &QgsRelationReferenceWidget::openForm );
163  connect( mHighlightFeatureButton, &QToolButton::triggered, this, &QgsRelationReferenceWidget::highlightActionTriggered );
164  connect( mMapIdentificationButton, &QAbstractButton::clicked, this, &QgsRelationReferenceWidget::mapIdentification );
165  connect( mRemoveFKButton, &QAbstractButton::clicked, this, &QgsRelationReferenceWidget::deleteForeignKeys );
166  connect( mAddEntryButton, &QAbstractButton::clicked, this, &QgsRelationReferenceWidget::addEntry );
167  connect( mComboBox, &QComboBox::editTextChanged, this, &QgsRelationReferenceWidget::updateAddEntryButton );
168 }
169 
171 {
172  deleteHighlight();
173  unsetMapTool();
174 }
175 
176 void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool allowNullValue )
177 {
178  mAllowNull = allowNullValue;
179  mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector );
180 
181  if ( relation.isValid() )
182  {
183  mReferencedLayerId = relation.referencedLayerId();
184  mReferencedLayerName = relation.referencedLayer()->name();
186  mReferencedLayerProviderKey = relation.referencedLayer()->providerType();
187  mInvalidLabel->hide();
188 
189  mRelation = relation;
190  mReferencingLayer = relation.referencingLayer();
191  mReferencedLayer = relation.referencedLayer();
192  const QList<QgsRelation::FieldPair> fieldPairs = relation.fieldPairs();
193  for ( const QgsRelation::FieldPair &fieldPair : fieldPairs )
194  {
195  mReferencedFields << fieldPair.referencedField();
196  }
197  if ( mComboBox )
198  {
199  mComboBox->setSourceLayer( mReferencedLayer );
200  mComboBox->setIdentifierFields( mReferencedFields );
201  }
202  mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() );
203 
204  if ( mEmbedForm )
205  {
207  mAttributeEditorFrame->setTitle( mReferencedLayer->name() );
208  mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this );
209  mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
210  }
211 
212  connect( mReferencedLayer, &QgsVectorLayer::editingStarted, this, &QgsRelationReferenceWidget::updateAddEntryButton );
213  connect( mReferencedLayer, &QgsVectorLayer::editingStopped, this, &QgsRelationReferenceWidget::updateAddEntryButton );
214  updateAddEntryButton();
215  }
216  else
217  {
218  mInvalidLabel->show();
219  }
220 
221  if ( mShown && isVisible() )
222  {
223  init();
224  }
225 }
226 
228 {
229  if ( !editable )
230  {
231  unsetMapTool();
232  }
233 
234  mFilterContainer->setEnabled( editable );
235  mComboBox->setEnabled( editable );
236  mComboBox->setEditable( true );
237  mMapIdentificationButton->setEnabled( editable );
238  mRemoveFKButton->setEnabled( editable );
239  mIsEditable = editable;
240 }
241 
242 void QgsRelationReferenceWidget::setForeignKey( const QVariant &value )
243 {
244  setForeignKeys( QVariantList() << value );
245 }
246 
247 void QgsRelationReferenceWidget::setForeignKeys( const QVariantList &values )
248 {
249  if ( values.isEmpty() )
250  {
251  return;
252  }
253  if ( qVariantListIsNull( values ) )
254  {
256  return;
257  }
258 
259  if ( !mReferencedLayer )
260  return;
261 
262  if ( mReadOnlySelector )
263  {
264  // Attributes from the referencing layer
265  QgsAttributes attrs = QgsAttributes( mReferencingLayer->fields().count() );
266  // Set the value on the foreign key fields of the referencing record
267 
268  const QList<QgsRelation::FieldPair> fieldPairs = mRelation.fieldPairs();
269  int fieldCount = std::min( fieldPairs.count(), values.count() );
270  for ( int i = 0; i < fieldCount; i++ )
271  {
272  int idx = mReferencingLayer->fields().lookupField( fieldPairs.at( i ).referencingField() );
273  attrs[idx] = values.at( i );
274  }
275 
276  QgsFeatureRequest request = mRelation.getReferencedFeatureRequest( attrs );
277 
278  mReferencedLayer->getFeatures( request ).nextFeature( mFeature );
279 
280  if ( !mFeature.isValid() )
281  {
282  return;
283  }
284 
285  mForeignKeys.clear();
286  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
287  mForeignKeys << mFeature.attribute( fieldName );
288 
289  QgsExpression expr( mReferencedLayer->displayExpression() );
291  context.setFeature( mFeature );
292  QString title = expr.evaluate( &context ).toString();
293  if ( expr.hasEvalError() )
294  {
295  QStringList titleFields;
296  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
297  titleFields << mFeature.attribute( fieldName ).toString();
298  title = titleFields.join( QStringLiteral( " " ) );
299  }
300  mLineEdit->setText( title );
301  }
302  else
303  {
304  mComboBox->setIdentifierValues( values );
305 
306  if ( mChainFilters )
307  {
308  QVariant nullValue = QgsApplication::nullRepresentation();
309 
310  QgsFeatureRequest request = mComboBox->currentFeatureRequest();
311 
312  mReferencedLayer->getFeatures( request ).nextFeature( mFeature );
313 
314  const int count = std::min( mFilterComboBoxes.size(), mFilterFields.size() );
315  for ( int i = 0; i < count; i++ )
316  {
317  QVariant v = mFeature.attribute( mFilterFields[i] );
318  QString f = v.isNull() ? nullValue.toString() : v.toString();
319  mFilterComboBoxes.at( i )->setCurrentIndex( mFilterComboBoxes.at( i )->findText( f ) );
320  }
321  }
322  }
323 
324  mRemoveFKButton->setEnabled( mIsEditable );
325  highlightFeature( mFeature ); // TODO : make this async
326  updateAttributeEditorFrame( mFeature );
327 
328  emitForeignKeysChanged( foreignKeys() );
329 }
330 
332 {
333  // deactivate filter comboboxes
334  if ( mChainFilters && !mFilterComboBoxes.isEmpty() )
335  {
336  QComboBox *cb = mFilterComboBoxes.first();
337  cb->setCurrentIndex( 0 );
338  disableChainedComboBoxes( cb );
339  }
340 
341  if ( mReadOnlySelector )
342  {
343  const QString nullValue = QgsApplication::nullRepresentation();
344 
345  QString nullText;
346  if ( mAllowNull )
347  {
348  nullText = tr( "%1 (no selection)" ).arg( nullValue );
349  }
350  mLineEdit->setText( nullText );
351  QVariantList nullAttributes;
352  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
353  {
354  Q_UNUSED( fieldName );
355  nullAttributes << QVariant( QVariant::Int );
356  }
357  mForeignKeys = nullAttributes;
358  mFeature.setValid( false );
359  }
360  else
361  {
362  mComboBox->setIdentifierValuesToNull();
363  }
364  mRemoveFKButton->setEnabled( false );
365  updateAttributeEditorFrame( QgsFeature() );
366 
367  emitForeignKeysChanged( foreignKeys() );
368 }
369 
371 {
372  QgsFeature f;
373  if ( mReferencedLayer )
374  {
375  QgsFeatureRequest request;
376  if ( mReadOnlySelector )
377  {
378  request = QgsFeatureRequest().setFilterFid( mFeature.id() );
379  }
380  else
381  {
382  request = mComboBox->currentFeatureRequest();
383  }
384  mReferencedLayer->getFeatures( request ).nextFeature( f );
385  }
386  return f;
387 }
388 
390 {
391  if ( mReadOnlySelector )
392  {
393  whileBlocking( mLineEdit )->setText( QString() );
394  }
395  else
396  {
397  whileBlocking( mComboBox )->setIdentifierValuesToNull();
398  }
399  mRemoveFKButton->setEnabled( false );
400  updateAttributeEditorFrame( QgsFeature() );
401 }
402 
404 {
405  QVariantList fkeys;
406  if ( fkeys.isEmpty() )
407  return QVariant( QVariant::Int );
408  else
409  return fkeys.at( 0 );
410 }
411 
413 {
414  if ( mReadOnlySelector )
415  {
416  return mForeignKeys;
417  }
418  else
419  {
420  return mComboBox->identifierValues();
421  }
422 }
423 
425 {
426  mEditorContext = context;
427  mCanvas = canvas;
428  mMessageBar = messageBar;
429 
430  mMapToolIdentify.reset( new QgsMapToolIdentifyFeature( mCanvas ) );
431  mMapToolIdentify->setButton( mMapIdentificationButton );
432 
433  if ( mEditorContext.cadDockWidget() )
434  {
435  mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( mCanvas, mEditorContext.cadDockWidget() ) );
436  mMapToolDigitize->setButton( mAddEntryButton );
437  updateAddEntryButton();
438  }
439 }
440 
442 {
443  if ( display )
444  {
445  setSizePolicy( sizePolicy().horizontalPolicy(), QSizePolicy::MinimumExpanding );
446  mTopLayout->setAlignment( Qt::AlignTop );
447  }
448 
449  mAttributeEditorFrame->setVisible( display );
450  mEmbedForm = display;
451 }
452 
454 {
455  mChooserContainer->setHidden( readOnly );
456  mLineEdit->setVisible( readOnly );
457  mRemoveFKButton->setVisible( mAllowNull && readOnly );
458  mReadOnlySelector = readOnly;
459 }
460 
461 void QgsRelationReferenceWidget::setAllowMapIdentification( bool allowMapIdentification )
462 {
463  mHighlightFeatureButton->setVisible( allowMapIdentification );
464  mMapIdentificationButton->setVisible( allowMapIdentification );
465  mAllowMapIdentification = allowMapIdentification;
466 }
467 
469 {
470  mOrderByValue = orderByValue;
471 }
472 
473 void QgsRelationReferenceWidget::setFilterFields( const QStringList &filterFields )
474 {
475  mFilterFields = filterFields;
476 }
477 
479 {
480  mOpenFormButton->setVisible( openFormButtonVisible );
481  mOpenFormButtonVisible = openFormButtonVisible;
482 }
483 
485 {
486  mChainFilters = chainFilters;
487 }
488 
490 {
491  Q_UNUSED( e )
492 
493  mShown = true;
494  if ( !mInitialized )
495  init();
496 }
497 
499 {
500  if ( !mReadOnlySelector && mReferencedLayer )
501  {
502  QApplication::setOverrideCursor( Qt::WaitCursor );
503 
504  QSet<QString> requestedAttrs;
505 
506  if ( !mFilterFields.isEmpty() )
507  {
508  for ( const QString &fieldName : qgis::as_const( mFilterFields ) )
509  {
510  int idx = mReferencedLayer->fields().lookupField( fieldName );
511 
512  if ( idx == -1 )
513  continue;
514 
515  QComboBox *cb = new QComboBox();
516  cb->setProperty( "Field", fieldName );
517  cb->setProperty( "FieldAlias", mReferencedLayer->attributeDisplayName( idx ) );
518  mFilterComboBoxes << cb;
519  QVariantList uniqueValues = qgis::setToList( mReferencedLayer->uniqueValues( idx ) );
520  cb->addItem( mReferencedLayer->attributeDisplayName( idx ) );
521  QVariant nullValue = QgsApplication::nullRepresentation();
522  cb->addItem( nullValue.toString(), QVariant( mReferencedLayer->fields().at( idx ).type() ) );
523 
524  std::sort( uniqueValues.begin(), uniqueValues.end(), qgsVariantLessThan );
525  const auto constUniqueValues = uniqueValues;
526  for ( const QVariant &v : constUniqueValues )
527  {
528  cb->addItem( v.toString(), v );
529  }
530 
531  connect( cb, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRelationReferenceWidget::filterChanged );
532 
533  // Request this attribute for caching
534  requestedAttrs << fieldName;
535 
536  mFilterLayout->addWidget( cb );
537  }
538 
539  if ( mChainFilters )
540  {
541  QVariant nullValue = QgsApplication::nullRepresentation();
542 
543  QgsFeature ft;
544  QgsFeatureIterator fit = mReferencedLayer->getFeatures();
545  while ( fit.nextFeature( ft ) )
546  {
547  const int count = std::min( mFilterComboBoxes.count(), mFilterFields.count() );
548  for ( int i = 0; i < count - 1; i++ )
549  {
550  QVariant cv = ft.attribute( mFilterFields.at( i ) );
551  QVariant nv = ft.attribute( mFilterFields.at( i + 1 ) );
552  QString cf = cv.isNull() ? nullValue.toString() : cv.toString();
553  QString nf = nv.isNull() ? nullValue.toString() : nv.toString();
554  mFilterCache[mFilterFields[i]][cf] << nf;
555  }
556  }
557 
558  if ( !mFilterComboBoxes.isEmpty() )
559  {
560  QComboBox *cb = mFilterComboBoxes.first();
561  cb->setCurrentIndex( 0 );
562  disableChainedComboBoxes( cb );
563  }
564  }
565  }
566  else
567  {
568  mFilterContainer->hide();
569  }
570 
571  mComboBox->setSourceLayer( mReferencedLayer );
572  mComboBox->setDisplayExpression( mReferencedLayer->displayExpression() );
573  mComboBox->setAllowNull( mAllowNull );
574  mComboBox->setIdentifierFields( mReferencedFields );
575 
576  QVariant nullValue = QgsApplication::nullRepresentation();
577 
578  if ( mChainFilters && mFeature.isValid() )
579  {
580  for ( int i = 0; i < mFilterFields.size(); i++ )
581  {
582  QVariant v = mFeature.attribute( mFilterFields[i] );
583  QString f = v.isNull() ? nullValue.toString() : v.toString();
584  mFilterComboBoxes.at( i )->setCurrentIndex( mFilterComboBoxes.at( i )->findText( f ) );
585  }
586  }
587 
588  // Only connect after iterating, to have only one iterator on the referenced table at once
589  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRelationReferenceWidget::comboReferenceChanged );
590 
591  QApplication::restoreOverrideCursor();
592 
593  mInitialized = true;
594  }
595 }
596 
597 void QgsRelationReferenceWidget::highlightActionTriggered( QAction *action )
598 {
599  if ( action == mHighlightFeatureAction )
600  {
601  highlightFeature();
602  }
603  else if ( action == mScaleHighlightFeatureAction )
604  {
605  highlightFeature( QgsFeature(), Scale );
606  }
607  else if ( action == mPanHighlightFeatureAction )
608  {
609  highlightFeature( QgsFeature(), Pan );
610  }
611 }
612 
614 {
615  QgsFeature feat = referencedFeature();
616 
617  if ( !feat.isValid() )
618  return;
619 
621  QgsAttributeDialog attributeDialog( mReferencedLayer, new QgsFeature( feat ), true, this, true, context );
622  attributeDialog.exec();
623 }
624 
625 void QgsRelationReferenceWidget::highlightFeature( QgsFeature f, CanvasExtent canvasExtent )
626 {
627  if ( !mCanvas )
628  return;
629 
630  if ( !f.isValid() )
631  {
632  f = referencedFeature();
633  if ( !f.isValid() )
634  return;
635  }
636 
637  if ( !f.hasGeometry() )
638  {
639  return;
640  }
641 
642  QgsGeometry geom = f.geometry();
643 
644  // scale or pan
645  if ( canvasExtent == Scale )
646  {
647  QgsRectangle featBBox = geom.boundingBox();
648  featBBox = mCanvas->mapSettings().layerToMapCoordinates( mReferencedLayer, featBBox );
649  QgsRectangle extent = mCanvas->extent();
650  if ( !extent.contains( featBBox ) )
651  {
652  extent.combineExtentWith( featBBox );
653  extent.scale( 1.1 );
654  mCanvas->setExtent( extent, true );
655  mCanvas->refresh();
656  }
657  }
658  else if ( canvasExtent == Pan )
659  {
660  QgsGeometry centroid = geom.centroid();
661  QgsPointXY center = centroid.asPoint();
662  center = mCanvas->mapSettings().layerToMapCoordinates( mReferencedLayer, center );
663  mCanvas->zoomByFactor( 1.0, &center ); // refresh is done in this method
664  }
665 
666  // highlight
667  deleteHighlight();
668  mHighlight = new QgsHighlight( mCanvas, f, mReferencedLayer );
669  QgsIdentifyMenu::styleHighlight( mHighlight );
670  mHighlight->show();
671 
672  QTimer *timer = new QTimer( this );
673  timer->setSingleShot( true );
674  connect( timer, &QTimer::timeout, this, &QgsRelationReferenceWidget::deleteHighlight );
675  timer->start( 3000 );
676 }
677 
678 void QgsRelationReferenceWidget::deleteHighlight()
679 {
680  if ( mHighlight )
681  {
682  mHighlight->hide();
683  delete mHighlight;
684  }
685  mHighlight = nullptr;
686 }
687 
689 {
690  if ( !mAllowMapIdentification || !mReferencedLayer )
691  return;
692 
693  const QgsVectorLayerTools *tools = mEditorContext.vectorLayerTools();
694  if ( !tools )
695  return;
696  if ( !mCanvas )
697  return;
698 
699  mMapToolIdentify->setLayer( mReferencedLayer );
700  setMapTool( mMapToolIdentify );
701 
702  connect( mMapToolIdentify, qgis::overload<const QgsFeature &>::of( &QgsMapToolIdentifyFeature::featureIdentified ), this, &QgsRelationReferenceWidget::featureIdentified );
703 
704  if ( mMessageBar )
705  {
706  QString title = tr( "Relation %1 for %2." ).arg( mRelation.name(), mReferencingLayer->name() );
707  QString msg = tr( "Identify a feature of %1 to be associated. Press &lt;ESC&gt; to cancel." ).arg( mReferencedLayer->name() );
708  mMessageBarItem = QgsMessageBar::createMessage( title, msg, this );
709  mMessageBar->pushItem( mMessageBarItem );
710  }
711 }
712 
713 void QgsRelationReferenceWidget::comboReferenceChanged( int index )
714 {
715  Q_UNUSED( index )
716  mReferencedLayer->getFeatures( mComboBox->currentFeatureRequest() ).nextFeature( mFeature );
717  highlightFeature( mFeature );
718  updateAttributeEditorFrame( mFeature );
719 
720  emitForeignKeysChanged( mComboBox->identifierValues() );
721 }
722 
723 void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature &feature )
724 {
725  mOpenFormButton->setEnabled( feature.isValid() );
726  // Check if we're running with an embedded frame we need to update
727  if ( mAttributeEditorFrame && mReferencedAttributeForm )
728  {
729  mReferencedAttributeForm->setFeature( feature );
730  }
731 }
732 
734 {
735  return mAllowAddFeatures;
736 }
737 
739 {
740  mAllowAddFeatures = allowAddFeatures;
741  updateAddEntryButton();
742 }
743 
745 {
746  return mRelation;
747 }
748 
749 void QgsRelationReferenceWidget::featureIdentified( const QgsFeature &feature )
750 {
751  if ( mReadOnlySelector )
752  {
753  QgsExpression expr( mReferencedLayer->displayExpression() );
755  context.setFeature( feature );
756  QString title = expr.evaluate( &context ).toString();
757  if ( expr.hasEvalError() )
758  {
759  QStringList titleFields;
760  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
761  titleFields << mFeature.attribute( fieldName ).toString();
762  title = titleFields.join( QStringLiteral( " " ) );
763  }
764  mLineEdit->setText( title );
765  mForeignKeys.clear();
766  mFeature = feature;
767  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
768  mForeignKeys << mFeature.attribute( fieldName );
769  }
770  else
771  {
772  mComboBox->setCurrentFeature( feature );
773  mFeature = feature;
774  }
775 
776  mRemoveFKButton->setEnabled( mIsEditable );
777  highlightFeature( feature );
778  updateAttributeEditorFrame( feature );
779  emitForeignKeysChanged( foreignKeys(), true );
780 
781  unsetMapTool();
782 }
783 
784 void QgsRelationReferenceWidget::setMapTool( QgsMapTool *mapTool )
785 {
786  mCurrentMapTool = mapTool;
787  mCanvas->setMapTool( mapTool );
788 
789  mWindowWidget = window();
790 
791  mCanvas->window()->raise();
792  mCanvas->activateWindow();
793  mCanvas->setFocus();
794  connect( mapTool, &QgsMapTool::deactivated, this, &QgsRelationReferenceWidget::mapToolDeactivated );
795 }
796 
797 void QgsRelationReferenceWidget::unsetMapTool()
798 {
799  // deactivate map tools if activated
800  if ( mCurrentMapTool )
801  {
802  /* this will call mapToolDeactivated */
803  mCanvas->unsetMapTool( mCurrentMapTool );
804 
805  if ( mCurrentMapTool == mMapToolDigitize )
806  {
807  disconnect( mCanvas, &QgsMapCanvas::keyPressed, this, &QgsRelationReferenceWidget::onKeyPressed );
808  disconnect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationReferenceWidget::entryAdded );
809  }
810  else
811  {
812  disconnect( mMapToolIdentify, qgis::overload<const QgsFeature &>::of( &QgsMapToolIdentifyFeature::featureIdentified ), this, &QgsRelationReferenceWidget::featureIdentified );
813  }
814  }
815 }
816 
817 void QgsRelationReferenceWidget::onKeyPressed( QKeyEvent *e )
818 {
819  if ( e->key() == Qt::Key_Escape )
820  {
821  unsetMapTool();
822  }
823 }
824 
825 void QgsRelationReferenceWidget::mapToolDeactivated()
826 {
827  if ( mWindowWidget )
828  {
829  mWindowWidget->raise();
830  mWindowWidget->activateWindow();
831  }
832 
833  if ( mMessageBar && mMessageBarItem )
834  {
835  mMessageBar->popWidget( mMessageBarItem );
836  }
837  mMessageBarItem = nullptr;
838 }
839 
840 void QgsRelationReferenceWidget::filterChanged()
841 {
842  QVariant nullValue = QgsApplication::nullRepresentation();
843 
844  QMap<QString, QString> filters;
845  QgsAttributeList attrs;
846 
847  QComboBox *scb = qobject_cast<QComboBox *>( sender() );
848 
849  Q_ASSERT( scb );
850 
851  QgsFeature f;
852  QgsFeatureIds featureIds;
853  QString filterExpression;
854 
855  // comboboxes have to be disabled before building filters
856  if ( mChainFilters )
857  disableChainedComboBoxes( scb );
858 
859  // build filters
860  const auto constMFilterComboBoxes = mFilterComboBoxes;
861  for ( QComboBox *cb : constMFilterComboBoxes )
862  {
863  if ( cb->currentIndex() != 0 )
864  {
865  const QString fieldName = cb->property( "Field" ).toString();
866 
867  if ( cb->currentText() == nullValue.toString() )
868  {
869  filters[fieldName] = QStringLiteral( "\"%1\" IS NULL" ).arg( fieldName );
870  }
871  else
872  {
873  filters[fieldName] = QgsExpression::createFieldEqualityExpression( fieldName, cb->currentText() );
874  }
875  attrs << mReferencedLayer->fields().lookupField( fieldName );
876  }
877  }
878 
879  if ( mChainFilters )
880  {
881  QComboBox *ccb = nullptr;
882  const auto constMFilterComboBoxes = mFilterComboBoxes;
883  for ( QComboBox *cb : constMFilterComboBoxes )
884  {
885  if ( !ccb )
886  {
887  if ( cb == scb )
888  ccb = cb;
889 
890  continue;
891  }
892 
893  if ( ccb->currentIndex() != 0 )
894  {
895  const QString fieldName = cb->property( "Field" ).toString();
896 
897  cb->blockSignals( true );
898  cb->clear();
899  cb->addItem( cb->property( "FieldAlias" ).toString() );
900 
901  // ccb = scb
902  // cb = scb + 1
903  QStringList texts;
904  const auto txts { mFilterCache[ccb->property( "Field" ).toString()][ccb->currentText()] };
905  for ( const QString &txt : txts )
906  {
907  QMap<QString, QString> filtersAttrs = filters;
908  filtersAttrs[fieldName] = QgsExpression::createFieldEqualityExpression( fieldName, txt );
909  QString expression = filtersAttrs.values().join( QStringLiteral( " AND " ) );
910 
911  QgsAttributeList subset = attrs;
912  subset << mReferencedLayer->fields().lookupField( fieldName );
913 
914  QgsFeatureIterator it( mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterExpression( expression ).setSubsetOfAttributes( subset ) ) );
915 
916  bool found = false;
917  while ( it.nextFeature( f ) )
918  {
919  if ( !featureIds.contains( f.id() ) )
920  featureIds << f.id();
921 
922  found = true;
923  }
924 
925  // item is only provided if at least 1 feature exists
926  if ( found )
927  texts << txt;
928  }
929 
930  texts.sort();
931  cb->addItems( texts );
932 
933  cb->setEnabled( true );
934  cb->blockSignals( false );
935 
936  ccb = cb;
937  }
938  }
939  }
940  filterExpression = filters.values().join( QStringLiteral( " AND " ) );
941  mComboBox->setFilterExpression( filterExpression );
942 }
943 
944 void QgsRelationReferenceWidget::addEntry()
945 {
946  if ( !mReferencedLayer )
947  return;
948 
949  const QgsVectorLayerTools *tools = mEditorContext.vectorLayerTools();
950  if ( !tools )
951  return;
952  if ( !mCanvas )
953  return;
954 
955  // no geometry, skip the digitizing
956  if ( mReferencedLayer->geometryType() == QgsWkbTypes::UnknownGeometry || mReferencedLayer->geometryType() == QgsWkbTypes::NullGeometry )
957  {
958  QgsFeature f( mReferencedLayer->fields() );
959  entryAdded( f );
960  return;
961  }
962 
963  mMapToolDigitize->setLayer( mReferencedLayer );
964  setMapTool( mMapToolDigitize );
965 
966  connect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationReferenceWidget::entryAdded );
967  connect( mCanvas, &QgsMapCanvas::keyPressed, this, &QgsRelationReferenceWidget::onKeyPressed );
968 
969  if ( mMessageBar )
970  {
971  QString title = tr( "Relation %1 for %2." ).arg( mRelation.name(), mReferencingLayer->name() );
972 
973  QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mReferencingLayer, mFormFeature );
974  QString msg = tr( "Link feature to %1 \"%2\" : Digitize the geometry for the new feature on layer %3. Press &lt;ESC&gt; to cancel." )
975  .arg( mReferencingLayer->name(), displayString, mReferencedLayer->name() );
976  mMessageBarItem = QgsMessageBar::createMessage( title, msg, this );
977  mMessageBar->pushItem( mMessageBarItem );
978  }
979 
980 }
981 
982 void QgsRelationReferenceWidget::entryAdded( const QgsFeature &feat )
983 {
984  QgsFeature f( feat );
985  QgsAttributeMap attributes;
986 
987  // if custom text is in the combobox and the displayExpression is simply a field, use the current text for the new feature
988  if ( mComboBox->itemText( mComboBox->currentIndex() ) != mComboBox->currentText() )
989  {
990  int fieldIdx = mReferencedLayer->fields().lookupField( mReferencedLayer->displayExpression() );
991 
992  if ( fieldIdx != -1 )
993  {
994  attributes.insert( fieldIdx, mComboBox->currentText() );
995  }
996  }
997 
998  if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, f.geometry(), &f ) )
999  {
1000  QVariantList attrs;
1001  for ( const QString &fieldName : qgis::as_const( mReferencedFields ) )
1002  attrs << f.attribute( fieldName );
1003 
1004  mComboBox->setIdentifierValues( attrs );
1005 
1006  mAddEntryButton->setEnabled( false );
1007  }
1008 
1009  unsetMapTool();
1010 }
1011 
1012 void QgsRelationReferenceWidget::updateAddEntryButton()
1013 {
1014  mAddEntryButton->setVisible( mAllowAddFeatures && mMapToolDigitize );
1015  mAddEntryButton->setEnabled( mReferencedLayer && mReferencedLayer->isEditable() );
1016 }
1017 
1018 void QgsRelationReferenceWidget::disableChainedComboBoxes( const QComboBox *scb )
1019 {
1020  QComboBox *ccb = nullptr;
1021  const auto constMFilterComboBoxes = mFilterComboBoxes;
1022  for ( QComboBox *cb : constMFilterComboBoxes )
1023  {
1024  if ( !ccb )
1025  {
1026  if ( cb == scb )
1027  {
1028  ccb = cb;
1029  }
1030 
1031  continue;
1032  }
1033 
1034  cb->setCurrentIndex( 0 );
1035  if ( ccb->currentIndex() == 0 )
1036  {
1037  cb->setEnabled( false );
1038  }
1039 
1040  ccb = cb;
1041  }
1042 }
1043 
1044 void QgsRelationReferenceWidget::emitForeignKeysChanged( const QVariantList &foreignKeys, bool force )
1045 {
1046  if ( foreignKeys == mForeignKeys && force == false )
1047  return;
1048 
1049  mForeignKeys = foreignKeys;
1051  emit foreignKeyChanged( foreignKeys.at( 0 ) );
1054 }
1055 
1057 {
1058  return mReferencedLayerName;
1059 }
1060 
1061 void QgsRelationReferenceWidget::setReferencedLayerName( const QString &relationLayerName )
1062 {
1063  mReferencedLayerName = relationLayerName;
1064 }
1065 
1067 {
1068  return mReferencedLayerId;
1069 }
1070 
1071 void QgsRelationReferenceWidget::setReferencedLayerId( const QString &relationLayerId )
1072 {
1073  mReferencedLayerId = relationLayerId;
1074 }
1075 
1077 {
1078  return mReferencedLayerProviderKey;
1079 }
1080 
1081 void QgsRelationReferenceWidget::setReferencedLayerProviderKey( const QString &relationProviderKey )
1082 {
1083  mReferencedLayerProviderKey = relationProviderKey;
1084 }
1085 
1087 {
1088  return mReferencedLayerDataSource;
1089 }
1090 
1091 void QgsRelationReferenceWidget::setReferencedLayerDataSource( const QString &relationDataSource )
1092 {
1093  const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
1094  mReferencedLayerDataSource = resolver.writePath( relationDataSource );
1095 }
1096 
1098 {
1099  mFormFeature = formFeature;
1100 }
QgsAttributeDialog
Definition: qgsattributedialog.h:37
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:993
qgsfeaturefiltermodel.h
qgsmaptoolidentifyfeature.h
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
qgsfields.h
qgsexpressioncontextutils.h
QgsRelationReferenceWidget::showEvent
void showEvent(QShowEvent *e) override
Definition: qgsrelationreferencewidget.cpp:489
QgsRelationReferenceWidget::Pan
@ Pan
Definition: qgsrelationreferencewidget.h:77
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.
qgsattributeform.h
QgsMapCanvas::extent
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Definition: qgsmapcanvas.cpp:1049
QObjectUniquePtr::reset
void reset(T *p=nullptr)
Will reset the managed pointer to p.
Definition: qobjectuniqueptr.h:176
qgscollapsiblegroupbox.h
QgsRelationReferenceWidget::referencedFeature
QgsFeature referencedFeature() const
Returns the related feature (from the referenced layer) if no feature is related, it returns an inval...
Definition: qgsrelationreferencewidget.cpp:370
QgsAttributeEditorContext::cadDockWidget
QgsAdvancedDigitizingDockWidget * cadDockWidget() const
Returns the associated CAD dock widget (e.g.
Definition: qgsattributeeditorcontext.h:155
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsMapCanvas::refresh
void refresh()
Repaints the canvas map.
Definition: qgsmapcanvas.cpp:524
QgsFeatureListComboBox::setCurrentFeature
void setCurrentFeature(const QgsFeature &feature)
Sets the current index by using the given feature.
Definition: qgsfeaturelistcombobox.cpp:77
QgsRectangle::combineExtentWith
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:359
QgsRelationReferenceWidget::allowMapIdentification
bool allowMapIdentification()
determines if the widget offers the possibility to select the related feature on the map (using a ded...
Definition: qgsrelationreferencewidget.h:131
QgsRelationReferenceWidget::init
void init()
Definition: qgsrelationreferencewidget.cpp:498
qgsmapcanvas.h
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:145
QgsRelationReferenceWidget::setFilterFields
void setFilterFields(const QStringList &filterFields)
Sets the fields for which filter comboboxes will be created.
Definition: qgsrelationreferencewidget.cpp:473
QgsMapCanvas::zoomByFactor
void zoomByFactor(double scaleFactor, const QgsPointXY *center=nullptr, bool ignoreScaleLock=false)
Zoom with the factor supplied.
Definition: qgsmapcanvas.cpp:2495
qgsfeaturelistcombobox.h
QgsRelationReferenceWidget::openForm
void openForm()
open the form of the related feature in a new dialog
Definition: qgsrelationreferencewidget.cpp:613
QgsMapToolIdentifyFeature::setLayer
void setLayer(QgsVectorLayer *vl)
change the layer used by the map tool to identify
Definition: qgsmaptoolidentifyfeature.h:55
qgsexpression.h
QgsFeatureListComboBox::setFilterExpression
void setFilterExpression(const QString &filterExpression)
An additional expression to further restrict the available features.
Definition: qgsfeaturelistcombobox.cpp:299
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:390
qgsVariantLessThan
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:121
QgsRelationReferenceWidget::foreignKeyChanged
Q_DECL_DEPRECATED void foreignKeyChanged(const QVariant &)
Emitted when the foreign key changed.
QgsRelationReferenceWidget::showIndeterminateState
void showIndeterminateState()
Sets the widget to display in an indeterminate "mixed value" state.
Definition: qgsrelationreferencewidget.cpp:389
QgsRelation::name
QString name
Definition: qgsrelation.h:48
QgsProject::pathResolver
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
Definition: qgsproject.cpp:2590
QgsRelationReferenceWidget::allowAddFeatures
bool allowAddFeatures() const
Determines if a button for adding new features should be shown.
Definition: qgsrelationreferencewidget.cpp:733
QgsAttributeForm::setFeature
void setFeature(const QgsFeature &feature)
Update all editors to correspond to a different feature.
Definition: qgsattributeform.cpp:271
qgsfeatureiterator.h
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsMapCanvas
Definition: qgsmapcanvas.h:83
QgsGeometry::centroid
QgsGeometry centroid() const
Returns the center of mass of a geometry.
Definition: qgsgeometry.cpp:2153
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsVectorLayerTools
Definition: qgsvectorlayertools.h:39
QgsFeatureListComboBox::identifierValues
QVariantList identifierValues
Definition: qgsfeaturelistcombobox.h:47
QgsFeature::setValid
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:188
QgsRelationReferenceWidget::setReferencedLayerProviderKey
void setReferencedLayerProviderKey(const QString &referencedLayerProviderKey)
Set the data provider key of the referenced layer to referencedLayerProviderKey.
Definition: qgsrelationreferencewidget.cpp:1081
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:306
QgsRelationReferenceWidget::setRelationEditable
void setRelationEditable(bool editable)
Definition: qgsrelationreferencewidget.cpp:227
QgsAttributeEditorContext::Embed
@ Embed
A form was embedded as a widget on another form.
Definition: qgsattributeeditorcontext.h:71
qVariantListIsNull
bool qVariantListIsNull(const QVariantList &list)
Definition: qgsrelationreferencewidget.cpp:50
qgsfeaturelistmodel.h
QgsRelationReferenceWidget::Scale
@ Scale
Definition: qgsrelationreferencewidget.h:78
QgsMapToolIdentifyFeature
The QgsMapToolIdentifyFeature class is a map tool to identify a feature on a chosen layer....
Definition: qgsmaptoolidentifyfeature.h:28
QgsRelationReferenceWidget::~QgsRelationReferenceWidget
~QgsRelationReferenceWidget() override
Definition: qgsrelationreferencewidget.cpp:170
QgsAttributeList
QList< int > QgsAttributeList
Definition: qgsfield.h:26
qgsidentifymenu.h
QgsCollapsibleGroupBox
Definition: qgscollapsiblegroupbox.h:178
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
QgsRelationReferenceWidget::chainFilters
bool chainFilters() const
Determines if the filters are chained.
Definition: qgsrelationreferencewidget.h:150
QgsRelationReferenceWidget::setReferencedLayerName
void setReferencedLayerName(const QString &referencedLayerName)
Set the name of the referenced layer to referencedLayerName.
Definition: qgsrelationreferencewidget.cpp:1061
QgsRelationReferenceWidget::setForeignKeys
void setForeignKeys(const QVariantList &values)
Sets the related feature using the foreign keys.
Definition: qgsrelationreferencewidget.cpp:247
QgsRectangle
Definition: qgsrectangle.h:41
QgsVectorLayer::isEditable
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
Definition: qgsvectorlayer.cpp:3586
QgsHighlight
Definition: qgshighlight.h:57
QgsFeatureRequest::setFilterFid
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets feature ID that should be fetched.
Definition: qgsfeaturerequest.cpp:103
QgsMapLayer::providerType
QString providerType() const
Returns the provider type (provider key) for this layer.
Definition: qgsmaplayer.cpp:1614
QgsRelation::referencingLayer
QgsVectorLayer referencingLayer
Definition: qgsrelation.h:46
qgsapplication.h
QgsMapTool
Definition: qgsmaptool.h:63
qgsmaptooldigitizefeature.h
QgsFeatureListComboBox::setDisplayExpression
void setDisplayExpression(const QString &displayExpression)
The display expression will be used to display features as well as the value to match the typed text ...
Definition: qgsfeaturelistcombobox.cpp:93
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3280
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:752
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsRectangle::scale
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
Definition: qgsrectangle.h:235
QgsRelationReferenceWidget::setAllowMapIdentification
void setAllowMapIdentification(bool allowMapIdentification)
Definition: qgsrelationreferencewidget.cpp:461
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsExpression::hasEvalError
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
Definition: qgsexpression.cpp:374
QgsVectorLayer::editingStarted
void editingStarted()
Emitted when editing on this layer has started.
QgsRelationReferenceWidget::setAllowAddFeatures
void setAllowAddFeatures(bool allowAddFeatures)
Determines if a button for adding new features should be shown.
Definition: qgsrelationreferencewidget.cpp:738
QgsRelationReferenceWidget::referencedLayerName
QString referencedLayerName() const
Returns the name of the referenced layer.
Definition: qgsrelationreferencewidget.cpp:1056
QgsMapToolDigitizeFeature::digitizingCompleted
void digitizingCompleted(const QgsFeature &feature)
Emitted whenever the digitizing has been successfully completed.
QgsRelationReferenceWidget::mapIdentification
void mapIdentification()
activate the map tool to select a new related feature on the map
Definition: qgsrelationreferencewidget.cpp:688
QgsFeatureListComboBox::setIdentifierValues
void setIdentifierValues(const QVariantList &identifierValues)
The identifier values of the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:257
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:1802
QgsRelationReferenceWidget::setEditorContext
void setEditorContext(const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar)
Sets the editor context.
Definition: qgsrelationreferencewidget.cpp:424
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:342
QgsAttributeEditorContext::StandaloneDialog
@ StandaloneDialog
A form was opened as a new dialog.
Definition: qgsattributeeditorcontext.h:72
QgsRelationReferenceWidget::foreignKeysChanged
void foreignKeysChanged(const QVariantList &)
Emitted when the foreign keys changed.
QgsMapToolDigitizeFeature::setLayer
void setLayer(QgsMapLayer *vl)
Change the layer edited by the map tool.
Definition: qgsmaptooldigitizefeature.cpp:365
QgsRelation::referencedLayer
QgsVectorLayer referencedLayer
Definition: qgsrelation.h:47
QgsRelationReferenceWidget::orderByValue
bool orderByValue()
If the widget will order the combobox entries by value.
Definition: qgsrelationreferencewidget.h:135
qgsattributetablefiltermodel.h
QgsMessageBar::pushItem
void pushItem(QgsMessageBarItem *item)
Display a message item on the bar, after hiding the currently visible one and putting it in a stack.
Definition: qgsmessagebar.cpp:274
QgsRelationReferenceWidget::setEmbedForm
void setEmbedForm(bool display)
Definition: qgsrelationreferencewidget.cpp:441
QgsRelationReferenceWidget::setReferencedLayerDataSource
void setReferencedLayerDataSource(const QString &referencedLayerDataSource)
Set the public data source of the referenced layer to referencedLayerDataSource.
Definition: qgsrelationreferencewidget.cpp:1091
QgsVectorLayer::uniqueValues
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
Definition: qgsvectorlayer.cpp:3949
QgsMessageBar
Definition: qgsmessagebar.h:60
QgsAttributeMap
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
qgsvectorlayerutils.h
qgsattributedialog.h
QgsMapToolDigitizeFeature
This tool digitizes geometry of new point/line/polygon features on already existing vector layers Onc...
Definition: qgsmaptooldigitizefeature.h:31
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
QgsFeatureListComboBox
Definition: qgsfeaturelistcombobox.h:39
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:228
qgsmessagebar.h
qgsattributetablemodel.h
QgsFeatureListComboBox::currentFeatureRequest
QgsFeatureRequest currentFeatureRequest() const
Shorthand for getting a feature request to query the currently selected feature.
Definition: qgsfeaturelistcombobox.cpp:267
QgsRelationReferenceWidget::setForeignKey
Q_DECL_DEPRECATED void setForeignKey(const QVariant &value)
this sets the related feature using from the foreign key
Definition: qgsrelationreferencewidget.cpp:242
QgsMapTool::setButton
void setButton(QAbstractButton *button)
Use this to associate a button to this maptool.
Definition: qgsmaptool.cpp:139
QgsMapCanvas::setExtent
void setExtent(const QgsRectangle &r, bool magnified=false)
Sets the extent of the map canvas to the specified rectangle.
Definition: qgsmapcanvas.cpp:1060
QgsMapCanvas::setMapTool
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
Definition: qgsmapcanvas.cpp:1975
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsRelation::FieldPair
Definition: qgsrelation.h:74
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
QgsFeatureListComboBox::setSourceLayer
void setSourceLayer(QgsVectorLayer *sourceLayer)
The layer from which features should be listed.
Definition: qgsfeaturelistcombobox.cpp:72
qgsvectorlayer.h
QgsPointXY
Definition: qgspointxy.h:43
QgsAttributeEditorContext::Single
@ Single
When showing a single feature (e.g. district information when looking at the form of a house)
Definition: qgsattributeeditorcontext.h:66
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:306
QgsRelationReferenceWidget::referencedLayerProviderKey
QString referencedLayerProviderKey() const
Returns the data provider key of the referenced layer.
Definition: qgsrelationreferencewidget.cpp:1076
QgsGeometry::asPoint
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Definition: qgsgeometry.cpp:1559
QgsMapLayer::publicSource
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
Definition: qgsmaplayer.cpp:184
QgsRelationReferenceWidget::relation
QgsRelation relation() const
Returns the current relation, which might be invalid.
Definition: qgsrelationreferencewidget.cpp:744
QgsRelationReferenceWidget::openFormButtonVisible
bool openFormButtonVisible
Definition: qgsrelationreferencewidget.h:70
QgsVectorLayer::editingStopped
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
qgsgeometry.h
QgsExpression::createFieldEqualityExpression
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
Definition: qgsexpression.cpp:1062
qgshighlight.h
QgsRelationReferenceWidget::foreignKeys
QVariantList foreignKeys() const
returns the related feature foreign key
Definition: qgsrelationreferencewidget.cpp:412
QgsFeatureListComboBox::setIdentifierFields
void setIdentifierFields(const QStringList &identifierFields)
Field name that will be used to uniquely identify the current feature.
Definition: qgsfeaturelistcombobox.cpp:203
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsVectorLayer::attributeDisplayName
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
Definition: qgsvectorlayer.cpp:3138
QgsRelationReferenceWidget::deleteForeignKeys
void deleteForeignKeys()
unset the currently related feature
Definition: qgsrelationreferencewidget.cpp:331
QgsGeometry
Definition: qgsgeometry.h:122
QgsRelationReferenceWidget::setRelation
void setRelation(const QgsRelation &relation, bool allowNullValue)
Definition: qgsrelationreferencewidget.cpp:176
qgseditorwidgetfactory.h
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsRelationReferenceWidget::setChainFilters
void setChainFilters(bool chainFilters)
Set if filters are chained.
Definition: qgsrelationreferencewidget.cpp:484
QgsRelation::isValid
bool isValid
Definition: qgsrelation.h:49
QgsRelationReferenceWidget::setOrderByValue
void setOrderByValue(bool orderByValue)
Sets if the widget will order the combobox entries by value.
Definition: qgsrelationreferencewidget.cpp:468
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:85
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:144
QgsMapCanvas::keyPressed
void keyPressed(QKeyEvent *e)
Emit key press event.
QgsRelationReferenceWidget::referencedLayerId
QString referencedLayerId() const
Returns the id of the referenced layer.
Definition: qgsrelationreferencewidget.cpp:1066
QgsMapCanvas::unsetMapTool
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
Definition: qgsmapcanvas.cpp:2015
QgsRelationReferenceWidget::setReferencedLayerId
void setReferencedLayerId(const QString &referencedLayerId)
Set the id of the referenced layer to referencedLayerId.
Definition: qgsrelationreferencewidget.cpp:1071
QgsRelation
Definition: qgsrelation.h:41
QgsFeatureListComboBox::setAllowNull
void setAllowNull(bool allowNull)
Determines if a NULL value should be available in the list.
Definition: qgsfeaturelistcombobox.cpp:234
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:962
QgsAttributes
Definition: qgsattributes.h:57
QgsRelationReferenceWidget::referencedLayerDataSource
QString referencedLayerDataSource() const
Returns the public data source of the referenced layer.
Definition: qgsrelationreferencewidget.cpp:1086
QgsFeature
Definition: qgsfeature.h:55
QgsAttributeForm
Definition: qgsattributeform.h:44
QgsRelationReferenceWidget::setOpenFormButtonVisible
void setOpenFormButtonVisible(bool openFormButtonVisible)
Definition: qgsrelationreferencewidget.cpp:478
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
qgsrelationreferencewidget.h
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:324
QgsFeatureListComboBox::setIdentifierValuesToNull
void setIdentifierValuesToNull()
Sets the identifier values of the currently selected feature to NULL value(s).
Definition: qgsfeaturelistcombobox.cpp:262
QgsMapToolIdentifyFeature::featureIdentified
void featureIdentified(const QgsFeature &)
QgsRelationReferenceWidget::QgsRelationReferenceWidget
QgsRelationReferenceWidget(QWidget *parent)
Definition: qgsrelationreferencewidget.cpp:64
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsExpression
Definition: qgsexpression.h:113
QgsAttributeEditorContext
Definition: qgsattributeeditorcontext.h:40
QgsVectorLayer::displayExpression
QString displayExpression
Definition: qgsvectorlayer.h:390
QgsRelationReferenceWidget::foreignKey
Q_DECL_DEPRECATED QVariant foreignKey() const
returns the related feature foreign key
Definition: qgsrelationreferencewidget.cpp:403
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsMapSettings::layerToMapCoordinates
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer's CRS to output CRS
Definition: qgsmapsettings.cpp:482
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:751
QgsIdentifyMenu::styleHighlight
static void styleHighlight(QgsHighlight *highlight)
Applies style from the settings to the highlight.
Definition: qgsidentifymenu.cpp:636
QgsRelationReferenceWidget::setReadOnlySelector
void setReadOnlySelector(bool readOnly)
Definition: qgsrelationreferencewidget.cpp:453
QgsRelationReferenceWidget::setFormFeature
void setFormFeature(const QgsFeature &formFeature)
Set the current form feature (from the referencing layer)
Definition: qgsrelationreferencewidget.cpp:1097
qgsrelationreferenceconfigdlg.h
QgsPathResolver
Definition: qgspathresolver.h:31
QgsAttributeEditorContext::vectorLayerTools
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
Definition: qgsattributeeditorcontext.h:171
QgsField::type
QVariant::Type type
Definition: qgsfield.h:57
QgsRelation::referencedLayerId
QString referencedLayerId() const
Access the referenced (parent) layer's id.
Definition: qgsrelation.cpp:296
QgsMapTool::deactivated
void deactivated()
signal emitted once the map tool is deactivated
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
QgsVectorLayerUtils::getFeatureDisplayString
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
Definition: qgsvectorlayerutils.cpp:961