Index: src/app/qgsattributetypedialog.h =================================================================== --- src/app/qgsattributetypedialog.h (revision 15691) +++ src/app/qgsattributetypedialog.h (working copy) @@ -78,6 +78,12 @@ void setCheckedState( QString checked, QString unchecked ); /** + * Setter to value relation to be displayed and edited in this dialog + * @param valueRelation value relation data which is to be displayed + */ + void setValueRelation( QgsVectorLayer::ValueRelationData valueRelationData ); + + /** * Getter for checked state after editing * @return string representing the checked */ @@ -95,6 +101,11 @@ */ QgsVectorLayer::RangeData rangeData(); + /** + * Getter for value relation data + */ + QgsVectorLayer::ValueRelationData valueRelationData(); + private slots: /** * Slot to handle change of index in combobox to select correct page @@ -124,6 +135,11 @@ */ void vCellChanged( int row, int column ); + /** + * update columns list + */ + void updateLayerColumns( int idx ); + private: QString defaultWindowTitle(); @@ -147,6 +163,7 @@ int mIndex; QgsVectorLayer::RangeData mRangeData; + QgsVectorLayer::ValueRelationData mValueRelationData; QgsVectorLayer::EditType mEditType; }; Index: src/app/qgsvectorlayerproperties.h =================================================================== --- src/app/qgsvectorlayerproperties.h (revision 15691) +++ src/app/qgsvectorlayerproperties.h (working copy) @@ -173,6 +173,7 @@ QMap mEditTypeMap; QMap > mValueMaps; QMap mRanges; + QMap mValueRelationData; QMap > mCheckedStates; QFont mDiagramFont; Index: src/app/qgsvectorlayerproperties.cpp =================================================================== --- src/app/qgsvectorlayerproperties.cpp (revision 15691) +++ src/app/qgsvectorlayerproperties.cpp (working copy) @@ -245,6 +245,7 @@ attributeTypeDialog.setValueMap( mValueMaps.value( index, layer->valueMap( index ) ) ); attributeTypeDialog.setRange( mRanges.value( index, layer->range( index ) ) ); + attributeTypeDialog.setValueRelation( mValueRelationData.value( index, layer->valueRelation( index ) ) ); QPair checkStates = mCheckedStates.value( index, layer->checkedState( index ) ); attributeTypeDialog.setCheckedState( checkStates.first, checkStates.second ); @@ -272,6 +273,9 @@ case QgsVectorLayer::CheckBox: mCheckedStates.insert( index, attributeTypeDialog.checkedState() ); break; + case QgsVectorLayer::ValueRelation: + mValueRelationData.insert( index, attributeTypeDialog.valueRelationData() ); + break; case QgsVectorLayer::LineEdit: case QgsVectorLayer::TextEdit: case QgsVectorLayer::UniqueValues: @@ -554,6 +558,7 @@ editTypeMap.insert( QgsVectorLayer::CheckBox, tr( "Checkbox" ) ); editTypeMap.insert( QgsVectorLayer::TextEdit, tr( "Text edit" ) ); editTypeMap.insert( QgsVectorLayer::Calendar, tr( "Calendar" ) ); + editTypeMap.insert( QgsVectorLayer::ValueRelation, tr( "Value relation" ) ); } QString QgsVectorLayerProperties::editTypeButtonText( QgsVectorLayer::EditType type ) @@ -635,6 +640,13 @@ } break; + case QgsVectorLayer::ValueRelation: + if ( mValueRelationData.contains( idx ) ) + { + layer->valueRelation( idx ) = mValueRelationData[idx]; + } + break; + case QgsVectorLayer::LineEdit: case QgsVectorLayer::UniqueValues: case QgsVectorLayer::UniqueValuesEditable: Index: src/app/qgsattributetypedialog.cpp =================================================================== --- src/app/qgsattributetypedialog.cpp (revision 15691) +++ src/app/qgsattributetypedialog.cpp (working copy) @@ -19,6 +19,7 @@ #include "qgsattributetypedialog.h" #include "qgsattributetypeloaddialog.h" #include "qgsvectordataprovider.h" +#include "qgsmaplayerregistry.h" #include "qgslogger.h" @@ -42,6 +43,17 @@ connect( loadFromLayerButton, SIGNAL( clicked() ), this, SLOT( loadFromLayerButtonPushed() ) ); connect( loadFromCSVButton, SIGNAL( clicked() ), this, SLOT( loadFromCSVButtonPushed() ) ); connect( tableWidget, SIGNAL( cellChanged( int, int ) ), this, SLOT( vCellChanged( int, int ) ) ); + + valueRelationLayer->clear(); + foreach( QgsMapLayer *l, QgsMapLayerRegistry::instance()->mapLayers() ) + { + QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( l ); + if ( vl ) + valueRelationLayer->addItem( vl->name(), vl->id() ); + } + + connect( valueRelationLayer, SIGNAL( currentIndexChanged( int ) ), this, SLOT( updateLayerColumns( int ) ) ); + valueRelationLayer->setCurrentIndex( -1 ); } QgsAttributeTypeDialog::~QgsAttributeTypeDialog() @@ -59,6 +71,11 @@ return mRangeData; } +QgsVectorLayer::ValueRelationData QgsAttributeTypeDialog::valueRelationData() +{ + return mValueRelationData; +} + QMap &QgsAttributeTypeDialog::valueMap() { return mValueMap; @@ -259,6 +276,10 @@ case QgsVectorLayer::Calendar: setPage( 11 ); break; + + case QgsVectorLayer::ValueRelation: + setPage( 12 ); + break; } } @@ -272,6 +293,11 @@ mRangeData = range; } +void QgsAttributeTypeDialog::setValueRelation( QgsVectorLayer::ValueRelationData valueRelation ) +{ + mValueRelationData = valueRelation; +} + void QgsAttributeTypeDialog::setIndex( int index, QgsVectorLayer::EditType editType ) { mIndex = index; @@ -397,6 +423,13 @@ editableUniqueValues->setChecked( editType == QgsVectorLayer::UniqueValuesEditable ); break; + case QgsVectorLayer::ValueRelation: + valueRelationLayer->setCurrentIndex( valueRelationLayer->findData( mValueRelationData.mLayer ) ); + valueRelationKeyColumn->setCurrentIndex( valueRelationKeyColumn->findText( mValueRelationData.mKey ) ); + valueRelationValueColumn->setCurrentIndex( valueRelationValueColumn->findText( mValueRelationData.mValue ) ); + valueRelationAllowNull->setChecked( mValueRelationData.mAllowNull ); + break; + case QgsVectorLayer::LineEdit: case QgsVectorLayer::UniqueValues: case QgsVectorLayer::Classification: @@ -559,6 +592,13 @@ case 11: mEditType = QgsVectorLayer::Calendar; break; + case 12: + mEditType = QgsVectorLayer::ValueRelation; + mValueRelationData.mLayer = valueRelationLayer->itemData( valueRelationLayer->currentIndex() ).toString(); + mValueRelationData.mKey = valueRelationKeyColumn->currentText(); + mValueRelationData.mValue = valueRelationValueColumn->currentText(); + mValueRelationData.mAllowNull = valueRelationAllowNull->isChecked(); + break; } QDialog::accept(); @@ -568,3 +608,24 @@ { return tr( "Attribute Edit Dialog" ); } + +void QgsAttributeTypeDialog::updateLayerColumns( int idx ) +{ + valueRelationKeyColumn->clear(); + valueRelationValueColumn->clear(); + + QString id = valueRelationLayer->itemData( idx ).toString(); + + QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( id ) ); + if ( !vl ) + return; + + foreach( const QgsField &f, vl->pendingFields() ) + { + valueRelationKeyColumn->addItem( f.name() ); + valueRelationValueColumn->addItem( f.name() ); + } + + valueRelationKeyColumn->setCurrentIndex( valueRelationKeyColumn->findText( mValueRelationData.mKey ) ); + valueRelationValueColumn->setCurrentIndex( valueRelationValueColumn->findText( mValueRelationData.mValue ) ); +} Index: src/gui/qgsattributeeditor.cpp =================================================================== --- src/gui/qgsattributeeditor.cpp (revision 15691) +++ src/gui/qgsattributeeditor.cpp (working copy) @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,47 @@ } break; + case QgsVectorLayer::ValueRelation: + { + QSettings settings; + QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString(); + + const QgsVectorLayer::ValueRelationData &data = vl->valueRelation( idx ); + + QgsVectorLayer *layer = qobject_cast( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) ); + QMap< QString, QString > map; + if ( layer ) + { + int ki = layer->fieldNameIndex( data.mKey ); + int vi = layer->fieldNameIndex( data.mValue ); + + if ( data.mAllowNull ) + map.insert( nullValue, tr( "(no selection)" ) ); + + if ( ki >= 0 && vi >= 0 ) + { + layer->select( QgsAttributeList() << ki << vi, QgsRectangle(), false ); + QgsFeature f; + while ( layer->nextFeature( f ) ) + { + map.insert( f.attributeMap()[ ki ].toString(), f.attributeMap()[ vi ].toString() ); + } + } + } + + QComboBox *cb = comboBox( editor, parent ); + if ( cb ) + { + for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ ) + { + cb->addItem( it.value(), it.key() ); + } + + myWidget = cb; + } + } + break; + case QgsVectorLayer::Classification: { QMap classes; @@ -482,7 +524,8 @@ { if ( editType == QgsVectorLayer::UniqueValues || editType == QgsVectorLayer::ValueMap || - editType == QgsVectorLayer::Classification ) + editType == QgsVectorLayer::Classification || + editType == QgsVectorLayer::ValueRelation ) { text = cb->itemData( cb->currentIndex() ).toString(); if ( text == nullValue ) @@ -621,6 +664,7 @@ case QgsVectorLayer::UniqueValues: case QgsVectorLayer::Enumeration: case QgsVectorLayer::ValueMap: + case QgsVectorLayer::ValueRelation: { QVariant v = value; QComboBox *cb = qobject_cast( editor ); Index: src/core/qgsvectorlayer.cpp =================================================================== --- src/core/qgsvectorlayer.cpp (revision 15691) +++ src/core/qgsvectorlayer.cpp (working copy) @@ -3013,6 +3013,14 @@ { mCheckedStates[ name ] = QPair( editTypeElement.attribute( "checked" ), editTypeElement.attribute( "unchecked" ) ); } + else if ( editType == ValueRelation ) + { + QString id = editTypeElement.attribute( "layer" ); + QString key = editTypeElement.attribute( "key" ); + QString value = editTypeElement.attribute( "value" ); + bool allowNull = editTypeElement.attribute( "allowNull" ) == "true"; + mValueRelations[ name ] = ValueRelationData( id, key, value, allowNull ); + } } } @@ -3208,6 +3216,17 @@ } break; + case ValueRelation: + if ( mValueRelations.contains( it.key() ) ) + { + const ValueRelationData &data = mValueRelations[ it.key() ]; + editTypeElement.setAttribute( "layer", data.mLayer ); + editTypeElement.setAttribute( "key", data.mKey ); + editTypeElement.setAttribute( "value", data.mValue ); + editTypeElement.setAttribute( "allowNull", data.mAllowNull ? "true" : "false" ); + } + break; + case LineEdit: case UniqueValues: case UniqueValuesEditable: @@ -5256,3 +5275,21 @@ mDiagramLayerSettings = new QgsDiagramLayerSettings(); *mDiagramLayerSettings = s; } + +QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx ) +{ + const QgsFieldMap &fields = pendingFields(); + + // FIXME: throw an exception!? + if ( fields.contains( idx ) ) + { + QgsDebugMsg( QString( "field %1 not found" ).arg( idx ) ); + } + + if ( !mValueRelations.contains( fields[idx].name() ) ) + { + mValueRelations[ fields[idx].name()] = ValueRelationData(); + } + + return mValueRelations[ fields[idx].name()]; +} Index: src/core/qgsvectorlayer.h =================================================================== --- src/core/qgsvectorlayer.h (revision 15691) +++ src/core/qgsvectorlayer.h (working copy) @@ -98,14 +98,15 @@ Classification, EditRange, SliderRange, - CheckBox, /* added in 1.4 */ + CheckBox, /* added in 1.4 */ FileName, Enumeration, - Immutable, /* The attribute value should not be changed in the attribute form*/ - Hidden, /* The attribute value should not be shown in the attribute form @added in 1.4 */ - TextEdit, /* multiline edit @added in 1.4*/ - Calendar, /* calendar widget @added in 1.5 */ - DialRange, /* dial range @added in 1.5 */ + Immutable, /* The attribute value should not be changed in the attribute form*/ + Hidden, /* The attribute value should not be shown in the attribute form @added in 1.4 */ + TextEdit, /* multiline edit @added in 1.4*/ + Calendar, /* calendar widget @added in 1.5 */ + DialRange, /* dial range @added in 1.5 */ + ValueRelation, /* value map from an table @added in 1.8 */ }; struct RangeData @@ -119,6 +120,18 @@ QVariant mStep; }; + struct ValueRelationData + { + ValueRelationData() {} + ValueRelationData( QString layer, QString key, QString value, bool allowNull ) + : mLayer( layer ), mKey( key ), mValue( value ), mAllowNull( allowNull ) {} + + QString mLayer; + QString mKey; + QString mValue; + bool mAllowNull; + }; + /** Constructor */ QgsVectorLayer( QString path = QString::null, QString baseName = QString::null, QString providerLib = QString::null, bool loadDefaultStyleFlag = true ); @@ -587,6 +600,11 @@ /**access range */ RangeData &range( int idx ); + /**access relations + * @note added in 1.8 + **/ + ValueRelationData &valueRelation( int idx ); + /**Adds a new overlay to this class. QgsVectorLayer takes ownership of the object @note this method was added in version 1.1 */ @@ -928,6 +946,7 @@ QMap< QString, QMap > mValueMaps; QMap< QString, RangeData > mRanges; QMap< QString, QPair > mCheckedStates; + QMap< QString, ValueRelationData > mValueRelations; QString mEditForm, mEditFormInit; //annotation form for this layer Index: src/ui/qgsattributetypeedit.ui =================================================================== --- src/ui/qgsattributetypeedit.ui (revision 15691) +++ src/ui/qgsattributetypeedit.ui (working copy) @@ -76,6 +76,11 @@ Calendar + + + Value relation + + @@ -87,7 +92,7 @@ - 0 + 12 @@ -591,6 +596,79 @@ + + + + + + Layer + + + valueRelationLayer + + + + + + + + + + Key column + + + valueRelationKeyColumn + + + + + + + + + + Value column + + + valueRelationValueColumn + + + + + + + + + + Select layer, key column and value column + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::RightToLeft + + + Allow null value + + + + + @@ -614,8 +692,8 @@ accept() - 248 - 254 + 257 + 418 157 @@ -630,8 +708,8 @@ reject() - 316 - 260 + 325 + 418 286