QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsrelationwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrelationwidgetwrapper.cpp
3  --------------------------------------
4  Date : 14.5.2014
5  Copyright : (C) 2014 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 
20 #include "qgsproject.h"
21 #include "qgsrelationmanager.h"
24 #include "qgsgui.h"
25 #include <QWidget>
26 
27 QgsRelationWidgetWrapper::QgsRelationWidgetWrapper( QgsVectorLayer *vl, const QgsRelation &relation, QWidget *editor, QWidget *parent )
28  : QgsRelationWidgetWrapper( QStringLiteral( "relation_editor" ), vl, relation, editor, parent )
29 {
30 }
31 
32 QgsRelationWidgetWrapper::QgsRelationWidgetWrapper( const QString &relationEditorName, QgsVectorLayer *vl, const QgsRelation &relation, QWidget *editor, QWidget *parent )
33  : QgsWidgetWrapper( vl, editor, parent )
34  , mRelation( relation )
35  , mRelationEditorId( relationEditorName )
36 {
37 }
38 
39 QWidget *QgsRelationWidgetWrapper::createWidget( QWidget *parent )
40 {
41  QgsAttributeForm *form = qobject_cast<QgsAttributeForm *>( parent );
42  if ( form )
44 
45  QgsAbstractRelationEditorWidget *relationEditorWidget = QgsGui::relationWidgetRegistry()->create( mRelationEditorId, widgetConfig(), parent );
46 
47  if ( !relationEditorWidget )
48  {
49  QgsLogger::warning( QStringLiteral( "Failed to create relation widget \"%1\", fallback to \"basic\" relation widget" ).arg( mRelationEditorId ) );
50  relationEditorWidget = QgsGui::relationWidgetRegistry()->create( QStringLiteral( "relation_editor" ), widgetConfig(), parent );
51  }
52 
54 
55  return relationEditorWidget;
56 }
57 
59 {
60  if ( mWidget && mRelation.isValid() )
61  mWidget->setFeature( feature );
62 }
63 
65 {
66  if ( mWidget && mRelation.isValid() )
67  mWidget->setMultiEditFeatureIds( fids );
68 }
69 
71 {
72  if ( mWidget )
73  mWidget->setVisible( visible );
74 }
75 
76 void QgsRelationWidgetWrapper::aboutToSave()
77 {
78  if ( !mRelation.isValid() || !widget() || !widget()->isVisible() || mRelation.referencingLayer() == mRelation.referencedLayer() || ( mNmRelation.isValid() && mNmRelation.referencedLayer() == mRelation.referencedLayer() ) )
79  return;
80 
81  // If the layer is already saved before, return
82  const QgsAttributeEditorContext *ctx = &context();
83  do
84  {
85  if ( ctx->relation().isValid() && ( ctx->relation().referencedLayer() == mRelation.referencingLayer()
86  || ( mNmRelation.isValid() && ctx->relation().referencedLayer() == mNmRelation.referencedLayer() ) )
87  )
88  {
89  return;
90  }
91  ctx = ctx->parentContext();
92  }
93  while ( ctx );
94 
95  // Calling isModified() will emit a beforeModifiedCheck()
96  // signal that will make the embedded form to send any
97  // outstanding widget changes to the edit buffer
98  mRelation.referencingLayer()->isModified();
99 
100  if ( mNmRelation.isValid() )
101  mNmRelation.referencedLayer()->isModified();
102 }
103 
105 {
106  return mRelation;
107 }
108 
109 void QgsRelationWidgetWrapper::widgetValueChanged( const QString &attribute, const QVariant &newValue, bool attributeChanged )
110 {
111  if ( mWidget && attributeChanged )
112  {
113  QgsFeature feature { mWidget->feature() };
114  if ( feature.attribute( attribute ) != newValue )
115  {
116  feature.setAttribute( attribute, newValue );
117  QgsAttributeEditorContext newContext { mWidget->editorContext() };
118  newContext.setParentFormFeature( feature );
119  mWidget->setEditorContext( newContext );
120  mWidget->setFeature( feature, false );
121  mWidget->parentFormValueChanged( attribute, newValue );
122  }
123  }
124 }
125 
127 {
129  return visibleButtons().testFlag( QgsAttributeEditorRelation::Button::Unlink );
131 }
132 
134 {
138 }
139 
140 void QgsRelationWidgetWrapper::setShowSaveChildEditsButton( bool showSaveChildEditsButton )
141 {
145 }
146 
148 {
149  return false;
150 }
151 
153 {
154  Q_UNUSED( showLabel )
155 }
156 
158 {
159  QgsAbstractRelationEditorWidget *w = qobject_cast<QgsAbstractRelationEditorWidget *>( editor );
160 
161  // if the editor cannot be cast to relation editor, insert a new one
162  if ( !w )
163  {
164  w = QgsGui::relationWidgetRegistry()->create( mRelationEditorId, widgetConfig(), editor );
165  if ( ! editor->layout() )
166  {
167  editor->setLayout( new QVBoxLayout( editor ) );
168  }
169  editor->layout()->addWidget( w );
170  }
171 
173 
174  // read the legacy config of force-suppress-popup to support settings made on autoconfigurated forms
175  // it will be overwritten on specific widget configuration
176  if ( config( QStringLiteral( "force-suppress-popup" ), false ).toBool() )
177  {
178  const_cast<QgsVectorLayerTools *>( myContext.vectorLayerTools() )->setForceSuppressFormPopup( true );
179  }
180 
181  /* TODO: this seems to have no effect
182  if ( config( QStringLiteral( "hide-save-child-edits" ), false ).toBool() )
183  {
184  w->setShowSaveChildEditsButton( false );
185  }
186  */
187 
188  // read the legacy config of nm-rel to support settings made on autoconfigurated forms
189  // it will be overwritten on specific widget configuration
190  mNmRelation = QgsProject::instance()->relationManager()->relation( config( QStringLiteral( "nm-rel" ) ).toString() );
191 
192  // If this widget is already embedded by the same relation, reduce functionality
193  const QgsAttributeEditorContext *ctx = &context();
194  do
195  {
196  if ( ( ctx->relation().id() == mRelation.id() && ctx->formMode() == QgsAttributeEditorContext::Embed )
197  || ( mNmRelation.isValid() && ctx->relation().id() == mNmRelation.id() ) )
198  {
199  w->setVisible( false );
200  break;
201  }
202  ctx = ctx->parentContext();
203  }
204  while ( ctx );
205 
206  w->setEditorContext( myContext );
207  w->setRelations( mRelation, mNmRelation );
208 
209  mWidget = w;
210 }
211 
213 {
214  return mWidget;
215 }
216 
218 {
220  return visibleButtons().testFlag( QgsAttributeEditorRelation::Button::Link );
222 }
223 
225 {
229 }
230 
232 {
234  return visibleButtons().testFlag( QgsAttributeEditorRelation::Button::SaveChildEdits );
236 }
237 
238 void QgsRelationWidgetWrapper::setVisibleButtons( const QgsAttributeEditorRelation::Buttons &buttons )
239 {
240  if ( ! mWidget )
241  return;
242  QVariantMap config = mWidget->config();
243  config.insert( "buttons", qgsFlagValueToKeys( buttons ) );
244 
245  mWidget->setConfig( config );
246 }
247 
248 QgsAttributeEditorRelation::Buttons QgsRelationWidgetWrapper::visibleButtons() const
249 {
250  return qgsFlagKeysToValue( mWidget->config().value( QStringLiteral( "buttons" ) ).toString(), QgsAttributeEditorRelation::AllButtons );
251 }
252 
253 void QgsRelationWidgetWrapper::setForceSuppressFormPopup( bool forceSuppressFormPopup )
254 {
255  if ( mWidget )
256  {
258  //it's set to true if one widget is configured like this but the setting is done generally (influencing all widgets).
260  }
261 }
262 
264 {
265  if ( mWidget )
266  return mWidget->forceSuppressFormPopup();
267 
268  return false;
269 }
270 
271 void QgsRelationWidgetWrapper::setNmRelationId( const QVariant &nmRelationId )
272 {
273  if ( mWidget )
274  {
275  mNmRelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
276 
277  // If this widget is already embedded by the same relation, reduce functionality
278  const QgsAttributeEditorContext *ctx = &context();
279  while ( ctx && ctx->relation().isValid() )
280  {
281  if ( ( ctx->relation().id() == mRelation.id() && ctx->formMode() == QgsAttributeEditorContext::Embed )
282  || ( mNmRelation.isValid() && ctx->relation().id() == mNmRelation.id() ) )
283  {
284  mWidget->setVisible( false );
285  break;
286  }
287  ctx = ctx->parentContext();
288  }
289 
290  mWidget->setRelations( mRelation, mNmRelation );
291  }
292 }
293 
295 {
296  if ( mWidget )
297  return mWidget->nmRelationId();
298  return QVariant();
299 }
300 
301 
302 void QgsRelationWidgetWrapper::setLabel( const QString &label )
303 {
304  Q_UNUSED( label )
305 }
306 
308 {
309  return QString();
310 }
311 
312 void QgsRelationWidgetWrapper::setWidgetConfig( const QVariantMap &config )
313 {
314  if ( mWidget )
315  mWidget->setConfig( config );
316 }
317 
319 {
320  return mWidget ? mWidget->config() : QVariantMap();
321 }
QgsAbstractRelationEditorWidget::setConfig
virtual void setConfig(const QVariantMap &config)=0
Defines the widget configuration.
QgsProject::relationManager
QgsRelationManager relationManager
Definition: qgsproject.h:114
QgsAttributeEditorContext::setParentFormFeature
void setParentFormFeature(const QgsFeature &feature)
Sets the feature of the currently edited parent form.
Definition: qgsattributeeditorcontext.h:258
QgsRelationWidgetWrapper::widgetConfig
QVariantMap widgetConfig() const
Returns the whole widget config.
Definition: qgsrelationwidgetwrapper.cpp:318
QgsRelationWidgetWrapper::setWidgetConfig
void setWidgetConfig(const QVariantMap &config)
Will set the config of this widget wrapper to the specified config.
Definition: qgsrelationwidgetwrapper.cpp:312
QgsRelationWidgetWrapper::showSaveChildEditsButton
Q_DECL_DEPRECATED bool showSaveChildEditsButton() const
Determines if the "Save child layer edits" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:231
QgsWidgetWrapper
Manages an editor widget Widget and wrapper share the same parent.
Definition: qgswidgetwrapper.h:52
QgsAbstractRelationEditorWidget::relatedFeaturesChanged
void relatedFeaturesChanged()
Emit this signal, whenever the related features changed.
qgsgui.h
QgsRelationWidgetWrapper::visibleButtons
Q_DECL_DEPRECATED QgsAttributeEditorRelation::Buttons visibleButtons() const
Returns the buttons which are shown.
Definition: qgsrelationwidgetwrapper.cpp:248
QgsRelationWidgetWrapper::setShowLinkButton
Q_DECL_DEPRECATED void setShowLinkButton(bool showLinkButton)
Determines if the "link feature" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:224
qgsrelationwidgetregistry.h
QgsRelationWidgetWrapper
Definition: qgsrelationwidgetwrapper.h:32
qgsFlagKeysToValue
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
Definition: qgis.h:2520
QgsAttributeEditorRelation::Unlink
@ Unlink
Unlink button.
Definition: qgsattributeeditorrelation.h:45
QgsVectorLayerTools
Methods in this class are used to handle basic operations on vector layers. With an implementation of...
Definition: qgsvectorlayertools.h:39
QgsAbstractRelationEditorWidget::parentFormValueChanged
virtual void parentFormValueChanged(const QString &attribute, const QVariant &newValue)=0
Called when an attribute value in the parent widget has changed to newValue.
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsRelationManager::relation
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Definition: qgsrelationmanager.cpp:95
QgsAbstractRelationEditorWidget::setEditorContext
virtual void setEditorContext(const QgsAttributeEditorContext &context)
Sets the editor context.
Definition: qgsabstractrelationeditorwidget.cpp:95
QgsAttributeEditorContext::Embed
@ Embed
A form was embedded as a widget on another form.
Definition: qgsattributeeditorcontext.h:72
QgsRelationWidgetWrapper::setLabel
Q_DECL_DEPRECATED void setLabel(const QString &label=QString())
Sets label for this element If it's empty it takes the relation id as label.
Definition: qgsrelationwidgetwrapper.cpp:302
QgsAbstractRelationEditorWidget::editorContext
QgsAttributeEditorContext editorContext() const
Returns the attribute editor context.
Definition: qgsabstractrelationeditorwidget.cpp:100
QgsWidgetWrapper::context
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
Definition: qgswidgetwrapper.cpp:87
qgsrelationeditorwidget.h
QgsWidgetWrapper::widget
QWidget * widget()
Access the widget managed by this wrapper.
Definition: qgswidgetwrapper.cpp:47
QgsRelationWidgetWrapper::showLinkButton
Q_DECL_DEPRECATED bool showLinkButton() const
Determines if the "link feature" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:217
QgsRelationWidgetWrapper::setNmRelationId
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
Definition: qgsrelationwidgetwrapper.cpp:271
QgsRelationWidgetWrapper::forceSuppressFormPopup
bool forceSuppressFormPopup() const
Determines the force suppress form popup status that is configured for this widget.
Definition: qgsrelationwidgetwrapper.cpp:263
QgsRelationWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsrelationwidgetwrapper.cpp:39
QgsAttributeEditorContext::relation
const QgsRelation & relation() const
Returns the attribute relation.
Definition: qgsattributeeditorcontext.h:190
QgsRelation::referencingLayer
QgsVectorLayer referencingLayer
Definition: qgsrelation.h:47
QgsRelationWidgetWrapper::widgetValueChanged
void widgetValueChanged(const QString &attribute, const QVariant &newValue, bool attributeChanged)
Will be called when a value in the current edited form or table row changes.
Definition: qgsrelationwidgetwrapper.cpp:109
QgsRelation::id
QString id
Definition: qgsrelation.h:46
QgsRelationWidgetWrapper::relation
QgsRelation relation() const
The relation for which this wrapper is created.
Definition: qgsrelationwidgetwrapper.cpp:104
QgsRelationWidgetWrapper::QgsRelationWidgetWrapper
QgsRelationWidgetWrapper(QgsVectorLayer *vl, const QgsRelation &relation, QWidget *editor=nullptr, QWidget *parent=nullptr)
Constructor for QgsRelationWidgetWrapper.
Definition: qgsrelationwidgetwrapper.cpp:27
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
qgsFlagValueToKeys
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
Definition: qgis.h:2498
QgsRelationWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsrelationwidgetwrapper.cpp:157
QgsAbstractRelationEditorWidget::forceSuppressFormPopup
bool forceSuppressFormPopup() const
Determines the force suppress form popup status that is configured for this widget.
Definition: qgsabstractrelationeditorwidget.cpp:168
QgsAbstractRelationEditorWidget::config
virtual QVariantMap config() const =0
Returns the widget configuration.
QgsRelation::referencedLayer
QgsVectorLayer referencedLayer
Definition: qgsrelation.h:48
QgsAbstractRelationEditorWidget::nmRelationId
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
Definition: qgsabstractrelationeditorwidget.cpp:138
QgsLogger::warning
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
QgsAbstractRelationEditorWidget::feature
QgsFeature feature() const
Returns the widget's current feature If the widget is in multiedit mode only the first is returned.
Definition: qgsabstractrelationeditorwidget.cpp:182
QgsAbstractRelationEditorWidget::setForceSuppressFormPopup
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status with forceSuppressFormPopup configured for this widget.
Definition: qgsabstractrelationeditorwidget.cpp:163
qgsattributeeditorcontext.h
QgsRelationWidgetWrapper::setShowUnlinkButton
Q_DECL_DEPRECATED void setShowUnlinkButton(bool showUnlinkButton)
Determines if the "unlink feature" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:133
QgsAttributeEditorContext::formMode
FormMode formMode() const
Returns the form mode.
Definition: qgsattributeeditorcontext.h:204
qgsrelationmanager.h
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsRelationWidgetWrapper::setFeature
void setFeature(const QgsFeature &feature) override
Definition: qgsrelationwidgetwrapper.cpp:58
qgsabstractrelationeditorwidget.h
QgsAttributeEditorRelation::Link
@ Link
Link button.
Definition: qgsattributeeditorrelation.h:44
QgsRelationWidgetWrapper::label
Q_DECL_DEPRECATED QString label() const
Determines the label of this element.
Definition: qgsrelationwidgetwrapper.cpp:307
QgsFeature::setAttribute
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:262
QgsRelationWidgetWrapper::setVisibleButtons
Q_DECL_DEPRECATED void setVisibleButtons(const QgsAttributeEditorRelation::Buttons &buttons)
Defines the buttons which are shown.
Definition: qgsrelationwidgetwrapper.cpp:238
QgsRelationWidgetWrapper::setVisible
void setVisible(bool visible)
Sets the visibility of the wrapper's widget.
Definition: qgsrelationwidgetwrapper.cpp:70
QgsWidgetWrapper::config
QVariantMap config() const
Returns the whole config.
Definition: qgswidgetwrapper.cpp:82
QgsGui::relationWidgetRegistry
static QgsRelationWidgetRegistry * relationWidgetRegistry()
Returns the global relation widget registry, used for managing all known relation widget factories.
Definition: qgsgui.cpp:90
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsRelationWidgetWrapper::setMultiEditFeatureIds
void setMultiEditFeatureIds(const QgsFeatureIds &fids)
Set multiple feature to edit simultaneously.
Definition: qgsrelationwidgetwrapper.cpp:64
QgsRelation::isValid
bool isValid
Definition: qgsrelation.h:50
QgsRelationWidgetWrapper::setShowLabel
Q_DECL_DEPRECATED void setShowLabel(bool showLabel)
Defines if a title label should be shown for this widget.
Definition: qgsrelationwidgetwrapper.cpp:152
QgsRelationWidgetWrapper::nmRelationId
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
Definition: qgsrelationwidgetwrapper.cpp:294
QgsRelationWidgetWrapper::setShowSaveChildEditsButton
Q_DECL_DEPRECATED void setShowSaveChildEditsButton(bool showChildEdits)
Determines if the "Save child layer edits" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:140
QgsRelation
Definition: qgsrelation.h:42
QgsRelationWidgetRegistry::create
QgsAbstractRelationEditorWidget * create(const QString &widgetType, const QVariantMap &config, QWidget *parent=nullptr) const
Create a relation widget of a given type for a given field.
Definition: qgsrelationwidgetregistry.cpp:77
QgsRelationWidgetWrapper::showLabel
Q_DECL_DEPRECATED bool showLabel() const
Defines if a title label should be shown for this widget.
Definition: qgsrelationwidgetwrapper.cpp:147
QgsAttributeForm::widgetValueChanged
void widgetValueChanged(const QString &attribute, const QVariant &value, bool attributeChanged)
Notifies about changes of attributes.
QgsAttributeEditorRelation::SaveChildEdits
@ SaveChildEdits
Save child edits button.
Definition: qgsattributeeditorrelation.h:46
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsAttributeForm
Definition: qgsattributeform.h:44
QgsVectorLayer::isModified
bool isModified() const override
Returns true if the provider has been modified since the last commit.
Definition: qgsvectorlayer.cpp:3763
QgsRelationWidgetWrapper::setForceSuppressFormPopup
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup for this widget and for the vectorLay...
Definition: qgsrelationwidgetwrapper.cpp:253
QgsRelationWidgetWrapper::relatedFeaturesChanged
void relatedFeaturesChanged()
Emit this signal, whenever the related features changed.
QgsAbstractRelationEditorWidget::setRelations
void setRelations(const QgsRelation &relation, const QgsRelation &nmrelation)
Sets the relation(s) for this widget If only one relation is set, it will act as a simple 1:N relatio...
Definition: qgsabstractrelationeditorwidget.cpp:55
QgsAbstractRelationEditorWidget::setMultiEditFeatureIds
void setMultiEditFeatureIds(const QgsFeatureIds &fids)
Set multiple feature to edit simultaneously.
Definition: qgsabstractrelationeditorwidget.cpp:116
QgsAttributeEditorContext::parentContext
const QgsAttributeEditorContext * parentContext() const
Definition: qgsattributeeditorcontext.h:230
QgsAttributeEditorContext
This class contains context information for attribute editor widgets. It will be passed to embedded w...
Definition: qgsattributeeditorcontext.h:40
qgsrelationwidgetwrapper.h
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsAttributeEditorContext::Multiple
@ Multiple
When showing a list of features (e.g. houses as an embedded form in a district form)
Definition: qgsattributeeditorcontext.h:66
QgsAbstractRelationEditorWidget
Base class to build new relation widgets.
Definition: qgsabstractrelationeditorwidget.h:45
qgsproject.h
QgsAttributeEditorContext::vectorLayerTools
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
Definition: qgsattributeeditorcontext.h:172
QgsRelationWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsrelationwidgetwrapper.cpp:212
QgsRelationWidgetWrapper::showUnlinkButton
Q_DECL_DEPRECATED bool showUnlinkButton() const
Determines if the "unlink feature" button should be shown.
Definition: qgsrelationwidgetwrapper.cpp:126
QgsAttributeEditorRelation::AllButtons
@ AllButtons
All buttons.
Definition: qgsattributeeditorrelation.h:51
QgsAbstractRelationEditorWidget::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: qgsabstractrelationeditorwidget.cpp:105