Skip to content
Permalink
Browse files

Correctly use QgsProperties in editor widgets

TODO: save/restore properties
  • Loading branch information
nyalldawson authored and m-kuhn committed Mar 9, 2017
1 parent 2af1e9f commit 16870194147b1a974047139be6313e8e71b6aed2
@@ -14,7 +14,7 @@
***************************************************************************/

#include "qgseditorconfigwidget.h"

#include "qgspropertyoverridebutton.h"

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

QgsExpressionContext QgsEditorConfigWidget::createExpressionContext() const
{
return QgsExpressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );
}

void QgsEditorConfigWidget::initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key )
{
button->blockSignals( true );
button->init( key, mPropertyCollection, QgsWidgetWrapper::propertyDefinitions(), mLayer );
connect( button, &QgsPropertyOverrideButton::changed, this, &QgsEditorConfigWidget::changed );
button->registerExpressionContextGenerator( this );
button->blockSignals( false );
}

@@ -18,9 +18,11 @@

#include <QWidget>
#include "qgis_gui.h"

#include "qgseditorwidgetwrapper.h"
#include "qgsexpressioncontextgenerator.h"

class QgsVectorLayer;
class QgsPropertyOverrideButton;

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

class GUI_EXPORT QgsEditorConfigWidget : public QWidget
class GUI_EXPORT QgsEditorConfigWidget : public QWidget, public QgsExpressionContextGenerator
{
Q_OBJECT
public:
@@ -72,13 +74,27 @@ class GUI_EXPORT QgsEditorConfigWidget : public QWidget
*/
QgsVectorLayer *layer();

QgsExpressionContext createExpressionContext() const override;

signals:

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

protected:

/**
* Registers a property override button, setting up its initial value, connections and description.
* @param button button to register
* @param key corresponding data defined property key
*/
void initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key );

//! Temporary property collection for config widgets
QgsPropertyCollection mPropertyCollection;

private:
QgsVectorLayer *mLayer = nullptr;
int mField;
@@ -285,6 +285,7 @@ class GUI_EXPORT QgsEditorWidgetWrapper : public QgsWidgetWrapper
int mFieldIdx;
QgsFeature mFeature;
mutable QVariant mDefaultValue; // Cache default value, we don't want to retrieve different serial numbers if called repeatedly

};

// We'll use this class inside a QVariant in the widgets properties
@@ -18,6 +18,15 @@

#include <QWidget>


QgsPropertiesDefinition QgsWidgetWrapper::sPropertyDefinitions;

const QgsPropertiesDefinition &QgsWidgetWrapper::propertyDefinitions()
{
QgsWidgetWrapper::initPropertyDefinitions();
return sPropertyDefinitions;
}

QgsWidgetWrapper::QgsWidgetWrapper( QgsVectorLayer *vl, QWidget *editor, QWidget *parent )
: QObject( parent )
, mWidget( editor )
@@ -90,3 +99,14 @@ void QgsWidgetWrapper::setEnabled( bool enabled )
{
Q_UNUSED( enabled );
}

void QgsWidgetWrapper::initPropertyDefinitions()
{
if ( !sPropertyDefinitions.isEmpty() )
return;

sPropertyDefinitions = QgsPropertiesDefinition
{
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QString() ) }
};
}
@@ -24,6 +24,7 @@ class QgsVectorLayer;

#include "qgsattributeeditorcontext.h"
#include "qgis_gui.h"
#include "qgspropertycollection.h"

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

/**
* Data defined properties for different editor widgets.
*/
enum Property
{
RootPath = 0, //!< Root path for external resource
};

/**
* Returns the editor widget property definitions.
* @note added in QGIS 3.0
*/
static const QgsPropertiesDefinition &propertyDefinitions();

/**
* Create a new widget wrapper
*
@@ -133,6 +148,26 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
*/
virtual bool valid() const = 0;


/** Returns a reference to the editor widget's property collection, used for data defined overrides.
* @note added in QGIS 3.0
* @see setDataDefinedProperties()
*/
QgsPropertyCollection &dataDefinedProperties() { return mPropertyCollection; }

/** Returns a reference to the editor widget's property collection, used for data defined overrides.
* @note added in QGIS 3.0
* @see setDataDefinedProperties()
*/
const QgsPropertyCollection &dataDefinedProperties() const { return mPropertyCollection; }

/** Sets the editor widget's property collection, used for data defined overrides.
* @param collection property collection. Existing properties will be replaced.
* @note added in QGIS 3.0
* @see dataDefinedProperties()
*/
void setDataDefinedProperties( const QgsPropertyCollection &collection ) { mPropertyCollection = collection; }

protected:

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

//! Data defined property collection
QgsPropertyCollection mPropertyCollection;

public slots:

/**
@@ -180,6 +218,11 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
QWidget *mParent = nullptr;
QgsVectorLayer *mLayer = nullptr;
bool mInitialized;

//! Property definitions
static QgsPropertiesDefinition sPropertyDefinitions;

static void initPropertyDefinitions();
};

// We'll use this class inside a QVariant in the widgets properties
@@ -21,26 +21,12 @@
#include "qgsapplication.h"
#include "qgsvectorlayer.h"
#include "qgspropertyoverridebutton.h"
#include "qgseditorwidgetwrapper.h"

#include <QFileDialog>

class QgsExternalResourceWidgetWrapper;

const QgsPropertiesDefinition &QgsExternalResourceConfigDlg::propertyDefinitions()
{
static QgsPropertiesDefinition propertyDefinitions;

if ( propertyDefinitions.isEmpty() )
{
propertyDefinitions = QgsPropertiesDefinition
{
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QString() ) }
};
}

return propertyDefinitions;
}

QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl, int fieldIdx, QWidget *parent )
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
@@ -57,9 +43,7 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,

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

mRootPathPropertyOverrideButton->init( RootPath, mPropertyCollection, propertyDefinitions(), vl );

mRootPathPropertyOverrideButton->setVectorLayer( vl );
initializeDataDefinedButton( mRootPathPropertyOverrideButton, QgsEditorWidgetWrapper::RootPath );
connect( mRootPathPropertyOverrideButton, &QgsPropertyOverrideButton::changed, this, &QgsExternalResourceConfigDlg::rootPathPropertyChanged );

// Activate Relative Default Path option only if Default Path is set
@@ -116,8 +100,7 @@ void QgsExternalResourceConfigDlg::chooseDefaultPath()
void QgsExternalResourceConfigDlg::rootPathPropertyChanged()
{
QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();

setRootPathExpression( prop.expressionString() );
setRootPathExpression( prop );

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

if ( !mRootPathExpression->text().isEmpty() )
cfg.insert( QStringLiteral( "DefaultRootExpression" ), mRootPathExpression->toolTip() );

// Save Storage Mode
cfg.insert( QStringLiteral( "StorageMode" ), mStorageButtonGroup->checkedId() );

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

mRootPath->setText( config.value( QStringLiteral( "DefaultRoot" ) ).toString() );
setRootPathExpression( config.value( QStringLiteral( "DefaultRootExpression" ) ).toString() );

bool rootPathIsExpression = config.value( QStringLiteral( "DefaultRootStyle" ) ) == QStringLiteral( "expression" );

QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
prop.setActive( rootPathIsExpression );
mRootPathPropertyOverrideButton->setToProperty( prop );
rootPathPropertyChanged();

mRootPathExpression->setVisible( rootPathIsExpression );
mRootPath->setVisible( !rootPathIsExpression );

// relative storage
if ( config.contains( QStringLiteral( "RelativeStorage" ) ) )
{
@@ -281,18 +252,12 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
}
}

void QgsExternalResourceConfigDlg::setRootPathExpression( const QString &expression )
void QgsExternalResourceConfigDlg::setRootPathExpression( const QgsProperty &property )
{
mRootPathExpression->setToolTip( expression );
mRootPathPropertyOverrideButton->setText( expression );

QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
prop.setExpressionString( expression );
mRootPathPropertyOverrideButton->setToProperty( prop );
mRootPathExpression->setToolTip( property.asExpression() );

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

mRootPathExpression->setText( exp.evaluate( &ctx ).toString() );
mRootPathExpression->setText( property.valueAsString( ctx ) );
enableRelativeDefault();
}
@@ -48,16 +48,9 @@ class GUI_EXPORT QgsExternalResourceConfigDlg : public QgsEditorConfigWidget, pr
void enableRelativeDefault();

private:
enum Properties
{
RootPath
};

void setRootPathExpression( const QString &expression );
void setRootPathExpression( const QgsProperty &property );

const QgsPropertiesDefinition &propertyDefinitions();

QgsPropertyCollection mPropertyCollection;
};

#endif // QGSEXTERNALRESOURCECONFIGDLG_H
@@ -79,14 +79,17 @@ bool QgsExternalResourceWidgetWrapper::valid() const

void QgsExternalResourceWidgetWrapper::setFeature( const QgsFeature &feature )
{
if ( mQgsWidget && mDefaultRootExpression.isValid() )
if ( mQgsWidget && mPropertyCollection.isActive( QgsEditorWidgetWrapper::RootPath ) )
{
QgsExpressionContext expressionContext = QgsExpressionContextUtils::createFeatureBasedContext( feature, layer()->fields() );

QVariant value = mDefaultRootExpression.evaluate( &expressionContext );
qWarning() << "Default root << " << value.toString();

mQgsWidget->setDefaultRoot( value.toString() );
QgsExpressionContext expressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( layer() ) );
expressionContext.setFeature( feature );
bool ok = false;
QString path = mPropertyCollection.valueAsString( QgsEditorWidgetWrapper::RootPath, expressionContext, QString(), &ok );
if ( ok )
{
qWarning() << "Default root << " << path;
mQgsWidget->setDefaultRoot( path );
}
}

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

qWarning() << "Default root style " << cfg.value( QStringLiteral( "DefaultRootStyle" ) );
if ( cfg.value( QStringLiteral( "DefaultRootStyle" ) ).toString() == QStringLiteral( "expression" ) )
{
mDefaultRootExpression = QgsExpression( cfg.value( QStringLiteral( "DefaultRootExpression" ) ).toString() );
}
else
if ( !mPropertyCollection.isActive( QgsWidgetWrapper::RootPath ) )
{
mQgsWidget->setDefaultRoot( cfg.value( QStringLiteral( "DefaultRoot" ) ).toString() );
}
@@ -61,8 +61,6 @@ class GUI_EXPORT QgsExternalResourceWidgetWrapper : public QgsEditorWidgetWrappe
QLineEdit *mLineEdit = nullptr;
QLabel *mLabel = nullptr;
QgsExternalResourceWidget *mQgsWidget = nullptr;

QgsExpression mDefaultRootExpression;
};

#endif // QGSEXTERNALRESOURCEWIDGETWRAPPER_H

0 comments on commit 1687019

Please sign in to comment.
You can’t perform that action at this time.