diff --git a/python/core/qgseditformconfig.sip b/python/core/qgseditformconfig.sip index 06ecdc39d647..4148ac1127d5 100644 --- a/python/core/qgseditformconfig.sip +++ b/python/core/qgseditformconfig.sip @@ -474,7 +474,16 @@ class QgsEditFormConfig : QObject /** * 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 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 diff --git a/python/core/qgsfield.sip b/python/core/qgsfield.sip index ce63bdc41f2d..a1bd42eef03f 100644 --- a/python/core/qgsfield.sip +++ b/python/core/qgsfield.sip @@ -165,7 +165,7 @@ class QgsField /* Raise an exception if the arguments couldn't be parsed. */ sipNoMethod(sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible); - return NULL; + return nullptr; %End //! Allows direct construction of QVariants from fields. diff --git a/src/app/qgsattributetypedialog.cpp b/src/app/qgsattributetypedialog.cpp index 1d45831f3e44..0ed4bef46a84 100644 --- a/src/app/qgsattributetypedialog.cpp +++ b/src/app/qgsattributetypedialog.cpp @@ -163,16 +163,26 @@ void QgsAttributeTypeDialog::setWidgetV2Config( const QgsEditorWidgetConfig& con mWidgetV2Config = config; } -bool QgsAttributeTypeDialog::fieldEditable() +bool QgsAttributeTypeDialog::fieldEditable() const { return isFieldEditableCheckBox->isChecked(); } -bool QgsAttributeTypeDialog::labelOnTop() +void QgsAttributeTypeDialog::setNotNull( bool notnull ) +{ + notNullCheckBox->setChecked( notnull ); +} + +bool QgsAttributeTypeDialog::labelOnTop() const { return labelOnTopCheckBox->isChecked(); } +bool QgsAttributeTypeDialog::notNull() const +{ + return notNullCheckBox->isChecked(); +} + void QgsAttributeTypeDialog::setFieldEditable( bool editable ) { isFieldEditableCheckBox->setChecked( editable ); diff --git a/src/app/qgsattributetypedialog.h b/src/app/qgsattributetypedialog.h index 578d2a003191..6ed6d73a7536 100644 --- a/src/app/qgsattributetypedialog.h +++ b/src/app/qgsattributetypedialog.h @@ -69,6 +69,11 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut */ void setLabelOnTop( bool onTop ); + /** + * Getter for checkbox for label on top of field + */ + bool labelOnTop() const; + /** * Setter for checkbox for editable state of field */ @@ -77,12 +82,17 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut /** * Getter for checkbox for editable state of field */ - bool fieldEditable(); + bool fieldEditable() const; /** - * Getter for checkbox for label on top of field + * Getter for checkbox for not null + */ + void setNotNull( bool notnull ); + + /** + * Getter for checkbox for not null */ - bool labelOnTop(); + bool notNull() const; private slots: /** diff --git a/src/app/qgsfieldsproperties.cpp b/src/app/qgsfieldsproperties.cpp index 9278c5581c66..03c38ad51a57 100644 --- a/src/app/qgsfieldsproperties.cpp +++ b/src/app/qgsfieldsproperties.cpp @@ -527,6 +527,7 @@ void QgsFieldsProperties::attributeTypeDialog() attributeTypeDialog.setFieldEditable( cfg.mEditable ); attributeTypeDialog.setLabelOnTop( cfg.mLabelOnTop ); + attributeTypeDialog.setNotNull( cfg.mNotNull ); attributeTypeDialog.setWidgetV2Config( cfg.mEditorWidgetV2Config ); attributeTypeDialog.setWidgetV2Type( cfg.mEditorWidgetV2Type ); @@ -536,6 +537,7 @@ void QgsFieldsProperties::attributeTypeDialog() cfg.mEditable = attributeTypeDialog.fieldEditable(); cfg.mLabelOnTop = attributeTypeDialog.labelOnTop(); + cfg.mNotNull = attributeTypeDialog.notNull(); cfg.mEditorWidgetV2Type = attributeTypeDialog.editorWidgetV2Type(); cfg.mEditorWidgetV2Config = attributeTypeDialog.editorWidgetV2Config(); @@ -908,6 +910,7 @@ void QgsFieldsProperties::apply() mLayer->editFormConfig()->setReadOnly( i, !cfg.mEditable ); mLayer->editFormConfig()->setLabelOnTop( i, cfg.mLabelOnTop ); + mLayer->editFormConfig()->setNotNull( i, cfg.mNotNull ); mLayer->editFormConfig()->setWidgetType( idx, cfg.mEditorWidgetV2Type ); mLayer->editFormConfig()->setWidgetConfig( idx, cfg.mEditorWidgetV2Config ); @@ -974,6 +977,7 @@ QgsFieldsProperties::FieldConfig::FieldConfig() : mEditable( true ) , mEditableEnabled( true ) , mLabelOnTop( false ) + , mNotNull( false ) , mButton( nullptr ) { } @@ -985,6 +989,7 @@ QgsFieldsProperties::FieldConfig::FieldConfig( QgsVectorLayer* layer, int idx ) mEditableEnabled = layer->fields().fieldOrigin( idx ) != QgsFields::OriginJoin && layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression; mLabelOnTop = layer->editFormConfig()->labelOnTop( idx ); + mNotNull = layer->editFormConfig()->notNull( idx ); mEditorWidgetV2Type = layer->editFormConfig()->widgetType( idx ); mEditorWidgetV2Config = layer->editFormConfig()->widgetConfig( idx ); diff --git a/src/app/qgsfieldsproperties.h b/src/app/qgsfieldsproperties.h index 2189e862a212..ae53b3d0bf1b 100644 --- a/src/app/qgsfieldsproperties.h +++ b/src/app/qgsfieldsproperties.h @@ -92,6 +92,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope bool mEditable; bool mEditableEnabled; bool mLabelOnTop; + bool mNotNull; QPushButton* mButton; QString mEditorWidgetV2Type; QMap mEditorWidgetV2Config; diff --git a/src/core/qgseditformconfig.cpp b/src/core/qgseditformconfig.cpp index 4c9279010655..e98deda8afda 100644 --- a/src/core/qgseditformconfig.cpp +++ b/src/core/qgseditformconfig.cpp @@ -119,6 +119,14 @@ bool QgsEditFormConfig::labelOnTop( int idx ) const return false; } +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 ) { if ( idx >= 0 && idx < mFields.count() ) @@ -131,6 +139,12 @@ void QgsEditFormConfig::setLabelOnTop( int idx, bool 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 ) { QDomNode editFormNode = node.namedItem( "editform" ); @@ -280,7 +294,6 @@ void QgsEditFormConfig::writeXml( QDomNode& node ) const efifpField.appendChild( doc.createTextNode( QgsProject::instance()->writePath( initFilePath() ) ) ); node.appendChild( efifpField ); - QDomElement eficField = doc.createElement( "editforminitcode" ); eficField.appendChild( doc.createCDATASection( initCode() ) ); node.appendChild( eficField ); @@ -337,6 +350,7 @@ void QgsEditFormConfig::writeXml( QDomNode& node ) const { QDomElement widgetElem = doc.createElement( "widget" ); widgetElem.setAttribute( "name", configIt.key() ); + // widgetElem.setAttribute( "notNull", ); QDomElement configElem = doc.createElement( "config" ); widgetElem.appendChild( configElem ); diff --git a/src/core/qgseditformconfig.h b/src/core/qgseditformconfig.h index 65e8689f6bb4..f34e7100859d 100644 --- a/src/core/qgseditformconfig.h +++ b/src/core/qgseditformconfig.h @@ -512,6 +512,15 @@ class CORE_EXPORT QgsEditFormConfig : public QObject */ void setReadOnly( int idx, bool readOnly = true ); + /** + * 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 * while if it returns false, the widget will receive its label on the left hand side. @@ -633,6 +642,7 @@ class CORE_EXPORT QgsEditFormConfig : public QObject QMap< QString, bool> mFieldEditables; QMap< QString, bool> mLabelOnTop; + QMap< QString, bool> mNotNull; QMap mEditorWidgetV2Types; QMap mWidgetConfigs; diff --git a/src/core/qgseditorwidgetconfig.h b/src/core/qgseditorwidgetconfig.h index a6dbceefb019..b9fdabdb4ad1 100644 --- a/src/core/qgseditorwidgetconfig.h +++ b/src/core/qgseditorwidgetconfig.h @@ -16,6 +16,8 @@ #include #include +#ifndef QGSEDITORWIDGETCONFIG_H +#define QGSEDITORWIDGETCONFIG_H /** * Holds a set of configuration parameters for a editor widget wrapper. @@ -30,4 +32,6 @@ * You get these passed, for every new widget wrapper. */ -typedef QMap QgsEditorWidgetConfig; +typedef QVariantMap QgsEditorWidgetConfig; + +#endif // QGSEDITORWIDGETCONFIG_H diff --git a/src/core/qgsfeature.cpp b/src/core/qgsfeature.cpp index 0cef3ee28691..c71ff8241f1a 100644 --- a/src/core/qgsfeature.cpp +++ b/src/core/qgsfeature.cpp @@ -288,6 +288,12 @@ int QgsFeature::fieldNameIndex( const QString& fieldName ) const return d->fields.fieldNameIndex( fieldName ); } +/*************************************************************************** + * This class is considered CRITICAL and any change MUST be accompanied with + * full unit tests in testqgsfeature.cpp. + * See details in QEP #17 + ****************************************************************************/ + QDataStream& operator<<( QDataStream& out, const QgsFeature& feature ) { out << feature.id(); diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index e1fa901b6947..b025b4aa5af2 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -1105,13 +1105,13 @@ QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request } -bool QgsVectorLayer::addFeature( QgsFeature& f, bool alsoUpdateExtent ) +bool QgsVectorLayer::addFeature( QgsFeature& feature, bool alsoUpdateExtent ) { Q_UNUSED( alsoUpdateExtent ); // TODO[MD] if ( !mValid || !mEditBuffer || !mDataProvider ) return false; - bool success = mEditBuffer->addFeature( f ); + bool success = mEditBuffer->addFeature( feature ); if ( success ) updateExtents(); diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index ee902cb6ef53..3adb15401af7 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -975,11 +975,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer QgsFeatureIterator getFeatures( const QgsFeatureRequest& request = QgsFeatureRequest() ); /** Adds a feature - @param f feature to add + @param feature feature to add @param alsoUpdateExtent If True, will also go to the effort of e.g. updating the extents. @return True in case of success and False in case of error */ - bool addFeature( QgsFeature& f, bool alsoUpdateExtent = true ); + bool addFeature( QgsFeature& feature, bool alsoUpdateExtent = true ); /** Updates an existing feature. This method needs to query the datasource on every call. Consider using {@link changeAttributeValue()} or diff --git a/src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp b/src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp index 63184a75620c..9dc1116157e6 100644 --- a/src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp +++ b/src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp @@ -251,6 +251,7 @@ void QgsEditorWidgetRegistry::readMapLayer( QgsMapLayer* mapLayer, const QDomEle vectorLayer->editFormConfig()->setReadOnly( idx, ewv2CfgElem.attribute( "fieldEditable", "1" ) != "1" ); vectorLayer->editFormConfig()->setLabelOnTop( idx, ewv2CfgElem.attribute( "labelOnTop", "0" ) == "1" ); + vectorLayer->editFormConfig()->setNotNull( idx, ewv2CfgElem.attribute( "notNull", "0" ) == "1" ); vectorLayer->editFormConfig()->setWidgetConfig( idx, cfg ); } else @@ -307,6 +308,7 @@ void QgsEditorWidgetRegistry::writeMapLayer( QgsMapLayer* mapLayer, QDomElement& QDomElement ewv2CfgElem = doc.createElement( "widgetv2config" ); ewv2CfgElem.setAttribute( "fieldEditable", !vectorLayer->editFormConfig()->readOnly( idx ) ); ewv2CfgElem.setAttribute( "labelOnTop", vectorLayer->editFormConfig()->labelOnTop( idx ) ); + ewv2CfgElem.setAttribute( "notNull", vectorLayer->editFormConfig()->notNull( idx ) ); mWidgetFactories[widgetType]->writeConfig( vectorLayer->editFormConfig()->widgetConfig( idx ), ewv2CfgElem, doc, vectorLayer, idx ); diff --git a/src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp b/src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp index 79e23a8a7ce0..403795f243b0 100644 --- a/src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp +++ b/src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp @@ -24,6 +24,7 @@ QgsEditorWidgetWrapper::QgsEditorWidgetWrapper( QgsVectorLayer* vl, int fieldIdx : QgsWidgetWrapper( vl, editor, parent ) , mFieldIdx( fieldIdx ) { + connect( this, SIGNAL( valueChanged( QVariant ) ), this, SLOT( onValueChanged( QVariant ) ) ); } int QgsEditorWidgetWrapper::fieldIdx() const @@ -61,6 +62,7 @@ void QgsEditorWidgetWrapper::setEnabled( bool enabled ) void QgsEditorWidgetWrapper::setFeature( const QgsFeature& feature ) { setValue( feature.attribute( mFieldIdx ) ); + onValueChanged( value() ); } void QgsEditorWidgetWrapper::valueChanged( const QString& value ) @@ -92,3 +94,28 @@ void QgsEditorWidgetWrapper::valueChanged() { emit valueChanged( value() ); } + +void QgsEditorWidgetWrapper::updateConstraintsOk( bool constraintStatus ) +{ + if ( constraintStatus ) + { + widget()->setStyleSheet( "" ); + } + else + { + widget()->setStyleSheet( "QWidget{ background-color: '#dd7777': }" ); + } +} + +void QgsEditorWidgetWrapper::onValueChanged( const QVariant& value ) +{ + if ( layer()->editFormConfig()->notNull( mFieldIdx ) ) + { + if ( value.isNull() != mIsNull ) + { + updateConstraintsOk( value.isNull() ); + emit constraintStatusChanged( "NotNull", !value.isNull() ); + mIsNull = value.isNull(); + } + } +} diff --git a/src/gui/editorwidgets/core/qgseditorwidgetwrapper.h b/src/gui/editorwidgets/core/qgseditorwidgetwrapper.h index ad30e2ad8797..182f0ecb244d 100644 --- a/src/gui/editorwidgets/core/qgseditorwidgetwrapper.h +++ b/src/gui/editorwidgets/core/qgseditorwidgetwrapper.h @@ -118,6 +118,13 @@ class GUI_EXPORT QgsEditorWidgetWrapper : public QgsWidgetWrapper */ void valueChanged( const QVariant& value ); + /** + * @brief constraintStatusChanged + * @param constraint + * @param status + */ + void constraintStatusChanged( const QString& constraint, bool status ); + public slots: /** * Will be called when the feature changes @@ -185,8 +192,28 @@ class GUI_EXPORT QgsEditorWidgetWrapper : public QgsWidgetWrapper */ void valueChanged(); + private: + /** + * 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 updateConstraintsOk( bool constraintStatus ); + + private slots: + /** + * @brief mFieldIdx + */ + void onValueChanged( const QVariant& value ); + private: int mFieldIdx; + bool mIsNull; }; // We'll use this class inside a QVariant in the widgets properties diff --git a/src/gui/editorwidgets/qgsrangewidgetfactory.cpp b/src/gui/editorwidgets/qgsrangewidgetfactory.cpp index 9ef096d5c381..dbda88b42b79 100644 --- a/src/gui/editorwidgets/qgsrangewidgetfactory.cpp +++ b/src/gui/editorwidgets/qgsrangewidgetfactory.cpp @@ -38,7 +38,7 @@ QgsEditorWidgetConfig QgsRangeWidgetFactory::readConfig( const QDomElement& conf { Q_UNUSED( layer ); Q_UNUSED( fieldIdx ); - QMap cfg; + QgsEditorWidgetConfig cfg; cfg.insert( "Style", configElement.attribute( "Style" ) ); cfg.insert( "Min", configElement.attribute( "Min" ) ); diff --git a/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp b/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp index 2c59588e075f..6b58462561d7 100644 --- a/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp +++ b/src/gui/editorwidgets/qgsrelationreferenceconfigdlg.cpp @@ -55,7 +55,7 @@ QgsRelationReferenceConfigDlg::QgsRelationReferenceConfigDlg( QgsVectorLayer* vl } } -void QgsRelationReferenceConfigDlg::setConfig( const QMap& config ) +void QgsRelationReferenceConfigDlg::setConfig( const QgsEditorWidgetConfig& config ) { if ( config.contains( "AllowNULL" ) ) { diff --git a/src/gui/editorwidgets/qgsrelationreferencefactory.cpp b/src/gui/editorwidgets/qgsrelationreferencefactory.cpp index 9315d14eb03a..b6cf3438535f 100644 --- a/src/gui/editorwidgets/qgsrelationreferencefactory.cpp +++ b/src/gui/editorwidgets/qgsrelationreferencefactory.cpp @@ -46,7 +46,7 @@ QgsEditorWidgetConfig QgsRelationReferenceFactory::readConfig( const QDomElement { Q_UNUSED( layer ); Q_UNUSED( fieldIdx ); - QMap cfg; + QgsEditorWidgetConfig cfg; cfg.insert( "AllowNULL", configElement.attribute( "AllowNULL" ) == "1" ); cfg.insert( "OrderByValue", configElement.attribute( "OrderByValue" ) == "1" ); diff --git a/src/gui/qgsattributeform.cpp b/src/gui/qgsattributeform.cpp index ea65e175451a..9a31e6f76d56 100644 --- a/src/gui/qgsattributeform.cpp +++ b/src/gui/qgsattributeform.cpp @@ -655,6 +655,41 @@ void QgsAttributeForm::onAttributeChanged( const QVariant& value ) //nothing to do break; } + + if ( eww->layer()->editFormConfig()->notNull( eww->fieldIdx() ) ) + { + QLabel* buddy = mBuddyMap.value( eww->widget() ); + + if ( buddy ) + { + if ( !buddy->property( "originalText" ).isValid() ) + buddy->setProperty( "originalText", buddy->text() ); + + QString text = buddy->property( "originalText" ).toString(); + + if ( value.isNull() ) + { + // not good +#if QT_VERSION >= 0x050000 + buddy->setText( QString( "%1" ).arg( text ) ); +#else + buddy->setText( QString( "%1*" ).arg( text ) ); +#endif + } + else + { + // good +#if QT_VERSION >= 0x050000 + buddy->setText( QString( "%1" ).arg( text ) ); +#else + buddy->setText( QString( "%1*" ).arg( text ) ); +#endif + } + } + } + + + emit attributeChanged( eww->field().name(), value ); } void QgsAttributeForm::onAttributeAdded( int idx ) @@ -714,6 +749,36 @@ void QgsAttributeForm::onUpdatedFields() setFeature( mFeature ); } +void QgsAttributeForm::onConstraintStatusChanged( const QString& constraint, bool ok ) +{ + Q_UNUSED( constraint ) + + + QgsEditorWidgetWrapper* eww = qobject_cast( sender() ); + Q_ASSERT( eww ); + + QLabel* buddy = mBuddyMap.value( eww->widget() ); + + if ( buddy ) + { + if ( !buddy->property( "originalText" ).isValid() ) + buddy->setProperty( "originalText", buddy->text() ); + + QString text = buddy->property( "originalText" ).toString(); + + if ( !ok ) + { + // not good + buddy->setText( QString( "%1*" ).arg( text ) ); + } + else + { + // good + buddy->setText( QString( "%1*" ).arg( text ) ); + } + } +} + void QgsAttributeForm::preventFeatureRefresh() { mPreventFeatureRefresh = true; @@ -899,7 +964,7 @@ void QgsAttributeForm::init() bool labelOnTop = mLayer->editFormConfig()->labelOnTop( idx ); // This will also create the widget - QWidget *l = new QLabel( fieldName ); + QLabel *l = new QLabel( fieldName ); QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, mLayer, idx, widgetConfig, nullptr, this, mContext ); QWidget* w = nullptr; @@ -915,6 +980,11 @@ void QgsAttributeForm::init() w = new QLabel( QString( "

Failed to create widget with type '%1'

" ).arg( widgetType ) ); } + l->setBuddy( w ); + + if ( w ) + w->setObjectName( field.name() ); + if ( eww ) addWidgetWrapper( eww ); @@ -957,6 +1027,7 @@ void QgsAttributeForm::init() } mButtonBox->setVisible( buttonBoxVisible ); +<<<<<<< HEAD if ( !mSearchButtonBox ) { mSearchButtonBox = new QWidget(); @@ -1011,7 +1082,7 @@ void QgsAttributeForm::init() } mSearchButtonBox->setVisible( mMode == SearchMode ); - connectWrappers(); + afterWidgetInit(); connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) ); connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( resetValues() ) ); @@ -1251,6 +1322,8 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt mypLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); } + mypLabel->setBuddy( widgetInfo.widget ); + if ( widgetInfo.labelOnTop ) { QVBoxLayout* c = new QVBoxLayout(); @@ -1350,7 +1423,7 @@ void QgsAttributeForm::createWrappers() } } -void QgsAttributeForm::connectWrappers() +void QgsAttributeForm::afterWidgetInit() { bool isFirstEww = true; @@ -1367,8 +1440,20 @@ void QgsAttributeForm::connectWrappers() } connect( eww, SIGNAL( valueChanged( const QVariant& ) ), this, SLOT( onAttributeChanged( const QVariant& ) ) ); + connect( eww, SIGNAL( constraintStatusChanged( QString, bool ) ), this, SLOT( onConstraintStatusChanged( QString, bool ) ) ); } } + + // Update buddy widget list + + mBuddyMap.clear(); + QList labels = findChildren(); + + Q_FOREACH ( QLabel* label, labels ) + { + if ( label->buddy() ) + mBuddyMap.insert( label->buddy(), label ); + } } diff --git a/src/gui/qgsattributeform.h b/src/gui/qgsattributeform.h index 89770ebc2886..a49c6546a28a 100644 --- a/src/gui/qgsattributeform.h +++ b/src/gui/qgsattributeform.h @@ -21,6 +21,7 @@ #include "qgsattributeeditorcontext.h" #include +#include #include class QgsAttributeFormInterface; @@ -233,6 +234,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget void onAttributeAdded( int idx ); void onAttributeDeleted( int idx ); void onUpdatedFields(); + void onConstraintStatusChanged( const QString& constraint, bool ok ); void preventFeatureRefresh(); void synchronizeEnabledState(); @@ -282,7 +284,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget * Called once maximally. */ void createWrappers(); - void connectWrappers(); + void afterWidgetInit(); void scanForEqualAttributes( QgsFeatureIterator& fit, QSet< int >& mixedValueFields, QHash< int, QVariant >& fieldSharedValues ) const; @@ -330,6 +332,9 @@ class GUI_EXPORT QgsAttributeForm : public QWidget Mode mMode; + //! Backlinks widgets to buddies. + QMap mBuddyMap; + friend class TestQgsDualView; }; diff --git a/src/ui/qgsattributetypeedit.ui b/src/ui/qgsattributetypeedit.ui index 5f774a4adb82..adb2cb02bd8b 100644 --- a/src/ui/qgsattributetypeedit.ui +++ b/src/ui/qgsattributetypeedit.ui @@ -14,17 +14,7 @@ Edit Widget Properties - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + @@ -47,9 +37,26 @@ - + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Not Null + + +