| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| /*************************************************************************** | ||
| qgsrelation.sip | ||
| -------------------------------------- | ||
| Date : 29.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| class QgsRelation | ||
| { | ||
| %TypeHeaderCode | ||
| #include <qgsrelation.h> | ||
| %End | ||
| public: | ||
| /** | ||
| * Defines a relation between matchin fields of the two involved tables of a relation. | ||
| * Often, a relation is only defined by just one FieldPair with the name of the foreign key | ||
| * column of the referencing table as first element and the name of the primkary key column | ||
| * of the referenced table as the second element. | ||
| * | ||
| */ | ||
| typedef QPair< QString, QString > FieldPair; | ||
|
|
||
| /** | ||
| * Default constructor. Creates an invalid relation. | ||
| */ | ||
| QgsRelation(); | ||
|
|
||
| /** | ||
| * Creates a relation from an XML structure. Used for reading .qgs projects. | ||
| * | ||
| * @param node The dom node containing the relation information | ||
| * | ||
| * @return A relation | ||
| */ | ||
| static QgsRelation createFromXML( const QDomNode& node ); | ||
|
|
||
| /** | ||
| * Writes a relation to an XML structure. Used for saving .qgs projects | ||
| * | ||
| * @param node The parent node in which the relation will be created | ||
| * @param doc The document in which the relation will be saved | ||
| */ | ||
| void writeXML( QDomNode& node, QDomDocument& doc ) const; | ||
|
|
||
| /** | ||
| * Set a name for this relation | ||
| * | ||
| * @param id | ||
| */ | ||
| void setRelationId( QString id ); | ||
|
|
||
| /** | ||
| * Set a name for this relation | ||
| * | ||
| * @param name | ||
| */ | ||
| void setRelationName( QString name ); | ||
|
|
||
| /** | ||
| * Set the referencing layer id. This layer will be searched in the registry. | ||
| * | ||
| * @param id | ||
| */ | ||
| void setReferencingLayer( QString id ); | ||
|
|
||
| /** | ||
| * Set the referenced layer id. This layer will be searched in the registry. | ||
| * | ||
| * @param id | ||
| */ | ||
| void setReferencedLayer( QString id ); | ||
|
|
||
| /** | ||
| * Add a field pairs which is part of this relation | ||
| * The first element of each pair are the field names fo the foreign key. | ||
| * The second element of each pair are the field names of the matching primary key. | ||
| * | ||
| * @param referencingField The field name on the referencing layer (FK) | ||
| * @param referencedField The field name on the referenced layer (PK) | ||
| */ | ||
| void addFieldPair( QString referencingField, QString referencedField ); | ||
|
|
||
| /** | ||
| * Creates an iterator which returns all the features on the referencing (child) layer | ||
| * which have a foreign key pointing to the provided feature. | ||
| * | ||
| * @param feature A feature from the referenced (parent) layer | ||
| * | ||
| * @return An iterator with all the referenced features | ||
| */ | ||
| QgsFeatureIterator getRelatedFeatures( const QgsFeature& feature ) const; | ||
|
|
||
| /** | ||
| * Creates a request to return all the features on the referencing (child) layer | ||
| * which have a foreign key pointing to the provided feature. | ||
| * | ||
| * @param feature A feature from the referenced (parent) layer | ||
| * | ||
| * @return An request for all the referenced features | ||
| */ | ||
| QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const; | ||
|
|
||
| const QString name() const; | ||
|
|
||
| /** | ||
| * The id | ||
| * @return | ||
| */ | ||
| const QString& id() const; | ||
|
|
||
| /** | ||
| * Access the referencing (child) layer's id | ||
| * This is the layer which has the field(s) which point to another layer | ||
| * | ||
| * @return The id of the referencing layer | ||
| */ | ||
| QString referencingLayerId() const; | ||
|
|
||
| /** | ||
| * Access the referencing (child) layer | ||
| * This is the layer which has the field(s) which point to another layer | ||
| * | ||
| * @return The referencing layer | ||
| */ | ||
| QgsVectorLayer* referencingLayer() const; | ||
|
|
||
| /** | ||
| * Access the referenced (parent) layer's id | ||
| * | ||
| * @return The id of the referenced layer | ||
| */ | ||
| QString referencedLayerId() const; | ||
|
|
||
| /** | ||
| * Access the referenced (parent) layer | ||
| * | ||
| * @return referenced layer | ||
| */ | ||
| QgsVectorLayer* referencedLayer() const; | ||
|
|
||
| /** | ||
| * Returns the field pairs which form this relation | ||
| * The first element of each pair are the field names fo the foreign key. | ||
| * The second element of each pair are the field names of the matching primary key. | ||
| * | ||
| * @return The fields forming the relation | ||
| */ | ||
| QMap< QString, QString > fieldPairs() const; | ||
| %MethodCode | ||
| QList< QgsRelation::FieldPair > pairs = sipCpp->fieldPairs(); | ||
| Q_FOREACH( const QgsRelation::FieldPair& pair, pairs ) | ||
| { | ||
| sipRes->insert( pair.first, pair.second ); | ||
| } | ||
| %End | ||
|
|
||
| /** | ||
| * Returns the validity of this relation. Don't use the information if it's not valid. | ||
| * | ||
| * @return true if the relation is valid | ||
| */ | ||
| bool isValid() const; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,258 @@ | ||
| /*************************************************************************** | ||
| qgsrelation.cpp | ||
| -------------------------------------- | ||
| Date : 29.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrelation.h" | ||
|
|
||
| #include "qgsapplication.h" | ||
| #include "qgslogger.h" | ||
| #include "qgsmaplayerregistry.h" | ||
| #include "qgsvectorlayer.h" | ||
|
|
||
| QgsRelation::QgsRelation() | ||
| : mReferencingLayer( NULL ) | ||
| , mReferencedLayer( NULL ) | ||
| , mValid( false ) | ||
| { | ||
| } | ||
|
|
||
| QgsRelation QgsRelation::createFromXML( const QDomNode &node ) | ||
| { | ||
| QDomElement elem = node.toElement(); | ||
|
|
||
| if ( elem.tagName() != "relation" ) | ||
| { | ||
| QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) ); | ||
| } | ||
|
|
||
| QgsRelation relation; | ||
|
|
||
| QString referencingLayerId = elem.attribute( "referencingLayer" ); | ||
| QString referencedLayerId = elem.attribute( "referencedLayer" ); | ||
| QString id = elem.attribute( "id" ); | ||
| QString name = elem.attribute( "name" ); | ||
|
|
||
| const QMap<QString, QgsMapLayer*>& mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); | ||
|
|
||
| QgsMapLayer* referencingLayer = mapLayers[referencingLayerId]; | ||
| QgsMapLayer* referencedLayer = mapLayers[referencedLayerId];; | ||
|
|
||
| if ( NULL == referencingLayer ) | ||
| { | ||
| QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencingLayerId ) ); | ||
| } | ||
| else if ( QgsMapLayer::VectorLayer != referencingLayer->type() ) | ||
| { | ||
| QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencingLayerId ) ); | ||
| } | ||
|
|
||
| if ( NULL == referencedLayer ) | ||
| { | ||
| QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencedLayerId ) ); | ||
| } | ||
| else if ( QgsMapLayer::VectorLayer != referencedLayer->type() ) | ||
| { | ||
| QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencedLayerId ) ); | ||
| } | ||
|
|
||
| relation.mReferencingLayerId = referencingLayerId; | ||
| relation.mReferencingLayer = qobject_cast<QgsVectorLayer*>( referencingLayer ); | ||
| relation.mReferencedLayerId = referencedLayerId; | ||
| relation.mReferencedLayer = qobject_cast<QgsVectorLayer*>( referencedLayer ); | ||
| relation.mRelationId = id; | ||
| relation.mRelationName = name; | ||
|
|
||
| QDomNodeList references = elem.elementsByTagName( "fieldRef" ); | ||
| for ( int i = 0; i < references.size(); ++i ) | ||
| { | ||
| QDomElement refEl = references.at( i ).toElement(); | ||
|
|
||
| QString referencingField = refEl.attribute( "referencingField" ); | ||
| QString referencedField = refEl.attribute( "referencedField" ); | ||
|
|
||
| relation.addFieldPair( referencingField, referencedField ); | ||
| } | ||
|
|
||
| relation.mValid = true; | ||
|
|
||
| return relation; | ||
| } | ||
|
|
||
| void QgsRelation::writeXML( QDomNode &node, QDomDocument &doc ) const | ||
| { | ||
| QDomElement elem = doc.createElement( "relation" ); | ||
| elem.setAttribute( "id", mRelationId ); | ||
| elem.setAttribute( "name", mRelationName ); | ||
| elem.setAttribute( "referencingLayer", mReferencingLayerId ); | ||
| elem.setAttribute( "referencedLayer", mReferencedLayerId ); | ||
|
|
||
| foreach ( FieldPair fields, mFieldPairs ) | ||
| { | ||
| QDomElement referenceElem = doc.createElement( "fieldRef" ); | ||
| referenceElem.setAttribute( "referencingField", fields.first ); | ||
| referenceElem.setAttribute( "referencedField", fields.second ); | ||
| elem.appendChild( referenceElem ); | ||
| } | ||
|
|
||
| node.appendChild( elem ); | ||
| } | ||
|
|
||
| void QgsRelation::setRelationId( QString id ) | ||
| { | ||
| mRelationId = id; | ||
| } | ||
|
|
||
| void QgsRelation::setRelationName( QString name ) | ||
| { | ||
| mRelationName = name; | ||
| } | ||
|
|
||
| void QgsRelation::setReferencingLayer( QString id ) | ||
| { | ||
| mReferencingLayerId = id; | ||
|
|
||
| updateRelationStatus(); | ||
| } | ||
|
|
||
| void QgsRelation::setReferencedLayer( QString id ) | ||
| { | ||
| mReferencedLayerId = id; | ||
|
|
||
| updateRelationStatus(); | ||
| } | ||
|
|
||
| void QgsRelation::addFieldPair( QString referencingField, QString referencedField ) | ||
| { | ||
| mFieldPairs << FieldPair( referencingField, referencedField ); | ||
| updateRelationStatus(); | ||
| } | ||
|
|
||
| void QgsRelation::addFieldPair( QgsRelation::FieldPair fieldPair ) | ||
| { | ||
| mFieldPairs << fieldPair; | ||
| updateRelationStatus(); | ||
| } | ||
|
|
||
| QgsFeatureIterator QgsRelation::getRelatedFeatures( const QgsFeature& feature ) const | ||
| { | ||
| return referencingLayer()->getFeatures( getRelatedFeaturesRequest( feature ) ); | ||
| } | ||
|
|
||
| QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feature ) const | ||
| { | ||
| QStringList conditions; | ||
|
|
||
| foreach ( const QgsRelation::FieldPair& fieldPair, mFieldPairs ) | ||
| { | ||
| int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() ); | ||
| QgsField referencingField = referencingLayer()->pendingFields().at( referencingIdx ); | ||
|
|
||
| switch ( referencingField.type() ) | ||
| { | ||
| case QVariant::String: | ||
| // Use quotes | ||
| conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() ); | ||
| break; | ||
|
|
||
| default: | ||
| // No quotes | ||
| conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() ); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| QgsFeatureRequest myRequest; | ||
|
|
||
| QgsDebugMsg( QString( "Filter conditions: '%1'" ).arg( conditions.join( " AND " ) ) ); | ||
|
|
||
| myRequest.setFilterExpression( conditions.join( " AND " ) ); | ||
|
|
||
| return myRequest; | ||
| } | ||
|
|
||
| const QString QgsRelation::name() const | ||
| { | ||
| return mRelationName; | ||
| } | ||
|
|
||
| const QString& QgsRelation::id() const | ||
| { | ||
| return mRelationId; | ||
| } | ||
|
|
||
| QString QgsRelation::referencingLayerId() const | ||
| { | ||
| return mReferencingLayerId; | ||
| } | ||
|
|
||
| QgsVectorLayer* QgsRelation::referencingLayer() const | ||
| { | ||
| return mReferencingLayer; | ||
| } | ||
|
|
||
| QString QgsRelation::referencedLayerId() const | ||
| { | ||
| return mReferencedLayerId; | ||
| } | ||
|
|
||
| QgsVectorLayer* QgsRelation::referencedLayer() const | ||
| { | ||
| return mReferencedLayer; | ||
| } | ||
|
|
||
| QList<QgsRelation::FieldPair> QgsRelation::fieldPairs() const | ||
| { | ||
| return mFieldPairs; | ||
| } | ||
|
|
||
| bool QgsRelation::isValid() const | ||
| { | ||
| return mValid; | ||
| } | ||
|
|
||
| void QgsRelation::updateRelationStatus() | ||
| { | ||
| const QMap<QString, QgsMapLayer*>& mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); | ||
|
|
||
| mReferencingLayer = qobject_cast<QgsVectorLayer*>( mapLayers[mReferencingLayerId] ); | ||
| mReferencedLayer = qobject_cast<QgsVectorLayer*>( mapLayers[mReferencedLayerId] ); | ||
|
|
||
| mValid = true; | ||
|
|
||
| if ( !mReferencedLayer || !mReferencingLayer ) | ||
| { | ||
| mValid = false; | ||
| } | ||
| else | ||
| { | ||
| if ( mFieldPairs.count() < 1 ) | ||
| { | ||
| mValid = false; | ||
| } | ||
|
|
||
| Q_FOREACH( const FieldPair& fieldPair, mFieldPairs ) | ||
| { | ||
| if ( -1 == mReferencingLayer->fieldNameIndex( fieldPair.first ) | ||
| || -1 == mReferencedLayer->fieldNameIndex( fieldPair.second ) ) | ||
| { | ||
| mValid = false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void QgsRelation::runChecks() | ||
| { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,227 @@ | ||
| /*************************************************************************** | ||
| qgsrelation.h | ||
| -------------------------------------- | ||
| Date : 29.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRELATION_H | ||
| #define QGSRELATION_H | ||
|
|
||
| #include <QList> | ||
| #include <QDomNode> | ||
| #include <QPair> | ||
|
|
||
| #include "qgsfield.h" | ||
| #include "qgsfeatureiterator.h" | ||
|
|
||
| class QgsVectorLayer; | ||
|
|
||
| class CORE_EXPORT QgsRelation | ||
| { | ||
| public: | ||
| /** | ||
| * Defines a relation between matchin fields of the two involved tables of a relation. | ||
| * Often, a relation is only defined by just one FieldPair with the name of the foreign key | ||
| * column of the referencing table as first element and the name of the primkary key column | ||
| * of the referenced table as the second element. | ||
| * | ||
| */ | ||
| class FieldPair : public QPair< QString, QString > | ||
| { | ||
| public: | ||
| //! Default constructor: NULL strings | ||
| FieldPair() | ||
| : QPair< QString, QString >() {} | ||
|
|
||
| //! Constructor which takes two fields | ||
| FieldPair( QString referencingField, QString referencedField ) | ||
| : QPair< QString, QString >( referencingField, referencedField ) {} | ||
|
|
||
| //! Get the name of the referencing field | ||
| const QString& referencingField() const { return first; } | ||
| //! Get the name of the referenced field | ||
| const QString& referencedField() const { return second; } | ||
| }; | ||
|
|
||
| /** | ||
| * Default constructor. Creates an invalid relation. | ||
| */ | ||
| QgsRelation(); | ||
|
|
||
| /** | ||
| * Creates a relation from an XML structure. Used for reading .qgs projects. | ||
| * | ||
| * @param node The dom node containing the relation information | ||
| * | ||
| * @return A relation | ||
| */ | ||
| static QgsRelation createFromXML( const QDomNode& node ); | ||
|
|
||
| /** | ||
| * Writes a relation to an XML structure. Used for saving .qgs projects | ||
| * | ||
| * @param node The parent node in which the relation will be created | ||
| * @param doc The document in which the relation will be saved | ||
| */ | ||
| void writeXML( QDomNode& node, QDomDocument& doc ) const; | ||
|
|
||
| /** | ||
| * Set a name for this relation | ||
| * | ||
| * @param id | ||
| */ | ||
| void setRelationId( QString id ); | ||
|
|
||
| /** | ||
| * Set a name for this relation | ||
| * | ||
| * @param name | ||
| */ | ||
| void setRelationName( QString name ); | ||
|
|
||
| /** | ||
| * Set the referencing layer id. This layer will be searched in the registry. | ||
| * | ||
| * @param id | ||
| */ | ||
| void setReferencingLayer( QString id ); | ||
|
|
||
| /** | ||
| * Set the referenced layer id. This layer will be searched in the registry. | ||
| * | ||
| * @param id | ||
| */ | ||
| void setReferencedLayer( QString id ); | ||
|
|
||
| /** | ||
| * Add a field pairs which is part of this relation | ||
| * The first element of each pair are the field names fo the foreign key. | ||
| * The second element of each pair are the field names of the matching primary key. | ||
| * | ||
| * @param referencingField The field name on the referencing layer (FK) | ||
| * @param referencedField The field name on the referenced layer (PK) | ||
| */ | ||
| void addFieldPair( QString referencingField, QString referencedField ); | ||
|
|
||
| /** | ||
| * Add a field pairs which is part of this relation | ||
| * The first element of each pair are the field names fo the foreign key. | ||
| * The second element of each pair are the field names of the matching primary key. | ||
| * | ||
| * @param fieldPair A pair of two strings | ||
| */ | ||
| void addFieldPair( FieldPair fieldPair ); | ||
|
|
||
| /** | ||
| * Creates an iterator which returns all the features on the referencing (child) layer | ||
| * which have a foreign key pointing to the provided feature. | ||
| * | ||
| * @param feature A feature from the referenced (parent) layer | ||
| * | ||
| * @return An iterator with all the referenced features | ||
| */ | ||
| QgsFeatureIterator getRelatedFeatures( const QgsFeature& feature ) const; | ||
|
|
||
| /** | ||
| * Creates a request to return all the features on the referencing (child) layer | ||
| * which have a foreign key pointing to the provided feature. | ||
| * | ||
| * @param feature A feature from the referenced (parent) layer | ||
| * | ||
| * @return An request for all the referenced features | ||
| */ | ||
| QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const; | ||
|
|
||
| const QString name() const; | ||
|
|
||
| /** | ||
| * The id | ||
| * @return | ||
| */ | ||
| const QString& id() const; | ||
|
|
||
| /** | ||
| * Access the referencing (child) layer's id | ||
| * This is the layer which has the field(s) which point to another layer | ||
| * | ||
| * @return The id of the referencing layer | ||
| */ | ||
| QString referencingLayerId() const; | ||
|
|
||
| /** | ||
| * Access the referencing (child) layer | ||
| * This is the layer which has the field(s) which point to another layer | ||
| * | ||
| * @return The referencing layer | ||
| */ | ||
| QgsVectorLayer* referencingLayer() const; | ||
|
|
||
| /** | ||
| * Access the referenced (parent) layer's id | ||
| * | ||
| * @return The id of the referenced layer | ||
| */ | ||
| QString referencedLayerId() const; | ||
|
|
||
| /** | ||
| * Access the referenced (parent) layer | ||
| * | ||
| * @return referenced layer | ||
| */ | ||
| QgsVectorLayer* referencedLayer() const; | ||
|
|
||
| /** | ||
| * Returns the field pairs which form this relation | ||
| * The first element of each pair are the field names fo the foreign key. | ||
| * The second element of each pair are the field names of the matching primary key. | ||
| * | ||
| * @return The fields forming the relation | ||
| */ | ||
| QList< FieldPair > fieldPairs() const; | ||
|
|
||
| /** | ||
| * Returns the validity of this relation. Don't use the information if it's not valid. | ||
| * | ||
| * @return true if the relation is valid | ||
| */ | ||
| bool isValid() const; | ||
|
|
||
| protected: | ||
| void updateRelationStatus(); | ||
| void runChecks(); | ||
|
|
||
| private: | ||
| /** Unique Id */ | ||
| QString mRelationId; | ||
| /** Human redable name*/ | ||
| QString mRelationName; | ||
| /** The child layer */ | ||
| QString mReferencingLayerId; | ||
| /** The child layer */ | ||
| QgsVectorLayer* mReferencingLayer; | ||
| /** The parent layer id */ | ||
| QString mReferencedLayerId; | ||
| /** The parent layer */ | ||
| QgsVectorLayer* mReferencedLayer; | ||
| /** A list of fields which define the relation. | ||
| * In most cases there will be only one value, but multiple values | ||
| * are supported for composited foreign keys. | ||
| * The first field is on the referencing layer, the second on the referenced */ | ||
| QList< FieldPair > mFieldPairs; | ||
|
|
||
| bool mValid; | ||
| }; | ||
|
|
||
| // Register QgsRelation for usage with QVariant | ||
| Q_DECLARE_METATYPE( QgsRelation ) | ||
|
|
||
| #endif // QGSRELATION_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| /*************************************************************************** | ||
| qgsrelationmanager.cpp | ||
| -------------------------------------- | ||
| Date : 1.3.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrelationmanager.h" | ||
|
|
||
| #include "qgsapplication.h" | ||
| #include "qgslogger.h" | ||
| #include "qgsproject.h" | ||
| #include "qgsvectorlayer.h" | ||
|
|
||
| QgsRelationManager::QgsRelationManager( QgsProject* project ) | ||
| : QObject( project ) | ||
| , mProject( project ) | ||
| { | ||
| connect( project, SIGNAL( readProject( const QDomDocument& ) ), SLOT( readProject( const QDomDocument& ) ) ); | ||
| connect( project, SIGNAL( writeProject( QDomDocument& ) ), SLOT( writeProject( QDomDocument& ) ) ); | ||
| } | ||
|
|
||
| void QgsRelationManager::setRelations( const QList<QgsRelation>& relations ) | ||
| { | ||
| mRelations.clear(); | ||
| foreach ( const QgsRelation& rel, relations ) | ||
| { | ||
| addRelation( rel ); | ||
| } | ||
| } | ||
|
|
||
| const QMap<QString, QgsRelation>& QgsRelationManager::relations() const | ||
| { | ||
| return mRelations; | ||
| } | ||
|
|
||
| void QgsRelationManager::addRelation( const QgsRelation& relation ) | ||
| { | ||
| if ( !relation.isValid() ) | ||
| return; | ||
|
|
||
| mRelations.insert( relation.id(), relation ); | ||
|
|
||
| mProject->dirty( true ); | ||
| } | ||
|
|
||
| void QgsRelationManager::removeRelation( const QString& name ) | ||
| { | ||
| mRelations.remove( name ); | ||
| } | ||
|
|
||
| void QgsRelationManager::removeRelation( const QgsRelation& relation ) | ||
| { | ||
| mRelations.remove( relation.id() ); | ||
| } | ||
|
|
||
| QgsRelation QgsRelationManager::relation( const QString& id ) const | ||
| { | ||
| return mRelations.value( id ); | ||
| } | ||
|
|
||
| void QgsRelationManager::clear() | ||
| { | ||
| mRelations.clear(); | ||
| } | ||
|
|
||
| QList<QgsRelation> QgsRelationManager::referencingRelations( QgsVectorLayer* layer, int fieldIdx ) const | ||
| { | ||
| if ( !layer ) | ||
| { | ||
| return mRelations.values(); | ||
| } | ||
|
|
||
| QList<QgsRelation> relations; | ||
|
|
||
| foreach ( const QgsRelation& rel, mRelations ) | ||
| { | ||
| if ( rel.referencingLayer() == layer ) | ||
| { | ||
| if ( fieldIdx != -2 ) | ||
| { | ||
| bool containsField = false; | ||
| foreach ( const QgsRelation::FieldPair& fp, rel.fieldPairs() ) | ||
| { | ||
| if ( fieldIdx == layer->fieldNameIndex( fp.referencingField() ) ) | ||
| { | ||
| containsField = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if ( !containsField ) | ||
| { | ||
| continue; | ||
| } | ||
| } | ||
| relations.append( rel ); | ||
| } | ||
| } | ||
|
|
||
| return relations; | ||
| } | ||
|
|
||
| QList<QgsRelation> QgsRelationManager::referencedRelations( QgsVectorLayer* layer ) const | ||
| { | ||
| if ( !layer ) | ||
| { | ||
| return mRelations.values(); | ||
| } | ||
|
|
||
| QList<QgsRelation> relations; | ||
|
|
||
| foreach ( const QgsRelation& rel, mRelations ) | ||
| { | ||
| if ( rel.referencedLayer() == layer ) | ||
| { | ||
| relations.append( rel ); | ||
| } | ||
| } | ||
|
|
||
| return relations; | ||
| } | ||
|
|
||
| void QgsRelationManager::readProject( const QDomDocument & doc ) | ||
| { | ||
| mRelations.clear(); | ||
|
|
||
| QDomNodeList nodes = doc.elementsByTagName( "relations" ); | ||
| if ( nodes.count() ) | ||
| { | ||
| QDomNode node = nodes.item( 0 ); | ||
| QDomNodeList relationNodes = node.childNodes(); | ||
| int relCount = relationNodes.count(); | ||
| for ( int i = 0; i < relCount; ++i ) | ||
| { | ||
| addRelation( QgsRelation::createFromXML( relationNodes.at( i ) ) ); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| QgsDebugMsg( "No relations data present in this document" ); | ||
| } | ||
|
|
||
| emit( relationsLoaded() ); | ||
| } | ||
|
|
||
| void QgsRelationManager::writeProject( QDomDocument & doc ) | ||
| { | ||
| QDomNodeList nl = doc.elementsByTagName( "qgis" ); | ||
| if ( !nl.count() ) | ||
| { | ||
| QgsDebugMsg( "Unable to find qgis element in project file" ); | ||
| return; | ||
| } | ||
| QDomNode qgisNode = nl.item( 0 ); // there should only be one | ||
|
|
||
| QDomElement relationsNode = doc.createElement( "relations" ); | ||
| qgisNode.appendChild( relationsNode ); | ||
|
|
||
| foreach ( const QgsRelation& relation, mRelations ) | ||
| { | ||
| relation.writeXML( relationsNode, doc ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /*************************************************************************** | ||
| qgsrelationmanager.h | ||
| -------------------------------------- | ||
| Date : 1.3.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRELATIONMANAGER_H | ||
| #define QGSRELATIONMANAGER_H | ||
|
|
||
| #include <QObject> | ||
| #include <QPair> | ||
| #include <QDomNode> | ||
| #include <QDomDocument> | ||
|
|
||
| #include "qgsrelation.h" | ||
|
|
||
| class QgsProject; | ||
| class QgsVectorLayer; | ||
|
|
||
| /** | ||
| * This class manages a set of relations between layers. | ||
| */ | ||
| class CORE_EXPORT QgsRelationManager : public QObject | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| explicit QgsRelationManager( QgsProject* project ); | ||
|
|
||
| void setRelations( const QList<QgsRelation>& relations ); | ||
| const QMap<QString, QgsRelation>& relations() const; | ||
| void addRelation( const QgsRelation& relation ); | ||
| void removeRelation( const QString& name ); | ||
| void removeRelation( const QgsRelation& relation ); | ||
| QgsRelation relation( const QString& id ) const; | ||
| void clear(); | ||
|
|
||
| QList<QgsRelation> referencingRelations( QgsVectorLayer* layer = NULL, int fieldIdx = -2 ) const; | ||
| QList<QgsRelation> referencedRelations( QgsVectorLayer* layer = NULL ) const; | ||
|
|
||
| signals: | ||
| void relationsLoaded(); | ||
|
|
||
| public slots: | ||
|
|
||
| private slots: | ||
| void readProject( const QDomDocument &doc ); | ||
| void writeProject( QDomDocument &doc ); | ||
|
|
||
| private: | ||
| /** The references */ | ||
| QMap<QString, QgsRelation> mRelations; | ||
|
|
||
| QgsProject* mProject; | ||
| }; | ||
|
|
||
| #endif // QGSRELATIONMANAGER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /*************************************************************************** | ||
| qgsrelationreferencefactory.cpp | ||
| -------------------------------------- | ||
| Date : 29.5.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrelationreferencefactory.h" | ||
|
|
||
| #include "qgsrelationreferencewidget.h" | ||
| #include "qgsrelreferenceconfigdlg.h" | ||
|
|
||
| QgsRelationReferenceFactory::QgsRelationReferenceFactory( QgsAttributeEditorContext context, QString name ) | ||
| : QgsEditorWidgetFactory( name ) | ||
| , mEditorContext( context ) | ||
| { | ||
| } | ||
|
|
||
| QgsEditorWidgetWrapper* QgsRelationReferenceFactory::create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const | ||
| { | ||
| return new QgsRelationReferenceWidget( vl, fieldIdx, editor, mEditorContext, parent ); | ||
| } | ||
|
|
||
| QgsEditorConfigWidget* QgsRelationReferenceFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const | ||
| { | ||
| return new QgsRelReferenceConfigDlg( vl, fieldIdx, parent ); | ||
| } | ||
|
|
||
| QgsEditorWidgetConfig QgsRelationReferenceFactory::readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ) | ||
| { | ||
| Q_UNUSED( layer ); | ||
| Q_UNUSED( fieldIdx ); | ||
| QMap<QString, QVariant> cfg; | ||
|
|
||
| cfg.insert( "AllowNULL", configElement.attribute( "AllowNULL" ) == "1" ); | ||
| cfg.insert( "ShowForm", configElement.attribute( "ShowForm" ) == "1" ); | ||
| cfg.insert( "Relation", configElement.attribute( "Relation" ) ); | ||
|
|
||
| return cfg; | ||
| } | ||
|
|
||
| void QgsRelationReferenceFactory::writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, const QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) | ||
| { | ||
| Q_UNUSED( doc ); | ||
| Q_UNUSED( layer ); | ||
| Q_UNUSED( fieldIdx ); | ||
|
|
||
| configElement.setAttribute( "AllowNULL", config["AllowNULL"].toBool() ); | ||
| configElement.setAttribute( "ShowForm", config["ShowForm"].toBool() ); | ||
| configElement.setAttribute( "Relation", config["Relation"].toString() ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /*************************************************************************** | ||
| qgsrelationreferencefactory.h | ||
| -------------------------------------- | ||
| Date : 29.5.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRELATIONREFERENCEFACTORY_H | ||
| #define QGSRELATIONREFERENCEFACTORY_H | ||
|
|
||
| #include "qgsattributeeditorcontext.h" | ||
| #include "qgseditorwidgetfactory.h" | ||
|
|
||
| class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory | ||
| { | ||
| public: | ||
| QgsRelationReferenceFactory( QgsAttributeEditorContext context, QString name ); | ||
|
|
||
| /** | ||
| * Override this in your implementation. | ||
| * Create a new editor widget wrapper. Call {@link QgsEditorWidgetRegistry::create()} | ||
| * instead of calling this method directly. | ||
| * | ||
| * @param vl The vector layer on which this widget will act | ||
| * @param fieldIdx The field index on which this widget will act | ||
| * @param editor An editor widget if already existent. If NULL is provided, a new widget will be created. | ||
| * @param parent The parent for the wrapper class and any created widget. | ||
| * | ||
| * @return A new widget wrapper | ||
| */ | ||
| virtual QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const; | ||
|
|
||
| /** | ||
| * Override this in your implementation. | ||
| * Create a new configuration widget for this widget type. | ||
| * | ||
| * @param vl The layer for which the widget will be created | ||
| * @param fieldIdx The field index for which the widget will be created | ||
| * @param parent The parent widget of the created config widget | ||
| * | ||
| * @return A configuration widget | ||
| */ | ||
| virtual QgsEditorConfigWidget* configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const; | ||
|
|
||
| /** | ||
| * Read the config from an XML file and map it to a proper {@link QgsEditorWidgetConfig}. | ||
| * | ||
| * @param configElement The configuration element from the project file | ||
| * @param layer The layer for which this configuration applies | ||
| * @param fieldIdx The field on the layer for which this configuration applies | ||
| * | ||
| * @return A configuration object. This will be passed to your widget wrapper later on | ||
| */ | ||
| virtual QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ); | ||
|
|
||
| /** | ||
| * Serialize your configuration and save it in a xml doc. | ||
| * | ||
| * @param config The configuration to serialize | ||
| * @param configElement The element, where you can write your configuration into | ||
| * @param doc The document. You can use this to create new nodes | ||
| * @param layer The layer for which this configuration applies | ||
| * @param fieldIdx The field on the layer for which this configuration applies | ||
| */ | ||
| virtual void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, const QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ); | ||
|
|
||
| private: | ||
| QgsAttributeEditorContext mEditorContext; | ||
| }; | ||
|
|
||
| #endif // QGSRELATIONREFERENCEFACTORY_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| /*************************************************************************** | ||
| qgsrelationreferencewidget.cpp | ||
| -------------------------------------- | ||
| Date : 20.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrelationreferencewidget.h" | ||
|
|
||
| #include <QPushButton> | ||
| #include <QDialog> | ||
|
|
||
| #include "qgsattributedialog.h" | ||
| #include "qgscollapsiblegroupbox.h" | ||
| #include "qgseditorwidgetfactory.h" | ||
| #include "qgsexpression.h" | ||
| #include "qgsfield.h" | ||
| #include "qgsproject.h" | ||
| #include "qgsrelreferenceconfigdlg.h" | ||
| #include "qgsrelationmanager.h" | ||
| #include "qgsvectorlayer.h" | ||
|
|
||
| QgsRelationReferenceWidget::QgsRelationReferenceWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QWidget* parent ) | ||
| : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent ) | ||
| , mInitialValueAssigned( false ) | ||
| , mComboBox( NULL ) | ||
| , mAttributeEditorFrame( NULL ) | ||
| , mAttributeEditorLayout( NULL ) | ||
| , mAttributeEditorButton( NULL ) | ||
| , mReferencedLayer( NULL ) | ||
| , mAttributeDialog( NULL ) | ||
| , mEditorContext( context ) | ||
| { | ||
| } | ||
|
|
||
| QWidget* QgsRelationReferenceWidget::createWidget( QWidget* parent ) | ||
| { | ||
| return new QWidget( parent ); | ||
| } | ||
|
|
||
| void QgsRelationReferenceWidget::initWidget( QWidget* editor ) | ||
| { | ||
| QGridLayout* layout = new QGridLayout( editor ); | ||
| editor->setLayout( layout ); | ||
|
|
||
| mComboBox = new QComboBox( editor ); | ||
| layout->addWidget( mComboBox, 0, 0, 1, 1 ); | ||
|
|
||
| if ( config( "ShowForm", true ).toBool() ) | ||
| { | ||
| mAttributeEditorFrame = new QgsCollapsibleGroupBox( editor ); | ||
| mAttributeEditorLayout = new QVBoxLayout( mAttributeEditorFrame ); | ||
| mAttributeEditorFrame->setLayout( mAttributeEditorLayout ); | ||
|
|
||
| layout->addWidget( mAttributeEditorFrame, 1, 0, 1, 3 ); | ||
| } | ||
| else | ||
| { | ||
| mAttributeEditorButton = new QPushButton( tr( "Open Form" ) ); | ||
|
|
||
| layout->addWidget( mAttributeEditorButton, 0, 1, 1, 1 ); | ||
|
|
||
| connect( mAttributeEditorButton, SIGNAL( clicked() ), this, SLOT( openForm() ) ); | ||
| } | ||
|
|
||
| layout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding ), 0, 2, 1, 1 ); | ||
|
|
||
| QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() ); | ||
|
|
||
| if ( relation.isValid() ) | ||
| { | ||
| mReferencedLayer = relation.referencedLayer(); | ||
| int refFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second ); | ||
|
|
||
| QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() ); | ||
|
|
||
| QgsExpression exp( mReferencedLayer->displayExpression() ); | ||
| exp.prepare( mReferencedLayer->pendingFields() ); | ||
|
|
||
| QgsFeature f; | ||
| while ( fit.nextFeature( f ) ) | ||
| { | ||
| QString txt = exp.evaluate( &f ).toString(); | ||
|
|
||
| mComboBox->addItem( txt, f.id() ); | ||
|
|
||
| mFidFkMap.insert( f.id(), f.attribute( refFieldIdx ) ); | ||
| } | ||
|
|
||
| if ( config( "AllowNULL" ).toBool() ) | ||
| { | ||
| mComboBox->addItem( "[NULL]" ); | ||
| } | ||
|
|
||
| // Only connect after iterating, to have only one iterator on the referenced table at once | ||
| connect( mComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( referenceChanged( int ) ) ); | ||
| } | ||
| else | ||
| { | ||
| QLabel* lbl = new QLabel( tr( "The relation is not valid. Please make sure your relation definitions are ok." ) ); | ||
| QFont font = lbl->font(); | ||
| font.setItalic( true ); | ||
| lbl->setStyleSheet( "QLabel { color: red; } " ); | ||
| lbl->setFont( font ); | ||
| layout->addWidget( lbl, 1, 0, 1, 3 ); | ||
| } | ||
| } | ||
|
|
||
| QVariant QgsRelationReferenceWidget::value() | ||
| { | ||
| QVariant varFid = mComboBox->itemData( mComboBox->currentIndex() ); | ||
| if ( varFid.isNull() ) | ||
| { | ||
| return QVariant(); | ||
| } | ||
| else | ||
| { | ||
| return mFidFkMap.value( varFid.value<QgsFeatureId>() ); | ||
| } | ||
| } | ||
|
|
||
| void QgsRelationReferenceWidget::setValue( const QVariant& value ) | ||
| { | ||
| QgsFeatureId fid = mFidFkMap.key( value ); | ||
| int oldIdx = mComboBox->currentIndex(); | ||
| mComboBox->setCurrentIndex( mComboBox->findData( fid ) ); | ||
|
|
||
| if ( !mInitialValueAssigned ) | ||
| { | ||
| // In case the default-selected item (first) is the actual item | ||
| // then no referenceChanged event was triggered automatically: | ||
| // Do it! | ||
| if ( oldIdx == mComboBox->currentIndex() ) | ||
| referenceChanged( mComboBox->currentIndex() ); | ||
| mInitialValueAssigned = true; | ||
| } | ||
| } | ||
|
|
||
| void QgsRelationReferenceWidget::setEnabled( bool enabled ) | ||
| { | ||
| mComboBox->setEnabled( enabled ); | ||
| } | ||
|
|
||
| void QgsRelationReferenceWidget::referenceChanged( int index ) | ||
| { | ||
| QgsFeatureId fid = mComboBox->itemData( index ).value<QgsFeatureId>(); | ||
|
|
||
| emit valueChanged( mFidFkMap.value( fid ) ); | ||
|
|
||
| // Check if we're running with an embedded frame we need to update | ||
| if ( mAttributeEditorFrame ) | ||
| { | ||
| QgsFeature feat; | ||
|
|
||
| mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat ); | ||
|
|
||
| if ( feat.isValid() ) | ||
| { | ||
| // Backup old dialog and delete only after creating the new dialog, so we can "hot-swap" the contained QgsFeature | ||
| QgsAttributeDialog* oldDialog = mAttributeDialog; | ||
|
|
||
| if ( mAttributeDialog && mAttributeDialog->dialog() ) | ||
| { | ||
| mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() ); | ||
| } | ||
|
|
||
| // TODO: Get a proper QgsDistanceArea thingie | ||
| mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, mAttributeEditorFrame, false, mEditorContext ); | ||
| QWidget* attrDialog = mAttributeDialog->dialog(); | ||
| attrDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window | ||
| mAttributeEditorLayout->addWidget( attrDialog ); | ||
| attrDialog->show(); | ||
|
|
||
| delete oldDialog; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void QgsRelationReferenceWidget::openForm() | ||
| { | ||
| QgsFeatureId fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>(); | ||
|
|
||
| QgsFeature feat; | ||
|
|
||
| mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat ); | ||
|
|
||
| if ( !feat.isValid() ) | ||
| return; | ||
|
|
||
| // TODO: Get a proper QgsDistanceArea thingie | ||
| mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, widget(), true, mEditorContext ); | ||
| mAttributeDialog->exec(); | ||
| delete mAttributeDialog; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /*************************************************************************** | ||
| qgsrelationreferencewidget.h | ||
| -------------------------------------- | ||
| Date : 20.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRELATIONREFERENCEWIDGET_H | ||
| #define QGSRELATIONREFERENCEWIDGET_H | ||
|
|
||
| #include "qgsattributeeditorcontext.h" | ||
| #include "qgseditorwidgetwrapper.h" | ||
| #include "qgsfeature.h" | ||
|
|
||
| #include <QComboBox> | ||
| #include <QPushButton> | ||
| #include <QVBoxLayout> | ||
|
|
||
| class QgsAttributeDialog; | ||
| class QgsVectorLayerTools; | ||
|
|
||
| class GUI_EXPORT QgsRelationReferenceWidget : public QgsEditorWidgetWrapper | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| explicit QgsRelationReferenceWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QWidget* parent = 0 ); | ||
| virtual QWidget* createWidget( QWidget* parent ); | ||
| virtual void initWidget( QWidget* editor ); | ||
| virtual QVariant value(); | ||
|
|
||
| signals: | ||
| void valueChanged( const QVariant& value ); | ||
|
|
||
| public slots: | ||
| virtual void setValue( const QVariant& value ); | ||
| virtual void setEnabled( bool enabled ); | ||
|
|
||
| private slots: | ||
| void referenceChanged( int index ); | ||
| void openForm(); | ||
|
|
||
| private: | ||
| bool mInitialValueAssigned; | ||
| QComboBox* mComboBox; | ||
| QWidget* mAttributeEditorFrame; | ||
| QVBoxLayout* mAttributeEditorLayout; | ||
| QPushButton* mAttributeEditorButton; | ||
| QgsVectorLayer* mReferencedLayer; | ||
| QVariant mCurrentValue; | ||
| QgsAttributeDialog* mAttributeDialog; | ||
| QHash<QgsFeatureId, QVariant> mFidFkMap; // Mapping from feature id => foreign key | ||
| QgsAttributeEditorContext mEditorContext; | ||
| }; | ||
|
|
||
| #endif // QGSRELATIONREFERENCEWIDGET_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| /*************************************************************************** | ||
| qgsrelreferenceconfigdlg.cpp | ||
| -------------------------------------- | ||
| Date : 21.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrelreferenceconfigdlg.h" | ||
|
|
||
| #include "qgseditorwidgetfactory.h" | ||
| #include "qgsfield.h" | ||
| #include "qgsproject.h" | ||
| #include "qgsrelationmanager.h" | ||
| #include "qgsvectorlayer.h" | ||
|
|
||
| QgsRelReferenceConfigDlg::QgsRelReferenceConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) | ||
| : QgsEditorConfigWidget( vl, fieldIdx, parent ) | ||
| { | ||
| setupUi( this ); | ||
|
|
||
| foreach ( const QgsRelation& relation, vl->referencingRelations( fieldIdx ) ) | ||
| { | ||
| QgsField fld = relation.fieldPairs().first().second; | ||
| mComboRelation->addItem( QString( "%1 (%2)" ).arg( relation.id(), relation.referencedLayerId() ), relation.id() ); | ||
| if ( relation.referencedLayer() ) | ||
| { | ||
| mTxtDisplayExpression->setText( relation.referencedLayer()->displayExpression() ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void QgsRelReferenceConfigDlg::setConfig( const QMap<QString, QVariant>& config ) | ||
| { | ||
| if ( config.contains( "AllowNULL" ) ) | ||
| { | ||
| mCbxAllowNull->setChecked( config[ "AllowNULL" ].toBool() ); | ||
| } | ||
|
|
||
| if ( config.contains( "ShowForm" ) ) | ||
| { | ||
| mCbxShowForm->setChecked( config[ "ShowForm" ].toBool() ); | ||
| } | ||
|
|
||
| if ( config.contains( "Relation" ) ) | ||
| { | ||
| mComboRelation->setCurrentIndex( mComboRelation->findData( config[ "Relation" ].toString() ) ); | ||
| } | ||
| } | ||
|
|
||
| void QgsRelReferenceConfigDlg::on_mComboRelation_indexChanged( int idx ) | ||
| { | ||
| QString relName = mComboRelation->itemData( idx ).toString(); | ||
| QgsRelation rel = QgsProject::instance()->relationManager()->relation( relName ); | ||
|
|
||
| QgsVectorLayer* referencedLayer = rel.referencedLayer(); | ||
| if ( referencedLayer ) | ||
| { | ||
| mTxtDisplayExpression->setText( referencedLayer->displayExpression() ); | ||
| } | ||
| } | ||
|
|
||
| QgsEditorWidgetConfig QgsRelReferenceConfigDlg::config() | ||
| { | ||
| QgsEditorWidgetConfig myConfig; | ||
| myConfig.insert( "AllowNULL", mCbxAllowNull->isChecked() ); | ||
| myConfig.insert( "ShowForm", mCbxShowForm->isChecked() ); | ||
| myConfig.insert( "Relation", mComboRelation->itemData( mComboRelation->currentIndex() ) ); | ||
|
|
||
| return myConfig; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| /*************************************************************************** | ||
| qgsrelreferenceconfigdlgbase.h | ||
| -------------------------------------- | ||
| Date : 21.4.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRELREFERENCECONFIGDLGBASE_H | ||
| #define QGSRELREFERENCECONFIGDLGBASE_H | ||
|
|
||
| #include "ui_qgsrelreferenceconfigdlgbase.h" | ||
| #include "qgseditorconfigwidget.h" | ||
|
|
||
| class GUI_EXPORT QgsRelReferenceConfigDlg : public QgsEditorConfigWidget, private Ui::QgsRelReferenceConfigDlgBase | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| explicit QgsRelReferenceConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ); | ||
| virtual QgsEditorWidgetConfig config(); | ||
| virtual void setConfig( const QgsEditorWidgetConfig& config ); | ||
|
|
||
| private slots: | ||
| void on_mComboRelation_indexChanged( int idx ); | ||
| }; | ||
|
|
||
| #endif // QGSRELREFERENCECONFIGDLGBASE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /*************************************************************************** | ||
| qgsfeatureselectiondlg.cpp | ||
| -------------------------------------- | ||
| Date : 11.6.2013 | ||
| Copyright : (C) 2013 Matthias Kuhn | ||
| Email : matthias dot kuhn at gmx dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsfeatureselectiondlg.h" | ||
|
|
||
| #include "qgsgenericfeatureselectionmanager.h" | ||
| #include "qgsdistancearea.h" | ||
|
|
||
| QgsFeatureSelectionDlg::QgsFeatureSelectionDlg( QgsVectorLayer* vl, QWidget *parent ) | ||
| : QDialog( parent ) | ||
| , mVectorLayer( vl ) | ||
| { | ||
| setupUi( this ); | ||
|
|
||
| mFeatureSelection = new QgsGenericFeatureSelectionManager( mDualView ); | ||
|
|
||
| mDualView->setFeatureSelectionManager( mFeatureSelection ); | ||
|
|
||
| // TODO: Proper QgsDistanceArea, proper mapcanvas | ||
| mDualView->init( mVectorLayer, NULL ); | ||
| } | ||
|
|
||
| const QgsFeatureIds& QgsFeatureSelectionDlg::selectedFeatures() | ||
| { | ||
| return mFeatureSelection->selectedFeaturesIds(); | ||
| } | ||
|
|
||
|
|