Skip to content

Commit 1687019

Browse files
nyalldawsonm-kuhn
authored andcommitted
Correctly use QgsProperties in editor widgets
TODO: save/restore properties
1 parent 2af1e9f commit 1687019

9 files changed

+115
-66
lines changed

src/gui/editorwidgets/core/qgseditorconfigwidget.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
***************************************************************************/
1515

1616
#include "qgseditorconfigwidget.h"
17-
17+
#include "qgspropertyoverridebutton.h"
1818

1919
QgsEditorConfigWidget::QgsEditorConfigWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
2020
: QWidget( parent )
@@ -34,3 +34,17 @@ QgsVectorLayer *QgsEditorConfigWidget::layer()
3434
return mLayer;
3535
}
3636

37+
QgsExpressionContext QgsEditorConfigWidget::createExpressionContext() const
38+
{
39+
return QgsExpressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );
40+
}
41+
42+
void QgsEditorConfigWidget::initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key )
43+
{
44+
button->blockSignals( true );
45+
button->init( key, mPropertyCollection, QgsWidgetWrapper::propertyDefinitions(), mLayer );
46+
connect( button, &QgsPropertyOverrideButton::changed, this, &QgsEditorConfigWidget::changed );
47+
button->registerExpressionContextGenerator( this );
48+
button->blockSignals( false );
49+
}
50+

src/gui/editorwidgets/core/qgseditorconfigwidget.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
#include <QWidget>
2020
#include "qgis_gui.h"
21-
21+
#include "qgseditorwidgetwrapper.h"
22+
#include "qgsexpressioncontextgenerator.h"
2223

2324
class QgsVectorLayer;
25+
class QgsPropertyOverrideButton;
2426

2527
/** \ingroup gui
2628
* This class should be subclassed for every configurable editor widget type.
@@ -30,7 +32,7 @@ class QgsVectorLayer;
3032
* It will only be instantiated by {@see QgsEditorWidgetFactory}
3133
*/
3234

33-
class GUI_EXPORT QgsEditorConfigWidget : public QWidget
35+
class GUI_EXPORT QgsEditorConfigWidget : public QWidget, public QgsExpressionContextGenerator
3436
{
3537
Q_OBJECT
3638
public:
@@ -72,13 +74,27 @@ class GUI_EXPORT QgsEditorConfigWidget : public QWidget
7274
*/
7375
QgsVectorLayer *layer();
7476

77+
QgsExpressionContext createExpressionContext() const override;
78+
7579
signals:
7680

7781
/** Emitted when the configuration of the widget is changed.
7882
* @note added in QGIS 3.0
7983
*/
8084
void changed();
8185

86+
protected:
87+
88+
/**
89+
* Registers a property override button, setting up its initial value, connections and description.
90+
* @param button button to register
91+
* @param key corresponding data defined property key
92+
*/
93+
void initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key );
94+
95+
//! Temporary property collection for config widgets
96+
QgsPropertyCollection mPropertyCollection;
97+
8298
private:
8399
QgsVectorLayer *mLayer = nullptr;
84100
int mField;

src/gui/editorwidgets/core/qgseditorwidgetwrapper.h

+1
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ class GUI_EXPORT QgsEditorWidgetWrapper : public QgsWidgetWrapper
285285
int mFieldIdx;
286286
QgsFeature mFeature;
287287
mutable QVariant mDefaultValue; // Cache default value, we don't want to retrieve different serial numbers if called repeatedly
288+
288289
};
289290

290291
// We'll use this class inside a QVariant in the widgets properties

src/gui/editorwidgets/core/qgswidgetwrapper.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818

1919
#include <QWidget>
2020

21+
22+
QgsPropertiesDefinition QgsWidgetWrapper::sPropertyDefinitions;
23+
24+
const QgsPropertiesDefinition &QgsWidgetWrapper::propertyDefinitions()
25+
{
26+
QgsWidgetWrapper::initPropertyDefinitions();
27+
return sPropertyDefinitions;
28+
}
29+
2130
QgsWidgetWrapper::QgsWidgetWrapper( QgsVectorLayer *vl, QWidget *editor, QWidget *parent )
2231
: QObject( parent )
2332
, mWidget( editor )
@@ -90,3 +99,14 @@ void QgsWidgetWrapper::setEnabled( bool enabled )
9099
{
91100
Q_UNUSED( enabled );
92101
}
102+
103+
void QgsWidgetWrapper::initPropertyDefinitions()
104+
{
105+
if ( !sPropertyDefinitions.isEmpty() )
106+
return;
107+
108+
sPropertyDefinitions = QgsPropertiesDefinition
109+
{
110+
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QString() ) }
111+
};
112+
}

src/gui/editorwidgets/core/qgswidgetwrapper.h

+43
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QgsVectorLayer;
2424

2525
#include "qgsattributeeditorcontext.h"
2626
#include "qgis_gui.h"
27+
#include "qgspropertycollection.h"
2728

2829
/** \ingroup gui
2930
* Manages an editor widget
@@ -41,6 +42,20 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
4142
Q_OBJECT
4243
public:
4344

45+
/**
46+
* Data defined properties for different editor widgets.
47+
*/
48+
enum Property
49+
{
50+
RootPath = 0, //!< Root path for external resource
51+
};
52+
53+
/**
54+
* Returns the editor widget property definitions.
55+
* @note added in QGIS 3.0
56+
*/
57+
static const QgsPropertiesDefinition &propertyDefinitions();
58+
4459
/**
4560
* Create a new widget wrapper
4661
*
@@ -133,6 +148,26 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
133148
*/
134149
virtual bool valid() const = 0;
135150

151+
152+
/** Returns a reference to the editor widget's property collection, used for data defined overrides.
153+
* @note added in QGIS 3.0
154+
* @see setDataDefinedProperties()
155+
*/
156+
QgsPropertyCollection &dataDefinedProperties() { return mPropertyCollection; }
157+
158+
/** Returns a reference to the editor widget's property collection, used for data defined overrides.
159+
* @note added in QGIS 3.0
160+
* @see setDataDefinedProperties()
161+
*/
162+
const QgsPropertyCollection &dataDefinedProperties() const { return mPropertyCollection; }
163+
164+
/** Sets the editor widget's property collection, used for data defined overrides.
165+
* @param collection property collection. Existing properties will be replaced.
166+
* @note added in QGIS 3.0
167+
* @see dataDefinedProperties()
168+
*/
169+
void setDataDefinedProperties( const QgsPropertyCollection &collection ) { mPropertyCollection = collection; }
170+
136171
protected:
137172

138173
/**
@@ -155,6 +190,9 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
155190
*/
156191
virtual void initWidget( QWidget *editor );
157192

193+
//! Data defined property collection
194+
QgsPropertyCollection mPropertyCollection;
195+
158196
public slots:
159197

160198
/**
@@ -180,6 +218,11 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
180218
QWidget *mParent = nullptr;
181219
QgsVectorLayer *mLayer = nullptr;
182220
bool mInitialized;
221+
222+
//! Property definitions
223+
static QgsPropertiesDefinition sPropertyDefinitions;
224+
225+
static void initPropertyDefinitions();
183226
};
184227

185228
// We'll use this class inside a QVariant in the widgets properties

src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp

+6-41
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,12 @@
2121
#include "qgsapplication.h"
2222
#include "qgsvectorlayer.h"
2323
#include "qgspropertyoverridebutton.h"
24+
#include "qgseditorwidgetwrapper.h"
2425

2526
#include <QFileDialog>
2627

2728
class QgsExternalResourceWidgetWrapper;
2829

29-
const QgsPropertiesDefinition &QgsExternalResourceConfigDlg::propertyDefinitions()
30-
{
31-
static QgsPropertiesDefinition propertyDefinitions;
32-
33-
if ( propertyDefinitions.isEmpty() )
34-
{
35-
propertyDefinitions = QgsPropertiesDefinition
36-
{
37-
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QString() ) }
38-
};
39-
}
40-
41-
return propertyDefinitions;
42-
}
43-
4430
QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
4531
: QgsEditorConfigWidget( vl, fieldIdx, parent )
4632
{
@@ -57,9 +43,7 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,
5743

5844
connect( mRootPathButton, &QToolButton::clicked, this, &QgsExternalResourceConfigDlg::chooseDefaultPath );
5945

60-
mRootPathPropertyOverrideButton->init( RootPath, mPropertyCollection, propertyDefinitions(), vl );
61-
62-
mRootPathPropertyOverrideButton->setVectorLayer( vl );
46+
initializeDataDefinedButton( mRootPathPropertyOverrideButton, QgsEditorWidgetWrapper::RootPath );
6347
connect( mRootPathPropertyOverrideButton, &QgsPropertyOverrideButton::changed, this, &QgsExternalResourceConfigDlg::rootPathPropertyChanged );
6448

6549
// Activate Relative Default Path option only if Default Path is set
@@ -116,8 +100,7 @@ void QgsExternalResourceConfigDlg::chooseDefaultPath()
116100
void QgsExternalResourceConfigDlg::rootPathPropertyChanged()
117101
{
118102
QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
119-
120-
setRootPathExpression( prop.expressionString() );
103+
setRootPathExpression( prop );
121104

122105
mRootPathExpression->setVisible( prop.isActive() );
123106
mRootPath->setVisible( !prop.isActive() );
@@ -172,9 +155,6 @@ QVariantMap QgsExternalResourceConfigDlg::config()
172155
if ( !mRootPath->text().isEmpty() )
173156
cfg.insert( QStringLiteral( "DefaultRoot" ), mRootPath->text() );
174157

175-
if ( !mRootPathExpression->text().isEmpty() )
176-
cfg.insert( QStringLiteral( "DefaultRootExpression" ), mRootPathExpression->toolTip() );
177-
178158
// Save Storage Mode
179159
cfg.insert( QStringLiteral( "StorageMode" ), mStorageButtonGroup->checkedId() );
180160

@@ -226,18 +206,9 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
226206
}
227207

228208
mRootPath->setText( config.value( QStringLiteral( "DefaultRoot" ) ).toString() );
229-
setRootPathExpression( config.value( QStringLiteral( "DefaultRootExpression" ) ).toString() );
230-
231-
bool rootPathIsExpression = config.value( QStringLiteral( "DefaultRootStyle" ) ) == QStringLiteral( "expression" );
232209

233-
QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
234-
prop.setActive( rootPathIsExpression );
235-
mRootPathPropertyOverrideButton->setToProperty( prop );
236210
rootPathPropertyChanged();
237211

238-
mRootPathExpression->setVisible( rootPathIsExpression );
239-
mRootPath->setVisible( !rootPathIsExpression );
240-
241212
// relative storage
242213
if ( config.contains( QStringLiteral( "RelativeStorage" ) ) )
243214
{
@@ -281,18 +252,12 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
281252
}
282253
}
283254

284-
void QgsExternalResourceConfigDlg::setRootPathExpression( const QString &expression )
255+
void QgsExternalResourceConfigDlg::setRootPathExpression( const QgsProperty &property )
285256
{
286-
mRootPathExpression->setToolTip( expression );
287-
mRootPathPropertyOverrideButton->setText( expression );
288-
289-
QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
290-
prop.setExpressionString( expression );
291-
mRootPathPropertyOverrideButton->setToProperty( prop );
257+
mRootPathExpression->setToolTip( property.asExpression() );
292258

293-
QgsExpression exp( expression );
294259
QgsExpressionContext ctx = layer()->createExpressionContext();
295260

296-
mRootPathExpression->setText( exp.evaluate( &ctx ).toString() );
261+
mRootPathExpression->setText( property.valueAsString( ctx ) );
297262
enableRelativeDefault();
298263
}

src/gui/editorwidgets/qgsexternalresourceconfigdlg.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,9 @@ class GUI_EXPORT QgsExternalResourceConfigDlg : public QgsEditorConfigWidget, pr
4848
void enableRelativeDefault();
4949

5050
private:
51-
enum Properties
52-
{
53-
RootPath
54-
};
5551

56-
void setRootPathExpression( const QString &expression );
52+
void setRootPathExpression( const QgsProperty &property );
5753

58-
const QgsPropertiesDefinition &propertyDefinitions();
59-
60-
QgsPropertyCollection mPropertyCollection;
6154
};
6255

6356
#endif // QGSEXTERNALRESOURCECONFIGDLG_H

src/gui/editorwidgets/qgsexternalresourcewidgetwrapper.cpp

+11-12
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,17 @@ bool QgsExternalResourceWidgetWrapper::valid() const
7979

8080
void QgsExternalResourceWidgetWrapper::setFeature( const QgsFeature &feature )
8181
{
82-
if ( mQgsWidget && mDefaultRootExpression.isValid() )
82+
if ( mQgsWidget && mPropertyCollection.isActive( QgsEditorWidgetWrapper::RootPath ) )
8383
{
84-
QgsExpressionContext expressionContext = QgsExpressionContextUtils::createFeatureBasedContext( feature, layer()->fields() );
85-
86-
QVariant value = mDefaultRootExpression.evaluate( &expressionContext );
87-
qWarning() << "Default root << " << value.toString();
88-
89-
mQgsWidget->setDefaultRoot( value.toString() );
84+
QgsExpressionContext expressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( layer() ) );
85+
expressionContext.setFeature( feature );
86+
bool ok = false;
87+
QString path = mPropertyCollection.valueAsString( QgsEditorWidgetWrapper::RootPath, expressionContext, QString(), &ok );
88+
if ( ok )
89+
{
90+
qWarning() << "Default root << " << path;
91+
mQgsWidget->setDefaultRoot( path );
92+
}
9093
}
9194

9295
QgsEditorWidgetWrapper::setFeature( feature );
@@ -130,11 +133,7 @@ void QgsExternalResourceWidgetWrapper::initWidget( QWidget *editor )
130133
}
131134

132135
qWarning() << "Default root style " << cfg.value( QStringLiteral( "DefaultRootStyle" ) );
133-
if ( cfg.value( QStringLiteral( "DefaultRootStyle" ) ).toString() == QStringLiteral( "expression" ) )
134-
{
135-
mDefaultRootExpression = QgsExpression( cfg.value( QStringLiteral( "DefaultRootExpression" ) ).toString() );
136-
}
137-
else
136+
if ( !mPropertyCollection.isActive( QgsWidgetWrapper::RootPath ) )
138137
{
139138
mQgsWidget->setDefaultRoot( cfg.value( QStringLiteral( "DefaultRoot" ) ).toString() );
140139
}

src/gui/editorwidgets/qgsexternalresourcewidgetwrapper.h

-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ class GUI_EXPORT QgsExternalResourceWidgetWrapper : public QgsEditorWidgetWrappe
6161
QLineEdit *mLineEdit = nullptr;
6262
QLabel *mLabel = nullptr;
6363
QgsExternalResourceWidget *mQgsWidget = nullptr;
64-
65-
QgsExpression mDefaultRootExpression;
6664
};
6765

6866
#endif // QGSEXTERNALRESOURCEWIDGETWRAPPER_H

0 commit comments

Comments
 (0)