Skip to content

Commit

Permalink
Merge pull request #3079 from pblottiere/constraints
Browse files Browse the repository at this point in the history
[FEATURE] widgets constraints
  • Loading branch information
m-kuhn committed Jun 1, 2016
2 parents 61e26fd + 8774ad2 commit 2b1560c
Show file tree
Hide file tree
Showing 37 changed files with 1,113 additions and 45 deletions.
43 changes: 42 additions & 1 deletion python/core/qgseditformconfig.sip
Expand Up @@ -474,7 +474,48 @@ class QgsEditFormConfig : QObject
/** /**
* If set to false, the widget at the given index will be read-only. * If set to false, the widget at the given index will be read-only.
*/ */
void setReadOnly(int idx, bool readOnly ); void setReadOnly( int idx, bool readOnly = true );

/**
* Returns the constraint expression of a specific field
* @param idx The index of the field
* @return the expression
* @note added in QGIS 2.16
*/
QString expression( int idx ) const;

/**
* Set the constraint expression for a specific field
* @param idx the field index
* @param str the constraint expression
* @note added in QGIS 2.16
*/
void setExpression( int idx, const QString& str );

/**
* Returns the constraint expression description of a specific filed.
* @param idx The index of the field
* @return the expression description
* @note added in QGIS 2.16
*/
QString expressionDescription( int idx ) const;

/**
* Set the constraint expression description for a specific field.
* @param idx The index of the field
* @param descr The description of the expression
* @note added in QGIS 2.16
*/
void setExpressionDescription( int idx, const QString &descr );

/**
* Returns if the field at fieldidx should be treated as NOT NULL value
*/
bool notNull( int fieldidx) const;
/**
* Set if the field at fieldidx should be treated as NOT NULL value
*/
void setNotNull( int idx, bool notnull = true );


/** /**
* If this returns true, the widget at the given index will receive its label on the previous line * If this returns true, the widget at the given index will receive its label on the previous line
Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsfield.sip
Expand Up @@ -165,7 +165,7 @@ class QgsField
/* Raise an exception if the arguments couldn't be parsed. */ /* Raise an exception if the arguments couldn't be parsed. */
sipNoMethod(sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible); sipNoMethod(sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible);


return NULL; return nullptr;
%End %End


//! Allows direct construction of QVariants from fields. //! Allows direct construction of QVariants from fields.
Expand Down
38 changes: 38 additions & 0 deletions python/gui/editorwidgets/core/qgseditorwidgetwrapper.sip
Expand Up @@ -88,6 +88,21 @@ class QgsEditorWidgetWrapper : QgsWidgetWrapper
*/ */
virtual void showIndeterminateState(); virtual void showIndeterminateState();


/**
* Update constraint.
* @param featureContext the feature to use to evaluate the constraint
* @note added in QGIS 2.16
*/
void updateConstraint( const QgsFeature &featureContext );

/**
* Get the current constraint status.
* @return true if the constraint is valid or if there's not constraint,
* false otherwise
* @note added in QGIS 2.16
*/
bool isValidConstraint() const;

signals: signals:
/** /**
* Emit this signal, whenever the value changed. * Emit this signal, whenever the value changed.
Expand All @@ -96,6 +111,16 @@ class QgsEditorWidgetWrapper : QgsWidgetWrapper
*/ */
void valueChanged( const QVariant& value ); void valueChanged( const QVariant& value );


/**
* Emit this signal when the constraint status changed.
* @brief constraintStatusChanged
* @param constraint represented as a string
* @param desc is the constraint description
* @param err the error represented as a string. Empty if none.
* @param status
*/
void constraintStatusChanged( const QString& constraint, const QString& err, bool status );

public slots: public slots:
/** /**
* Will be called when the feature changes * Will be called when the feature changes
Expand Down Expand Up @@ -162,4 +187,17 @@ class QgsEditorWidgetWrapper : QgsWidgetWrapper
* Will call the value() method to determine the emitted value * Will call the value() method to determine the emitted value
*/ */
void valueChanged(); void valueChanged();

protected:
/**
* This should update the widget with a visual cue if a constraint status
* changed.
*
* By default a stylesheet will be applied on the widget that changes the
* background color to red.
*
* This can be overwritten in subclasses to allow individual widgets to
* change the visual cue.
*/
virtual void updateConstraintWidgetStatus();
}; };
14 changes: 14 additions & 0 deletions python/gui/editorwidgets/qgsrelationreferencewidgetwrapper.sip
Expand Up @@ -21,4 +21,18 @@ class QgsRelationReferenceWidgetWrapper : QgsEditorWidgetWrapper
public slots: public slots:
virtual void setValue( const QVariant& value ); virtual void setValue( const QVariant& value );
virtual void setEnabled( bool enabled ); virtual void setEnabled( bool enabled );

protected:
/**
* This should update the widget with a visual cue if a constraint status
* changed.
*
* By default a stylesheet will be applied on the widget that changes the
* background color to red.
*
* This can be overwritten in subclasses to allow individual widgets to
* change the visual cue.
* @note added in QGIS 2.16
*/
void updateConstraintWidgetStatus();
}; };
36 changes: 34 additions & 2 deletions src/app/qgsattributetypedialog.cpp
Expand Up @@ -71,6 +71,8 @@ QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl, int fieldIdx


QSettings settings; QSettings settings;
restoreGeometry( settings.value( "/Windows/QgsAttributeTypeDialog/geometry" ).toByteArray() ); restoreGeometry( settings.value( "/Windows/QgsAttributeTypeDialog/geometry" ).toByteArray() );

constraintExpression->setLayer( vl );
} }


QgsAttributeTypeDialog::~QgsAttributeTypeDialog() QgsAttributeTypeDialog::~QgsAttributeTypeDialog()
Expand Down Expand Up @@ -163,16 +165,46 @@ void QgsAttributeTypeDialog::setWidgetV2Config( const QgsEditorWidgetConfig& con
mWidgetV2Config = config; mWidgetV2Config = config;
} }


bool QgsAttributeTypeDialog::fieldEditable() bool QgsAttributeTypeDialog::fieldEditable() const
{ {
return isFieldEditableCheckBox->isChecked(); return isFieldEditableCheckBox->isChecked();
} }


bool QgsAttributeTypeDialog::labelOnTop() void QgsAttributeTypeDialog::setNotNull( bool notNull )
{
notNullCheckBox->setChecked( notNull );
}

bool QgsAttributeTypeDialog::labelOnTop() const
{ {
return labelOnTopCheckBox->isChecked(); return labelOnTopCheckBox->isChecked();
} }


void QgsAttributeTypeDialog::setExpressionDescription( const QString &desc )
{
constraintExpressionDescription->setText( desc );
}

QString QgsAttributeTypeDialog::expressionDescription()
{
return constraintExpressionDescription->text();
}

bool QgsAttributeTypeDialog::notNull() const
{
return notNullCheckBox->isChecked();
}

void QgsAttributeTypeDialog::setExpression( const QString &str )
{
constraintExpression->setField( str );
}

QString QgsAttributeTypeDialog::expression() const
{
return constraintExpression->asExpression();
}

void QgsAttributeTypeDialog::setFieldEditable( bool editable ) void QgsAttributeTypeDialog::setFieldEditable( bool editable )
{ {
isFieldEditableCheckBox->setChecked( editable ); isFieldEditableCheckBox->setChecked( editable );
Expand Down
42 changes: 39 additions & 3 deletions src/app/qgsattributetypedialog.h
Expand Up @@ -69,6 +69,11 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
*/ */
void setLabelOnTop( bool onTop ); void setLabelOnTop( bool onTop );


/**
* Getter for checkbox for label on top of field
*/
bool labelOnTop() const;

/** /**
* Setter for checkbox for editable state of field * Setter for checkbox for editable state of field
*/ */
Expand All @@ -77,12 +82,43 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
/** /**
* Getter for checkbox for editable state of field * Getter for checkbox for editable state of field
*/ */
bool fieldEditable(); bool fieldEditable() const;


/** /**
* Getter for checkbox for label on top of field * Setter for checkbox for not null
*/
void setNotNull( bool notNull );

/**
* Getter for checkbox for not null
*/
bool notNull() const;

/*
* Setter for constraint expression description
* @param desc the expression description
* @note added in QGIS 2.16
**/
void setExpressionDescription( const QString &desc );

/*
* Getter for constraint expression description
* @return the expression description
* @note added in QGIS 2.16
**/
QString expressionDescription();

/**
* Getter for the constraint expression
* @note added in QGIS 2.16
*/
QString expression() const;

/**
* Setter for the constraint expression
* @note added in QGIS 2.16
*/ */
bool labelOnTop(); void setExpression( const QString &str );


private slots: private slots:
/** /**
Expand Down
14 changes: 14 additions & 0 deletions src/app/qgsfieldsproperties.cpp
Expand Up @@ -527,6 +527,9 @@ void QgsFieldsProperties::attributeTypeDialog()


attributeTypeDialog.setFieldEditable( cfg.mEditable ); attributeTypeDialog.setFieldEditable( cfg.mEditable );
attributeTypeDialog.setLabelOnTop( cfg.mLabelOnTop ); attributeTypeDialog.setLabelOnTop( cfg.mLabelOnTop );
attributeTypeDialog.setNotNull( cfg.mNotNull );
attributeTypeDialog.setExpression( cfg.mConstraint );
attributeTypeDialog.setExpressionDescription( cfg.mConstraintDescription );


attributeTypeDialog.setWidgetV2Config( cfg.mEditorWidgetV2Config ); attributeTypeDialog.setWidgetV2Config( cfg.mEditorWidgetV2Config );
attributeTypeDialog.setWidgetV2Type( cfg.mEditorWidgetV2Type ); attributeTypeDialog.setWidgetV2Type( cfg.mEditorWidgetV2Type );
Expand All @@ -536,6 +539,9 @@ void QgsFieldsProperties::attributeTypeDialog()


cfg.mEditable = attributeTypeDialog.fieldEditable(); cfg.mEditable = attributeTypeDialog.fieldEditable();
cfg.mLabelOnTop = attributeTypeDialog.labelOnTop(); cfg.mLabelOnTop = attributeTypeDialog.labelOnTop();
cfg.mNotNull = attributeTypeDialog.notNull();
cfg.mConstraintDescription = attributeTypeDialog.expressionDescription();
cfg.mConstraint = attributeTypeDialog.expression();


cfg.mEditorWidgetV2Type = attributeTypeDialog.editorWidgetV2Type(); cfg.mEditorWidgetV2Type = attributeTypeDialog.editorWidgetV2Type();
cfg.mEditorWidgetV2Config = attributeTypeDialog.editorWidgetV2Config(); cfg.mEditorWidgetV2Config = attributeTypeDialog.editorWidgetV2Config();
Expand Down Expand Up @@ -908,6 +914,9 @@ void QgsFieldsProperties::apply()


mLayer->editFormConfig()->setReadOnly( i, !cfg.mEditable ); mLayer->editFormConfig()->setReadOnly( i, !cfg.mEditable );
mLayer->editFormConfig()->setLabelOnTop( i, cfg.mLabelOnTop ); mLayer->editFormConfig()->setLabelOnTop( i, cfg.mLabelOnTop );
mLayer->editFormConfig()->setNotNull( i, cfg.mNotNull );
mLayer->editFormConfig()->setExpressionDescription( i, cfg.mConstraintDescription );
mLayer->editFormConfig()->setExpression( i, cfg.mConstraint );


mLayer->editFormConfig()->setWidgetType( idx, cfg.mEditorWidgetV2Type ); mLayer->editFormConfig()->setWidgetType( idx, cfg.mEditorWidgetV2Type );
mLayer->editFormConfig()->setWidgetConfig( idx, cfg.mEditorWidgetV2Config ); mLayer->editFormConfig()->setWidgetConfig( idx, cfg.mEditorWidgetV2Config );
Expand Down Expand Up @@ -974,6 +983,8 @@ QgsFieldsProperties::FieldConfig::FieldConfig()
: mEditable( true ) : mEditable( true )
, mEditableEnabled( true ) , mEditableEnabled( true )
, mLabelOnTop( false ) , mLabelOnTop( false )
, mNotNull( false )
, mConstraintDescription( QString() )
, mButton( nullptr ) , mButton( nullptr )
{ {
} }
Expand All @@ -985,6 +996,9 @@ QgsFieldsProperties::FieldConfig::FieldConfig( QgsVectorLayer* layer, int idx )
mEditableEnabled = layer->fields().fieldOrigin( idx ) != QgsFields::OriginJoin mEditableEnabled = layer->fields().fieldOrigin( idx ) != QgsFields::OriginJoin
&& layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression; && layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression;
mLabelOnTop = layer->editFormConfig()->labelOnTop( idx ); mLabelOnTop = layer->editFormConfig()->labelOnTop( idx );
mNotNull = layer->editFormConfig()->notNull( idx );
mConstraint = layer->editFormConfig()->expression( idx );
mConstraintDescription = layer->editFormConfig()->expressionDescription( idx );
mEditorWidgetV2Type = layer->editFormConfig()->widgetType( idx ); mEditorWidgetV2Type = layer->editFormConfig()->widgetType( idx );
mEditorWidgetV2Config = layer->editFormConfig()->widgetConfig( idx ); mEditorWidgetV2Config = layer->editFormConfig()->widgetConfig( idx );


Expand Down
3 changes: 3 additions & 0 deletions src/app/qgsfieldsproperties.h
Expand Up @@ -92,6 +92,9 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
bool mEditable; bool mEditable;
bool mEditableEnabled; bool mEditableEnabled;
bool mLabelOnTop; bool mLabelOnTop;
bool mNotNull;
QString mConstraint;
QString mConstraintDescription;
QPushButton* mButton; QPushButton* mButton;
QString mEditorWidgetV2Type; QString mEditorWidgetV2Type;
QMap<QString, QVariant> mEditorWidgetV2Config; QMap<QString, QVariant> mEditorWidgetV2Config;
Expand Down
48 changes: 47 additions & 1 deletion src/core/qgseditformconfig.cpp
Expand Up @@ -119,6 +119,46 @@ bool QgsEditFormConfig::labelOnTop( int idx ) const
return false; return false;
} }


QString QgsEditFormConfig::expression( int idx ) const
{
QString expr;

if ( idx >= 0 && idx < mFields.count() )
expr = mConstraints.value( mFields.at( idx ).name(), QString() );

return expr;
}

void QgsEditFormConfig::setExpression( int idx, const QString& str )
{
if ( idx >= 0 && idx < mFields.count() )
mConstraints[ mFields.at( idx ).name()] = str;
}

QString QgsEditFormConfig::expressionDescription( int idx ) const
{
QString description;

if ( idx >= 0 && idx < mFields.count() )
description = mConstraintsDescription[ mFields.at( idx ).name()];

return description;
}

void QgsEditFormConfig::setExpressionDescription( int idx, const QString &descr )
{
if ( idx >= 0 && idx < mFields.count() )
mConstraintsDescription[ mFields.at( idx ).name()] = descr;
}

bool QgsEditFormConfig::notNull( int idx ) const
{
if ( idx >= 0 && idx < mFields.count() )
return mNotNull.value( mFields.at( idx ).name(), false );
else
return false;
}

void QgsEditFormConfig::setReadOnly( int idx, bool readOnly ) void QgsEditFormConfig::setReadOnly( int idx, bool readOnly )
{ {
if ( idx >= 0 && idx < mFields.count() ) if ( idx >= 0 && idx < mFields.count() )
Expand All @@ -131,6 +171,12 @@ void QgsEditFormConfig::setLabelOnTop( int idx, bool onTop )
mLabelOnTop[ mFields.at( idx ).name()] = onTop; mLabelOnTop[ mFields.at( idx ).name()] = onTop;
} }


void QgsEditFormConfig::setNotNull( int idx, bool notnull )
{
if ( idx >= 0 && idx < mFields.count() )
mNotNull[ mFields.at( idx ).name()] = notnull;
}

void QgsEditFormConfig::readXml( const QDomNode& node ) void QgsEditFormConfig::readXml( const QDomNode& node )
{ {
QDomNode editFormNode = node.namedItem( "editform" ); QDomNode editFormNode = node.namedItem( "editform" );
Expand Down Expand Up @@ -280,7 +326,6 @@ void QgsEditFormConfig::writeXml( QDomNode& node ) const
efifpField.appendChild( doc.createTextNode( QgsProject::instance()->writePath( initFilePath() ) ) ); efifpField.appendChild( doc.createTextNode( QgsProject::instance()->writePath( initFilePath() ) ) );
node.appendChild( efifpField ); node.appendChild( efifpField );



QDomElement eficField = doc.createElement( "editforminitcode" ); QDomElement eficField = doc.createElement( "editforminitcode" );
eficField.appendChild( doc.createCDATASection( initCode() ) ); eficField.appendChild( doc.createCDATASection( initCode() ) );
node.appendChild( eficField ); node.appendChild( eficField );
Expand Down Expand Up @@ -337,6 +382,7 @@ void QgsEditFormConfig::writeXml( QDomNode& node ) const
{ {
QDomElement widgetElem = doc.createElement( "widget" ); QDomElement widgetElem = doc.createElement( "widget" );
widgetElem.setAttribute( "name", configIt.key() ); widgetElem.setAttribute( "name", configIt.key() );
// widgetElem.setAttribute( "notNull", );


QDomElement configElem = doc.createElement( "config" ); QDomElement configElem = doc.createElement( "config" );
widgetElem.appendChild( configElem ); widgetElem.appendChild( configElem );
Expand Down

0 comments on commit 2b1560c

Please sign in to comment.