QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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 "qgsgui.h"
21#include "qgsproject.h"
23#include "qgsrelationmanager.h"
25
26#include <QWidget>
27
28#include "moc_qgsrelationwidgetwrapper.cpp"
29
31 : QgsRelationWidgetWrapper( QStringLiteral( "relation_editor" ), vl, relation, editor, parent )
32{
33}
34
35QgsRelationWidgetWrapper::QgsRelationWidgetWrapper( const QString &relationEditorName, QgsVectorLayer *vl, const QgsRelation &relation, QWidget *editor, QWidget *parent )
36 : QgsWidgetWrapper( vl, editor, parent )
37 , mRelation( relation )
38 , mRelationEditorId( relationEditorName )
39{
40}
41
42QWidget *QgsRelationWidgetWrapper::createWidget( QWidget *parent )
43{
44 QgsAttributeForm *form = qobject_cast<QgsAttributeForm *>( parent );
45 if ( form )
47
48 QgsAbstractRelationEditorWidget *relationEditorWidget = QgsGui::relationWidgetRegistry()->create( mRelationEditorId, widgetConfig(), parent );
49
50 if ( !relationEditorWidget )
51 {
52 QgsLogger::warning( QStringLiteral( "Failed to create relation widget \"%1\", fallback to \"basic\" relation widget" ).arg( mRelationEditorId ) );
53 relationEditorWidget = QgsGui::relationWidgetRegistry()->create( QStringLiteral( "relation_editor" ), widgetConfig(), parent );
54 }
55
57
58 return relationEditorWidget;
59}
60
62{
63 if ( mWidget && mRelation.isValid() )
64 mWidget->setFeature( feature );
65}
66
68{
69 if ( mWidget && mRelation.isValid() )
70 mWidget->setMultiEditFeatureIds( fids );
71}
72
74{
75 if ( mWidget )
76 mWidget->setVisible( visible );
77}
78
79void QgsRelationWidgetWrapper::aboutToSave()
80{
81 if ( !mRelation.isValid() || !widget() || !widget()->isVisible() || mRelation.referencingLayer() == mRelation.referencedLayer() || ( mNmRelation.isValid() && mNmRelation.referencedLayer() == mRelation.referencedLayer() ) )
82 return;
83
84 // If the layer is already saved before, return
85 const QgsAttributeEditorContext *ctx = &context();
86 do
87 {
88 if ( ctx->relation().isValid() && ( ctx->relation().referencedLayer() == mRelation.referencingLayer() || ( mNmRelation.isValid() && ctx->relation().referencedLayer() == mNmRelation.referencedLayer() ) ) )
89 {
90 return;
91 }
92 ctx = ctx->parentContext();
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 ( void ) mRelation.referencingLayer()->isModified();
99
100 if ( mNmRelation.isValid() )
101 {
102 ( void ) mNmRelation.referencedLayer()->isModified();
103 }
104}
105
107{
108 return mRelation;
109}
110
111void QgsRelationWidgetWrapper::widgetValueChanged( const QString &attribute, const QVariant &newValue, bool attributeChanged )
112{
113 if ( mWidget && attributeChanged )
114 {
115 QgsFeature feature { mWidget->feature() };
116 if ( feature.attribute( attribute ) != newValue )
117 {
118 feature.setAttribute( attribute, newValue );
119 QgsAttributeEditorContext newContext { mWidget->editorContext() };
120 newContext.setParentFormFeature( feature );
121 mWidget->setEditorContext( newContext );
122 mWidget->setFeature( feature, false );
123 mWidget->parentFormValueChanged( attribute, newValue );
124 }
125 }
126}
127
134
141
148
150{
151 return false;
152}
153
155{
156 Q_UNUSED( showLabel )
157}
158
160{
161 QgsAbstractRelationEditorWidget *w = qobject_cast<QgsAbstractRelationEditorWidget *>( editor );
162
163 // if the editor cannot be cast to relation editor, insert a new one
164 if ( !w )
165 {
166 w = QgsGui::relationWidgetRegistry()->create( mRelationEditorId, widgetConfig(), editor );
167 if ( !editor->layout() )
168 {
169 editor->setLayout( new QVBoxLayout( editor ) );
170 }
171 editor->layout()->addWidget( w );
172 }
173
175
176 // read the legacy config of force-suppress-popup to support settings made on autoconfigurated forms
177 // it will be overwritten on specific widget configuration
178 if ( config( QStringLiteral( "force-suppress-popup" ), false ).toBool() )
179 {
180 const_cast<QgsVectorLayerTools *>( myContext.vectorLayerTools() )->setForceSuppressFormPopup( true );
181 }
182
183 /* TODO: this seems to have no effect
184 if ( config( QStringLiteral( "hide-save-child-edits" ), false ).toBool() )
185 {
186 w->setShowSaveChildEditsButton( false );
187 }
188 */
189
190 // read the legacy config of nm-rel to support settings made on autoconfigurated forms
191 // it will be overwritten on specific widget configuration
192 mNmRelation = QgsProject::instance()->relationManager()->relation( config( QStringLiteral( "nm-rel" ) ).toString() );
193
194 // If this widget is already embedded by the same relation, reduce functionality
195 const QgsAttributeEditorContext *ctx = &context();
196 do
197 {
198 if ( ( ctx->relation().id() == mRelation.id() && ctx->formMode() == QgsAttributeEditorContext::Embed )
199 || ( mNmRelation.isValid() && ctx->relation().id() == mNmRelation.id() ) )
200 {
201 w->setVisible( false );
202 break;
203 }
204 ctx = ctx->parentContext();
205 } while ( ctx );
206
207 w->setEditorContext( myContext );
208 w->setRelations( mRelation, mNmRelation );
209
210 mWidget = w;
211}
212
214{
215 return mWidget;
216}
217
224
231
238
240{
241 if ( !mWidget )
242 return;
243 QVariantMap config = mWidget->config();
244 config.insert( "buttons", qgsFlagValueToKeys( buttons ) );
245
246 mWidget->setConfig( config );
247}
248
250{
251 return qgsFlagKeysToValue( mWidget->config().value( QStringLiteral( "buttons" ) ).toString(), QgsAttributeEditorRelation::AllButtons );
252}
253
255{
256 if ( mWidget )
257 {
258 mWidget->setForceSuppressFormPopup( forceSuppressFormPopup );
259 //it's set to true if one widget is configured like this but the setting is done generally (influencing all widgets).
260 const_cast<QgsVectorLayerTools *>( mWidget->editorContext().vectorLayerTools() )->setForceSuppressFormPopup( forceSuppressFormPopup );
261 }
262}
263
265{
266 if ( mWidget )
267 return mWidget->forceSuppressFormPopup();
268
269 return false;
270}
271
273{
274 if ( mWidget )
275 {
276 mNmRelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
277
278 // If this widget is already embedded by the same relation, reduce functionality
279 const QgsAttributeEditorContext *ctx = &context();
280 while ( ctx && ctx->relation().isValid() )
281 {
282 if ( ( ctx->relation().id() == mRelation.id() && ctx->formMode() == QgsAttributeEditorContext::Embed )
283 || ( mNmRelation.isValid() && ctx->relation().id() == mNmRelation.id() ) )
284 {
285 mWidget->setVisible( false );
286 break;
287 }
288 ctx = ctx->parentContext();
289 }
290
291 mWidget->setRelations( mRelation, mNmRelation );
292 }
293}
294
296{
297 if ( mWidget )
298 return mWidget->nmRelationId();
299 return QVariant();
300}
301
302
304{
305 Q_UNUSED( label )
306}
307
309{
310 return QString();
311}
312
314{
315 if ( mWidget )
316 mWidget->setConfig( config );
317}
318
320{
321 return mWidget ? mWidget->config() : QVariantMap();
322}
Base class to build new relation widgets.
virtual void setEditorContext(const QgsAttributeEditorContext &context)
Sets the editor context.
void relatedFeaturesChanged()
Emit this signal, whenever the related features changed.
void setRelations(const QgsRelation &relation, const QgsRelation &nmrelation)
Sets the relation(s) for this widget If only one relation is set, it will act as a simple 1:N relatio...
void setFeature(const QgsFeature &feature, bool update=true)
Sets the feature being edited and updates the UI unless update is set to false.
Contains context information for attribute editor widgets.
FormMode formMode() const
Returns the form mode.
@ Multiple
When showing a list of features (e.g. houses as an embedded form in a district form).
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
@ Embed
A form was embedded as a widget on another form.
void setParentFormFeature(const QgsFeature &feature)
Sets the feature of the currently edited parent form.
const QgsAttributeEditorContext * parentContext() const
const QgsRelation & relation() const
Returns the attribute relation.
@ SaveChildEdits
Save child edits button.
The attribute form widget for vector layer features.
void widgetValueChanged(const QString &attribute, const QVariant &value, bool attributeChanged)
Notifies about changes of attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
static QgsRelationWidgetRegistry * relationWidgetRegistry()
Returns the global relation widget registry, used for managing all known relation widget factories.
Definition qgsgui.cpp:111
static void warning(const QString &msg)
Goes to qWarning.
QgsRelationManager * relationManager
Definition qgsproject.h:120
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
QgsAbstractRelationEditorWidget * create(const QString &widgetType, const QVariantMap &config, QWidget *parent=nullptr) const
Create a relation widget of a given type for a given field.
void relatedFeaturesChanged()
Emit this signal, whenever the related features changed.
Q_DECL_DEPRECATED bool showLabel() const
Defines if a title label should be shown for this widget.
void setVisible(bool visible)
Sets the visibility of the wrapper's widget.
Q_DECL_DEPRECATED void setVisibleButtons(const QgsAttributeEditorRelation::Buttons &buttons)
Defines the buttons which are shown.
QgsRelation relation() const
The relation for which this wrapper is created.
QVariantMap widgetConfig() const
Returns the whole widget config.
Q_DECL_DEPRECATED void setShowLabel(bool showLabel)
Defines if a title label should be shown for this widget.
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.
void setWidgetConfig(const QVariantMap &config)
Will set the config of this widget wrapper to the specified config.
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.
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup for this widget and for the vectorLay...
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Q_DECL_DEPRECATED bool showLinkButton() const
Determines if the "link feature" button should be shown.
Q_DECL_DEPRECATED bool showUnlinkButton() const
Determines if the "unlink feature" button should be shown.
bool forceSuppressFormPopup() const
Determines the force suppress form popup status that is configured for this widget.
bool valid() const override
Returns true if the widget has been properly initialized.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
void setMultiEditFeatureIds(const QgsFeatureIds &fids)
Set multiple feature to edit simultaneously.
Q_DECL_DEPRECATED void setShowUnlinkButton(bool showUnlinkButton)
Determines if the "unlink feature" button should be shown.
Q_DECL_DEPRECATED QgsAttributeEditorRelation::Buttons visibleButtons() const
Returns the buttons which are shown.
QgsRelationWidgetWrapper(QgsVectorLayer *vl, const QgsRelation &relation, QWidget *editor=nullptr, QWidget *parent=nullptr)
Constructor for QgsRelationWidgetWrapper.
Q_DECL_DEPRECATED QString label() const
Determines the label of this element.
void setNmRelationId(const QVariant &nmRelationId=QVariant())
Sets nmRelationId for the relation id of the second relation involved in an N:M relation.
QVariant nmRelationId() const
Determines the relation id of the second relation involved in an N:M relation.
Q_DECL_DEPRECATED bool showSaveChildEditsButton() const
Determines if the "Save child layer edits" button should be shown.
Q_DECL_DEPRECATED void setShowSaveChildEditsButton(bool showChildEdits)
Determines if the "Save child layer edits" button should be shown.
Q_DECL_DEPRECATED void setShowLinkButton(bool showLinkButton)
Determines if the "link feature" button should be shown.
void setFeature(const QgsFeature &feature) override
Represents a relationship between two vector layers.
Definition qgsrelation.h:42
QgsVectorLayer * referencedLayer
Definition qgsrelation.h:50
QString id
Definition qgsrelation.h:45
QgsVectorLayer * referencingLayer
Definition qgsrelation.h:47
Used to handle basic editing operations on vector layers.
void setForceSuppressFormPopup(bool forceSuppressFormPopup)
Sets force suppress form popup status to forceSuppressFormPopup.
Represents a vector layer which manages a vector based dataset.
QWidget * widget()
Access the widget managed by this wrapper.
QVariant config(const QString &key, const QVariant &defaultVal=QVariant()) const
Use this inside your overridden classes to access the configuration.
QgsWidgetWrapper(QgsVectorLayer *vl, QWidget *editor=nullptr, QWidget *parent=nullptr)
Create a new widget wrapper.
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
QVariantMap config() const
Returns the whole config.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7170
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
Definition qgis.h:6856
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:6878
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7169
QSet< QgsFeatureId > QgsFeatureIds