122 changes: 122 additions & 0 deletions images/themes/default/mActionUnlink.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
605 changes: 605 additions & 0 deletions images/themes/default/relation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion python/core/core.sip
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
%Include qgsdatasourceuri.sip
%Include qgsdbfilterproxymodel.sip
%Include qgsdistancearea.sip
%Include qgseditorwidgetconfig.sip
%Include qgserror.sip
%Include qgsexpression.sip
%Include qgseditorwidgetconfig.sip
%Include qgsfeature.sip
%Include qgsfeatureiterator.sip
%Include qgsfeaturerequest.sip
Expand Down Expand Up @@ -68,6 +68,7 @@
%Include qgsproviderregistry.sip
%Include qgspythonrunner.sip
%Include qgsrectangle.sip
%Include qgsrelation.sip
%Include qgsrenderchecker.sip
%Include qgsrendercontext.sip
%Include qgsrunprocess.sip
Expand Down
171 changes: 171 additions & 0 deletions python/core/qgsrelation.sip
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;
};
5 changes: 3 additions & 2 deletions python/gui/qgsattributedialog.sip
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ class QgsAttributeDialog : QObject
%End

public:
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true );
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true ) /Deprecated/;
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget* parent = 0, bool showDialogButtons = true );
void saveGeometry();
void restoreGeometry();
QDialog *dialog();
QgsFeature* feature();
const QgsFeature* feature();

public slots:
void accept();
Expand Down
11 changes: 11 additions & 0 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@

#include "nodetool/qgsmaptoolnodetool.h"

// Editor widgets
#include "qgseditorwidgetregistry.h"
#include "qgsrelationreferencefactory.h"

//
// Conditional Includes
//
Expand Down Expand Up @@ -577,6 +581,13 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,

mVectorLayerTools = new QgsGuiVectorLayerTools();

// Init the editor widget types
QgsEditorWidgetRegistry* editorWidgetRegistry = QgsEditorWidgetRegistry::instance();
QgsAttributeEditorContext context;
context.setVectorLayerTools( vectorLayerTools() );
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( context, tr( "Relation Reference" ) ) );


mInternalClipboard = new QgsClipboard; // create clipboard
connect( mInternalClipboard, SIGNAL( changed() ), this, SLOT( clipboardChanged() ) );
mQgisInterface = new QgisAppInterface( this ); // create the interfce
Expand Down
9 changes: 7 additions & 2 deletions src/app/qgisappinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,18 +609,23 @@ void QgisAppInterface::cacheloadForm( QString uifile )
}
}

QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &f )
QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &feature )
{
QgsDistanceArea myDa;

myDa.setSourceCrs( l->crs().srsid() );
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );

QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &f, false, myDa );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
return dialog->dialog();
}

QgsVectorLayerTools* QgisAppInterface::vectorLayerTools()
{
return qgis->vectorLayerTools();
}

QList<QgsMapLayer *> QgisAppInterface::editableLayers( bool modified ) const
{
return qgis->editableLayers( modified );
Expand Down
39 changes: 30 additions & 9 deletions src/app/qgisappinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,34 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
virtual QAction *actionCheckQgisVersion();
virtual QAction *actionAbout();

//! open feature form
// returns true when dialog was accepted
// @param l vector layer
// @param f feature to show/modify
// @param updateFeatureOnly only update the feature update (don't change any attributes of the layer)
// @added in 1.6
/**
* Open feature form
* returns true when dialog was accepted
* @param l vector layer
* @param f feature to show/modify
* @param updateFeatureOnly only update the feature update (don't change any attributes of the layer)
* @note added in 1.6
*/
virtual bool openFeatureForm( QgsVectorLayer *l, QgsFeature &f, bool updateFeatureOnly = false );

virtual QDialog* getFeatureForm( QgsVectorLayer *l, QgsFeature &f );
/**
* Returns a feature form for a given feature
*
* @param layer The layer for which the dialog will be created
* @param feature The feature for which the dialog will be created
*
* @return A feature form
*/
virtual QDialog* getFeatureForm( QgsVectorLayer *layer, QgsFeature &feature );

/**
* Access the vector layer tools instance.
* With the help of this you can access methods like addFeature, startEditing
* or stopEditing while giving the user the appropriate dialogs.
*
* @return An instance of the vector layer tools
*/
virtual QgsVectorLayerTools* vectorLayerTools();

/** This method is only needed when using a UI form with a custom widget plugin and calling
* openFeatureForm or getFeatureForm from Python (PyQt4) and you havn't used the info tool first.
Expand All @@ -449,11 +468,13 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
/** Return vector layers in edit mode
* @param modified whether to return only layers that have been modified
* @returns list of layers in legend order, or empty list
* @note added in 1.9 */
* @note added in 1.9
*/
virtual QList<QgsMapLayer *> editableLayers( bool modified = false ) const;

/** Get timeout for timed messages: default of 5 seconds
* @note added in 1.9 */
* @note added in 1.9
*/
virtual int messageTimeout();

signals:
Expand Down
60 changes: 60 additions & 0 deletions src/app/qgsfieldsproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

Expand Down Expand Up @@ -96,9 +97,23 @@ QgsFieldsProperties::QgsFieldsProperties( QgsVectorLayer *layer, QWidget* parent
connect( mDesignerTree, SIGNAL( itemSelectionChanged() ), this, SLOT( onAttributeSelectionChanged() ) );
connect( mFieldsList, SIGNAL( itemSelectionChanged() ), this, SLOT( onAttributeSelectionChanged() ) );

mRelationsList = new DragList( mRelationsFrame );
mRelationsFrameLayout->addWidget( mRelationsList );
mRelationsList->setColumnCount( RelColCount );
mRelationsList->setDragDropMode( QAbstractItemView::DragOnly );
mRelationsList->setSelectionMode( QAbstractItemView::SingleSelection );
mRelationsList->setSelectionBehavior( QAbstractItemView::SelectRows );
mRelationsList->setHorizontalHeaderItem( RelIdCol, new QTableWidgetItem( tr( "Id" ) ) );
mRelationsList->setHorizontalHeaderItem( RelNameCol, new QTableWidgetItem( tr( "Name" ) ) );
mRelationsList->setHorizontalHeaderItem( RelLayerCol, new QTableWidgetItem( tr( "Layer" ) ) );
mRelationsList->setHorizontalHeaderItem( RelFieldCol, new QTableWidgetItem( tr( "Field" ) ) );
mRelationsList->verticalHeader()->hide();

leEditForm->setText( layer->editForm() );
leEditFormInit->setText( layer->editFormInit() );

loadRelations();

updateButtons();
}

Expand Down Expand Up @@ -135,6 +150,10 @@ QTreeWidgetItem *QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeE
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() ) );
break;

case QgsAttributeEditorElement::AeTypeRelation:
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() ) );
break;

case QgsAttributeEditorElement::AeTypeContainer:
{
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Container, widgetDef->name() ) );
Expand Down Expand Up @@ -235,6 +254,40 @@ void QgsFieldsProperties::setRow( int row, int idx, const QgsField &field )
mFieldsList->setItem( row, attrWFSCol, wfsAttrItem );
}

void QgsFieldsProperties::loadRelations()
{
mRelationsList->setRowCount( 0 );

QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );

int idx = 0;

Q_FOREACH( const QgsRelation& relation, relations )
{
mRelationsList->insertRow( idx );

QTableWidgetItem* item = new QTableWidgetItem( relation.name() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
DesignerTreeItemData itemData( DesignerTreeItemData::Relation, QString( "%1" ).arg( relation.id() ) );
item->setData( DesignerTreeRole, itemData.asQVariant() );
mRelationsList->setItem( idx, RelNameCol, item );

item = new QTableWidgetItem( relation.referencingLayer()->name() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelLayerCol, item );

item = new QTableWidgetItem( relation.fieldPairs().first().referencingField() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelFieldCol, item );

item = new QTableWidgetItem( relation.id() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelIdCol, item );

++idx;
}
}

void QgsFieldsProperties::on_mAddItemButton_clicked()
{
QList<QTableWidgetItem*> listItems = mFieldsList->selectedItems();
Expand Down Expand Up @@ -693,6 +746,13 @@ QgsAttributeEditorElement* QgsFieldsProperties::createAttributeEditorWidget( QTr
break;
}

case DesignerTreeItemData::Relation:
{
QgsRelation relation = QgsProject::instance()->relationManager()->relation( itemData.name() );
widgetDef = new QgsAttributeEditorRelation( itemData.name(), relation, parent );
break;
}

case DesignerTreeItemData::Container:
{
QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( itemData.name(), parent );
Expand Down
13 changes: 13 additions & 0 deletions src/app/qgsfieldsproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
enum Type
{
Field,
Relation,
Container
};

Expand Down Expand Up @@ -159,6 +160,8 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
void loadRows();
void setRow( int row, int idx, const QgsField &field );

void loadRelations();

void loadAttributeEditorTree();
QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement* const widgetDef, QTreeWidgetItem* parent );

Expand Down Expand Up @@ -197,6 +200,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
QgsVectorLayer* mLayer;
DesignerTree* mDesignerTree;
DragList* mFieldsList;
DragList* mRelationsList;

// Holds all the first column items (header: id) of the table.
// The index in the list is the fieldIdx, and therefore acts as a mapping
Expand All @@ -219,6 +223,15 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
attrColCount,
};

enum relationColumns
{
RelNameCol = 0,
RelLayerCol,
RelFieldCol,
RelIdCol,
RelColCount
};

static QMap< QgsVectorLayer::EditType, QString > editTypeMap;
static void setupEditTypes();
static QString editTypeButtonText( QgsVectorLayer::EditType type );
Expand Down
19 changes: 19 additions & 0 deletions src/app/qgsprojectproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#include "qgsstylev2managerdialog.h"
#include "qgsvectorcolorrampv2.h"
#include "qgssymbolv2selectordialog.h"
#include "qgsrelationmanagerdialog.h"
#include "qgsrelationmanager.h"
#include "qgisapp.h"

//qt includes
#include <QColorDialog>
Expand Down Expand Up @@ -442,6 +445,20 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
resetPythonMacros();
}

// Initialize relation manager
mRelationManagerDlg = new QgsRelationManagerDialog( QgsProject::instance()->relationManager(), mTabRelations );
mTabRelations->layout()->addWidget( mRelationManagerDlg );

QList<QgsVectorLayer*> vectorLayers;
foreach ( QgsMapLayer* mapLayer, mapLayers.values() )
{
if ( QgsMapLayer::VectorLayer == mapLayer->type() )
{
vectorLayers.append( qobject_cast<QgsVectorLayer*> ( mapLayer ) );
}
}
mRelationManagerDlg->setLayers( vectorLayers );

// Update projection selector (after mLayerSrsId is set)
bool myProjectionEnabled = myRenderer->hasCrsTransformEnabled();
bool onFlyChecked = cbxProjectionEnabled->isChecked();
Expand Down Expand Up @@ -794,6 +811,8 @@ void QgsProjectProperties::apply()
}
QgsProject::instance()->writeEntry( "Macros", "/pythonCode", pythonMacros );

QgsProject::instance()->relationManager()->setRelations( mRelationManagerDlg->relations() );

//todo XXX set canvas color
emit refresh();
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsprojectproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "qgscontexthelp.h"

class QgsMapCanvas;
class QgsRelationManagerDialog;
class QgsStyleV2;

/*! Dialog to set project level properties
Expand Down Expand Up @@ -162,6 +163,7 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui:
void refresh();

private:
QgsRelationManagerDialog *mRelationManagerDlg;
QgsMapCanvas* mMapCanvas;
QgsStyleV2* mStyle;

Expand Down
5 changes: 5 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ SET(QGIS_CORE_SRCS
qgsprovidermetadata.cpp
qgsproviderregistry.cpp
qgspythonrunner.cpp
qgsrelation.cpp
qgsrelationmanager.cpp
qgsrendercontext.cpp
qgsrenderchecker.cpp
qgsrectangle.cpp
Expand Down Expand Up @@ -311,6 +313,7 @@ SET(QGIS_CORE_MOC_HDRS
qgspluginlayer.h
qgsproject.h
qgsrunprocess.h
qgsrelationmanager.h
qgsvectorlayer.h
qgsvectorlayereditbuffer.h
qgsnetworkaccessmanager.h
Expand Down Expand Up @@ -429,6 +432,8 @@ SET(QGIS_CORE_HDRS
qgsrectangle.h
qgsrendercontext.h
qgsrenderchecker.h
qgsrelation.h
qgsrelationmanager.h
qgsrunprocess.h
qgsscalecalculator.h
qgssnapper.h
Expand Down
6 changes: 3 additions & 3 deletions src/core/qgsfeaturerequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh )
mFilterFids = rh.mFilterFids;
if ( rh.mFilterExpression )
{
mFilterExpression = new QgsExpression( rh.mFilterExpression->expression() );
mFilterExpression = new QgsExpression( rh.mFilterExpression->dump() );
}
else
{
Expand Down Expand Up @@ -144,7 +144,7 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )
break;

case QgsFeatureRequest::FilterFid:
if ( feature.id () == mFilterFid )
if ( feature.id() == mFilterFid )
return true;
else
return false;
Expand All @@ -158,7 +158,7 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )
break;

case QgsFeatureRequest::FilterFids:
if ( mFilterFids.contains ( feature.id () ) )
if ( mFilterFids.contains( feature.id() ) )
return true;
else
return false;
Expand Down
1 change: 0 additions & 1 deletion src/core/qgsfeaturerequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ class CORE_EXPORT QgsFeatureRequest
bool acceptFeature( const QgsFeature& feature );

// TODO: in future
// void setFilterExpression(const QString& expression); // using QgsExpression
// void setFilterNativeExpression(con QString& expr); // using provider's SQL (if supported)
// void setLimit(int limit);

Expand Down
29 changes: 19 additions & 10 deletions src/core/qgsproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
#include <deque>
#include <memory>

#include "qgsdatasourceuri.h"
#include "qgsexception.h"
#include "qgslogger.h"
#include "qgsrectangle.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsexception.h"
#include "qgsprojectproperty.h"
#include "qgsprojectfiletransform.h"
#include "qgsprojectversion.h"
#include "qgspluginlayer.h"
#include "qgspluginlayerregistry.h"
#include "qgsdatasourceuri.h"
#include "qgsprojectfiletransform.h"
#include "qgsprojectproperty.h"
#include "qgsprojectversion.h"
#include "qgsrasterlayer.h"
#include "qgsrectangle.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"

#include <QApplication>
#include <QFileInfo>
Expand Down Expand Up @@ -332,7 +333,9 @@ struct QgsProject::Imp


QgsProject::QgsProject()
: imp_( new QgsProject::Imp ), mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
: imp_( new QgsProject::Imp )
, mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
, mRelationManager( new QgsRelationManager( this ) )
{
// Set some default project properties
// XXX THESE SHOULD BE MOVED TO STATUSBAR RELATED SOURCE
Expand All @@ -349,6 +352,7 @@ QgsProject::QgsProject()
QgsProject::~QgsProject()
{
delete mBadLayerHandler;
delete mRelationManager;

// note that std::auto_ptr automatically deletes imp_ when it's destroyed
} // QgsProject dtor
Expand Down Expand Up @@ -717,7 +721,6 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do

} // _getMapLayers


bool QgsProject::addLayer( const QDomElement& layerElem, QList<QDomNode>& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList )
{
QString type = layerElem.attribute( "type" );
Expand Down Expand Up @@ -865,6 +868,7 @@ bool QgsProject::read()

imp_->clear();
mEmbeddedLayers.clear();
mRelationManager->clear();

// now get any properties
_getProperties( *doc, imp_->properties_ );
Expand Down Expand Up @@ -1801,3 +1805,8 @@ QString QgsProject::homePath() const

return pfi.canonicalPath();
}

QgsRelationManager* QgsProject::relationManager() const
{
return mRelationManager;
}
17 changes: 11 additions & 6 deletions src/core/qgsproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class QDomNode;

class QgsMapLayer;
class QgsProjectBadLayerHandler;
class QgsRelationManager;
class QgsVectorLayer;

/** \ingroup core
Expand Down Expand Up @@ -281,32 +282,32 @@ class CORE_EXPORT QgsProject : public QObject
@note added in 1.4 */
void setBadLayerHandler( QgsProjectBadLayerHandler* handler );

/**Returns project file path if layer is embedded from other project file. Returns empty string if layer is not embedded*/
/** Returns project file path if layer is embedded from other project file. Returns empty string if layer is not embedded*/
QString layerIsEmbedded( const QString& id ) const;

/**Creates a maplayer instance defined in an arbitrary project file. Caller takes ownership
/** Creates a maplayer instance defined in an arbitrary project file. Caller takes ownership
@return the layer or 0 in case of error
@note: added in version 1.8
@note not available in python bindings
*/
bool createEmbeddedLayer( const QString& layerId, const QString& projectFilePath, QList<QDomNode>& brokenNodes,
QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList, bool saveFlag = true );

/**Convenience function to set snap settings per layer
/** Convenience function to set snap settings per layer
@note added in version 1.9*/
void setSnapSettingsForLayer( const QString& layerId, bool enabled, QgsSnapper::SnappingType type, QgsTolerance::UnitType unit, double tolerance,
bool avoidIntersection );

/**Convenience function to query snap settings of a layer
/** Convenience function to query snap settings of a layer
@note added in version 1.9*/
bool snapSettingsForLayer( const QString& layerId, bool& enabled, QgsSnapper::SnappingType& type, QgsTolerance::UnitType& units, double& tolerance,
bool& avoidIntersection ) const;

/**Convenience function to set topological editing
/** Convenience function to set topological editing
@note added in version 1.9*/
void setTopologicalEditing( bool enabled );

/**Convenience function to query topological editing status
/** Convenience function to query topological editing status
@note added in version 1.9*/
bool topologicalEditing() const;

Expand All @@ -315,6 +316,8 @@ class CORE_EXPORT QgsProject : public QObject
@note added in version 2.0 */
QString homePath() const;

QgsRelationManager* relationManager() const;

protected:

/** Set error message from read/write operation
Expand Down Expand Up @@ -398,6 +401,8 @@ class CORE_EXPORT QgsProject : public QObject
void snapSettings( QStringList& layerIdList, QStringList& enabledList, QStringList& snapTypeList, QStringList& snapUnitList, QStringList& toleranceUnitList,
QStringList& avoidIntersectionList ) const;

QgsRelationManager* mRelationManager;

}; // QgsProject


Expand Down
258 changes: 258 additions & 0 deletions src/core/qgsrelation.cpp
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()
{

}
227 changes: 227 additions & 0 deletions src/core/qgsrelation.h
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
172 changes: 172 additions & 0 deletions src/core/qgsrelationmanager.cpp
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 );
}
}
66 changes: 66 additions & 0 deletions src/core/qgsrelationmanager.h
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
29 changes: 18 additions & 11 deletions src/core/qgsvectordataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );

/**Returns the possible enum values of an attribute. Returns an empty stringlist if a provider does not support enum types
or if the given attribute is not an enum type.
/**
* Returns the possible enum values of an attribute. Returns an empty stringlist if a provider does not support enum types
* or if the given attribute is not an enum type.
* @param index the index of the attribute
* @param enumList reference to the list to fill
@note: added in version 1.2*/
* @note: added in version 1.2
*/
virtual void enumValues( int index, QStringList& enumList ) { Q_UNUSED( index ); enumList.clear(); }

/**
Expand Down Expand Up @@ -260,7 +262,9 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
int fieldNameIndex( const QString& fieldName ) const;

/**Return a map where the key is the name of the field and the value is its index*/
/**
* Return a map where the key is the name of the field and the value is its index
*/
QMap<QString, int> fieldNameMap() const;

/**
Expand Down Expand Up @@ -313,17 +317,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** Returns a list of available encodings */
static const QStringList &availableEncodings();

/* provider has errors to report
/**
* Provider has errors to report
* @note added in 1.7
*/
bool hasErrors();

/* clear recorded errors
/**
* Clear recorded errors
* @note added in 1.7
*/
void clearErrors();

/* get recorded errors
/**
* Get recorded errors
* @note added in 1.7
*/
QStringList errors();
Expand All @@ -350,13 +357,13 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** should provider fetch also features that don't have geometry? */
bool mFetchFeaturesWithoutGeom;

/**True if geometry should be added to the features in nextFeature calls*/
/** True if geometry should be added to the features in nextFeature calls*/
bool mFetchGeom;

/**List of attribute indices to fetch with nextFeature calls*/
/** List of attribute indices to fetch with nextFeature calls*/
QgsAttributeList mAttributesToFetch;

/**The names of the providers native types*/
/** The names of the providers native types*/
QList< NativeType > mNativeTypes;

void pushError( QString msg );
Expand All @@ -368,7 +375,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** old notation **/
QMap<QString, QVariant::Type> mOldTypeList;

// list of errors
/** list of errors */
QStringList mErrors;

static QStringList smEncodings;
Expand Down
47 changes: 47 additions & 0 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "qgspoint.h"
#include "qgsproviderregistry.h"
#include "qgsrectangle.h"
#include "qgsrelationmanager.h"
#include "qgsrendercontext.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsvectordataprovider.h"
Expand Down Expand Up @@ -176,6 +177,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
}

connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );

connect( QgsProject::instance()->relationManager(), SIGNAL( relationsLoaded() ), this, SLOT( onRelationsLoaded() ) );
} // QgsVectorLayer ctor


Expand Down Expand Up @@ -2117,6 +2120,13 @@ QgsAttributeEditorElement* QgsVectorLayer::attributeEditorElementFromDomElement(
int idx = *( dataProvider()->fieldNameMap() ).find( name );
newElement = new QgsAttributeEditorField( name, idx, parent );
}
else if ( elem.tagName() == "attributeEditorRelation" )
{
// At this time, the relations are not loaded
// So we only grab the id and delegate the rest to onRelationsLoaded()
QString name = elem.attribute( "name" );
newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
}
return newElement;
}

Expand Down Expand Up @@ -3834,6 +3844,23 @@ void QgsVectorLayer::invalidateSymbolCountedFlag()
mSymbolFeatureCounted = false;
}

void QgsVectorLayer::onRelationsLoaded()
{
Q_FOREACH( QgsAttributeEditorElement* elem, mAttributeEditorElements )
{
if ( elem->type() == QgsAttributeEditorElement::AeTypeContainer )
{
QgsAttributeEditorContainer* cont = dynamic_cast< QgsAttributeEditorContainer* >( elem );
QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
Q_FOREACH( QgsAttributeEditorElement* relElem, relations )
{
QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
rel->init( QgsProject::instance()->relationManager() );
}
}
}
}

QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
{
const QgsFields &fields = pendingFields();
Expand All @@ -3855,6 +3882,11 @@ QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
return mValueRelations[fieldName];
}

QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
{
return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
}

QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
{
return mAttributeEditorElements;
Expand Down Expand Up @@ -4057,3 +4089,18 @@ bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString errorMsg )

return readSymbology( myRoot, errorMsg );
}


QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
{
QDomElement elem = doc.createElement( "attributeEditorRelation" );
elem.setAttribute( "name", mName );
elem.setAttribute( "relation", mRelation.id() );
return elem;
}

bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
{
mRelation = relationManager->relation( mRelationId );
return mRelation.isValid();
}
56 changes: 56 additions & 0 deletions src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "qgsfield.h"
#include "qgssnapper.h"
#include "qgsfield.h"
#include "qgsrelation.h"

class QPainter;
class QImage;
Expand All @@ -44,6 +45,8 @@ class QgsGeometryVertexIndex;
class QgsLabel;
class QgsMapToPixel;
class QgsRectangle;
class QgsRelation;
class QgsRelationManager;
class QgsVectorDataProvider;
class QgsSingleSymbolRendererV2;
class QgsRectangle;
Expand All @@ -68,6 +71,7 @@ class CORE_EXPORT QgsAttributeEditorElement : public QObject
{
AeTypeContainer,
AeTypeField,
AeTypeRelation,
AeTypeInvalid
};

Expand Down Expand Up @@ -121,6 +125,37 @@ class CORE_EXPORT QgsAttributeEditorField : public QgsAttributeEditorElement
int mIdx;
};

/** @note Added in 2.1 */
class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement
{
public:
QgsAttributeEditorRelation( QString name , const QString relationId, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
, mRelationId( relationId ) {}

QgsAttributeEditorRelation( QString name , const QgsRelation& relation, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
, mRelationId( relation.id() )
, mRelation( relation ) {}

~QgsAttributeEditorRelation() {}

virtual QDomElement toDomElement( QDomDocument& doc ) const;
const QgsRelation& relation() const { return mRelation; }

/**
* Initializes the relation from the id
*
* @param relManager The relation manager to use for the initialization
* @return true if the relation was found in the relationmanager
*/
bool init( QgsRelationManager* relManager );

private:
QString mRelationId;
QgsRelation mRelation;
};

/** @note added in 1.7 */
struct CORE_EXPORT QgsVectorJoinInfo
{
Expand Down Expand Up @@ -1202,6 +1237,22 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
**/
ValueRelationData &valueRelation( int idx );

/**
* Get relations, where the foreign key is on this layer
*
* @param idx Only get relations, where idx forms part of the foreign key
* @return A list of relations
*/
QList<QgsRelation> referencingRelations( int idx );

/**
* Get relations, where the foreign key is on another layer, referencing this layer
*
* @param idx Only get relations, where idx forms part of the referenced key
* @return A list of relations
*/
QList<QgsRelation> referencedRelations( int idx );

/**access date format
* @note added in 1.9
*/
Expand Down Expand Up @@ -1446,6 +1497,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
void committedAttributeValuesChanges( const QString& layerId, const QgsChangedAttributesMap& changedAttributesValues );
void committedGeometriesChanges( const QString& layerId, const QgsGeometryMap& changedGeometries );

void saveLayerToProject();

/** Emitted when the font family defined for labeling layer is not found on system
* @note added in 1.9
*/
Expand All @@ -1460,6 +1513,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Signal emitted when setLayerTransparency() is called */
void layerTransparencyChanged( int layerTransparency );

private slots:
void onRelationsLoaded();

protected:
/** Set the extent */
void setExtent( const QgsRectangle &rect );
Expand Down
5 changes: 3 additions & 2 deletions src/core/qgsvectorlayercache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ QgsVectorLayerCache::QgsVectorLayerCache( QgsVectorLayer* layer, int cacheSize,
mCache.setMaxCost( cacheSize );

connect( mLayer, SIGNAL( featureDeleted( QgsFeatureId ) ), SLOT( featureDeleted( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), SLOT( featureAdded( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), SLOT( onFeatureAdded( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( layerDeleted() ), SLOT( layerDeleted() ) );

setCacheGeometry( true );
Expand Down Expand Up @@ -200,7 +200,7 @@ void QgsVectorLayerCache::featureDeleted( QgsFeatureId fid )
mCache.remove( fid );
}

void QgsVectorLayerCache::featureAdded( QgsFeatureId fid )
void QgsVectorLayerCache::onFeatureAdded( QgsFeatureId fid )
{
if ( mFullCache )
{
Expand All @@ -212,6 +212,7 @@ void QgsVectorLayerCache::featureAdded( QgsFeatureId fid )
QgsFeature feat;
featureAtId( fid, feat );
}
emit( featureAdded( fid ) );
}

void QgsVectorLayerCache::attributeAdded( int field )
Expand Down
11 changes: 10 additions & 1 deletion src/core/qgsvectorlayercache.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,19 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject
*/
void attributeValueChanged( const QgsFeatureId& fid, const int& field, const QVariant &value );

/**
* Is emitted, when a new feature has been added to the layer and this cache.
* You should connect to this signal instead of the layers', if you want to be sure
* that this cache has updated information for the new feature
*
* @param fid The featureid of the changed feature
*/
void featureAdded( QgsFeatureId fid );

private slots:
void onAttributeValueChanged( QgsFeatureId fid, int field, const QVariant& value );
void featureDeleted( QgsFeatureId fid );
void featureAdded( QgsFeatureId fid );
void onFeatureAdded( QgsFeatureId fid );
void attributeAdded( int field );
void attributeDeleted( int field );
void geometryChanged( QgsFeatureId fid, QgsGeometry& geom );
Expand Down
121 changes: 71 additions & 50 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,47 @@ editorwidgets/core/qgseditorconfigwidget.cpp
editorwidgets/core/qgseditorwidgetfactory.cpp
editorwidgets/core/qgseditorwidgetregistry.cpp
editorwidgets/core/qgseditorwidgetwrapper.cpp
editorwidgets/qgsrelationreferencewidget.cpp
editorwidgets/qgsrelationreferencefactory.cpp
editorwidgets/qgsrelreferenceconfigdlg.cpp

qgisgui.cpp
qgisinterface.cpp
qgsannotationitem.cpp
qgsattributeeditor.cpp
qgsattributedialog.cpp
qgsbusyindicatordialog.cpp
qgslegendinterface.cpp
qgspluginmanagerinterface.cpp
qgsattributeeditor.cpp
qgsattributeeditorcontext.cpp
qgsblendmodecombobox.cpp
qgsbusyindicatordialog.cpp
qgscharacterselectdialog.cpp
qgscollapsiblegroupbox.cpp
qgscolorbutton.cpp
qgscolordialog.cpp
qgscomposerview.cpp
qgscomposerruler.cpp
qgscomposerview.cpp
qgscredentialdialog.cpp
qgscursors.cpp
qgsdatadefinedbutton.cpp
qgsdetaileditemdata.cpp
qgsdetaileditemdelegate.cpp
qgsdetaileditemwidget.cpp
qgsdetaileditemdata.cpp
qgsdialog.cpp
qgsencodingfiledialog.cpp
qgserrordialog.cpp
qgsfiledropedit.cpp
qgsexpressionbuilderdialog.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionhighlighter.cpp
qgsexpressionselectiondialog.cpp
qgsfeatureselectiondlg.cpp
qgsfieldvalidator.cpp
qgsfiledropedit.cpp
qgsfilterlineedit.cpp
qgsformannotationitem.cpp
qgshtmlannotationitem.cpp
qgshighlight.cpp
qgsgenericprojectionselector.cpp
qgshighlight.cpp
qgshtmlannotationitem.cpp
qgslegendinterface.cpp
qgsludialog.cpp
qgsmanageconnectionsdialog.cpp
qgsmapcanvas.cpp
qgsmapcanvasitem.cpp
Expand All @@ -99,33 +111,31 @@ qgsmessagebar.cpp
qgsmessagebaritem.cpp
qgsmessageviewer.cpp
qgsmessagelogviewer.cpp
qgsmessageviewer.cpp
qgsnewhttpconnection.cpp
qgsnewvectorlayerdialog.cpp
qgsnumericsortlistviewitem.cpp
qgsoptionsdialogbase.cpp
qgscredentialdialog.cpp
qgsattributeeditorcontext.cpp
qgsowssourceselect.cpp
qgspluginmanagerinterface.cpp
qgsprojectbadlayerguihandler.cpp
qgsprojectionselector.cpp
qgsrasterlayersaveasdialog.cpp
qgsquerybuilder.cpp
qgsrasterformatsaveoptionswidget.cpp
qgsrasterlayersaveasdialog.cpp
qgsrasterpyramidsoptionswidget.cpp
qgsrelationadddlg.cpp
qgsrelationeditor.cpp
qgsrelationmanagerdialog.cpp
qgsrubberband.cpp
qgsscalecombobox.cpp
qgssearchquerybuilder.cpp
qgssublayersdialog.cpp
qgssvgannotationitem.cpp
qgstextannotationitem.cpp
qgsvertexmarker.cpp
qgsludialog.cpp
qgssearchquerybuilder.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionbuilderdialog.cpp
qgsexpressionselectiondialog.cpp
qgsexpressionhighlighter.cpp
qgsquerybuilder.cpp
qgscollapsiblegroupbox.cpp
qgsfilterlineedit.cpp
qgssublayersdialog.cpp
)

IF (WITH_TOUCH)
Expand Down Expand Up @@ -191,56 +201,62 @@ attributetable/qgsvectorlayerselectionmanager.h
editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorwidgetwrapper.h
editorwidgets/qgsrelationreferencewidget.h
editorwidgets/qgsrelreferenceconfigdlg.h

qgisinterface.h
qgsattributedialog.h
qgsattributeeditor.h
qgsblendmodecombobox.h
qgsbusyindicatordialog.h
qgscharacterselectdialog.h
qgscollapsiblegroupbox.h
qgscolordialog.h
qgscomposerview.h
qgscredentialdialog.h
qgsdatadefinedbutton.h
qgsdetaileditemdelegate.h
qgsdetaileditemwidget.h
qgsdialog.h
qgslegendinterface.h
qgspluginmanagerinterface.h
qgisinterface.h
qgsencodingfiledialog.h
qgserrordialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsfeatureselectiondlg.h
qgsfieldvalidator.h
qgsfilterlineedit.h
qgsformannotationitem.h
qgshtmlannotationitem.h
qgsgenericprojectionselector.h
qgshtmlannotationitem.h
qgslegendinterface.h
qgslonglongvalidator.h
qgsludialog.h
qgsmanageconnectionsdialog.h
qgsmapcanvas.h
qgsmapoverviewcanvas.h
qgsmaptoolemitpoint.h
qgsmaptoolidentify.h
qgsmessagebaritem.h
qgsmessagebar.h
qgsmessageviewer.h
qgsmessagelogviewer.h
qgsmessageviewer.h
qgsnewhttpconnection.h
qgsnewvectorlayerdialog.h
qgsoptionsdialogbase.h
qgscredentialdialog.h
qgsowssourceselect.h
qgspluginmanagerinterface.h
qgsprojectbadlayerguihandler.h
qgsprojectionselector.h
qgsrasterlayersaveasdialog.h
qgsquerybuilder.h
qgsrasterformatsaveoptionswidget.h
qgsrasterlayersaveasdialog.h
qgsrasterpyramidsoptionswidget.h
qgsludialog.h
qgsprojectbadlayerguihandler.h
qgslonglongvalidator.h
qgssearchquerybuilder.h
qgsrelationadddlg.h
qgsrelationeditor.h
qgsrelationmanagerdialog.h
qgsscalecombobox.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsquerybuilder.h
qgscollapsiblegroupbox.h
qgsfilterlineedit.h
qgssearchquerybuilder.h
qgssublayersdialog.h
)

Expand All @@ -251,21 +267,33 @@ QT4_WRAP_CPP(QGIS_GUI_MOC_SRCS ${QGIS_GUI_MOC_HDRS})
SET(QGIS_GUI_HDRS
qgisgui.h
qgisinterface.h
qgsattributeeditor.h
qgsattributedialog.h
qgsattributeeditorcontext.h
qgsbusyindicatordialog.h
qgscharacterselectdialog.h
qgscollapsiblegroupbox.h
qgscolordialog.h
qgscredentialdialog.h
qgscursors.h
qgsdatadefinedbutton.h
qgsencodingfiledialog.h
qgsexpressionbuilderdialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsfeatureselectiondlg.h
qgsfieldvalidator.h
qgsfiledropedit.h
qgsfilterlineedit.h
qgsgenericprojectionselector.h
qgshighlight.h
qgsmapcanvas.h
qgsmapcanvasitem.h
qgsmapcanvasmap.h
qgsmapcanvassnapper.h
qgsmapoverviewcanvas.h
qgsmaptip.h
qgsmaptool.h
qgsmaptoolemitpoint.h
qgsmaptoolidentify.h
Expand All @@ -275,25 +303,15 @@ qgsmessagebaritem.h
qgsmessagebar.h
qgsmessageviewer.h
qgsoptionsdialogbase.h
qgscredentialdialog.h
qgsowssourceselect.h
qgsprojectionselector.h
qgsrelationeditor.h
qgsrubberband.h
qgsvertexmarker.h
qgsmaptip.h
qgsscalecombobox.h
qgsblendmodecombobox.h
qgssearchquerybuilder.h
qgsattributeeditor.h
qgsattributedialog.h
qgsfieldvalidator.h
qgsexpressionbuilderwidget.h
qgsexpressionbuilderdialog.h
qgsexpressionselectiondialog.h
qgsexpressionhighlighter.h
qgscollapsiblegroupbox.h
qgsfilterlineedit.h
qgssublayersdialog.h
qgsvectorlayertools.h
qgsvertexmarker.h
qgsnumericsortlistviewitem.h
qgsannotationitem.h
qgstextannotationitem.h
Expand All @@ -319,6 +337,9 @@ editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetfactory.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorwidgetwrapper.h
editorwidgets/qgsrelationreferencefactory.h
editorwidgets/qgsrelationreferencewidget.h
editorwidgets/qgsrelreferenceconfigdlg.h

raster/qgsrasterrendererwidget.h
)
Expand Down
6 changes: 2 additions & 4 deletions src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@
#include "qgsmessagelog.h"


QgsEditorWidgetRegistry *QgsEditorWidgetRegistry::sInstance = 0;
QgsEditorWidgetRegistry QgsEditorWidgetRegistry::sInstance;

QgsEditorWidgetRegistry* QgsEditorWidgetRegistry::instance()
{
if( !sInstance )
sInstance = new QgsEditorWidgetRegistry();
return sInstance;
return &sInstance;
}

QgsEditorWidgetRegistry::QgsEditorWidgetRegistry()
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/core/qgseditorwidgetregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class GUI_EXPORT QgsEditorWidgetRegistry : public QObject

private:
QMap<QString, QgsEditorWidgetFactory*> mWidgetFactories;
static QgsEditorWidgetRegistry *sInstance;
static QgsEditorWidgetRegistry sInstance;
};


Expand Down
59 changes: 59 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencefactory.cpp
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() );
}
79 changes: 79 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencefactory.h
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
202 changes: 202 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencewidget.cpp
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;
}
63 changes: 63 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencewidget.h
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
78 changes: 78 additions & 0 deletions src/gui/editorwidgets/qgsrelreferenceconfigdlg.cpp
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;
}
35 changes: 35 additions & 0 deletions src/gui/editorwidgets/qgsrelreferenceconfigdlg.h
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
30 changes: 19 additions & 11 deletions src/gui/qgisinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class QgsLegendInterface;
class QgsPluginManagerInterface;
class QgsFeature;
class QgsMessageBar;
class QgsVectorLayerTools;

#include <QObject>
#include <QFont>
Expand Down Expand Up @@ -217,7 +218,7 @@ class GUI_EXPORT QgisInterface : public QObject
/** Return the message bar of the main app */
virtual QgsMessageBar * messageBar() = 0;

/**Return mainwindows / composer views of running composer instances (currently only one)*/
/** Return mainwindows / composer views of running composer instances (currently only one) */
virtual QList<QgsComposerView*> activeComposers() = 0;

/** Create a new composer
Expand Down Expand Up @@ -530,13 +531,17 @@ class GUI_EXPORT QgisInterface : public QObject
virtual QAction *actionCheckQgisVersion() = 0;
virtual QAction *actionAbout() = 0;

//! Open feature form
// returns true when dialog was accepted
// @added in 1.6
/**
* Open feature form
* @return true when dialog was accepted
* @note added in 1.6
*/
virtual bool openFeatureForm( QgsVectorLayer *l, QgsFeature &f, bool updateFeatureOnly = false ) = 0;

virtual QDialog* getFeatureForm( QgsVectorLayer *l, QgsFeature &f ) = 0;

virtual QgsVectorLayerTools* vectorLayerTools() = 0;

virtual void preloadForm( QString uifile ) = 0;

/** Return vector layers in edit mode
Expand All @@ -555,26 +560,29 @@ class GUI_EXPORT QgisInterface : public QObject
*/
void currentLayerChanged( QgsMapLayer * layer );

/**This signal is emitted when a new composer instance has been created
/**
* This signal is emitted when a new composer instance has been created
* @note added in 1.4
*/
void composerAdded( QgsComposerView* v );

/**This signal is emitted before a new composer instance is going to be removed
/**
* This signal is emitted before a new composer instance is going to be removed
* @note added in 1.4
*/
void composerWillBeRemoved( QgsComposerView* v );
/**This signal is emitted when the initialization is complete
* @note added in version 1.6
*/
/**
* This signal is emitted when the initialization is complete
* @note added in 1.6
*/
void initializationCompleted();
/** emitted when a project file is successfully read
@note
This is useful for plug-ins that store properties with project files. A
plug-in can connect to this signal. When it is emitted, the plug-in
knows to then check the project properties for any relevant state.
Added in v1.6
Added in 1.6
*/
void projectRead();
/** emitted when starting an entirely new project
Expand All @@ -585,7 +593,7 @@ class GUI_EXPORT QgisInterface : public QObject
it's probably more semantically correct to have an entirely separate
signal for when this happens.
Added in v1.6
Added in 1.6
*/
void newProjectCreated();
};
Expand Down
21 changes: 19 additions & 2 deletions src/gui/qgsattributedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsrelationeditor.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsattributeeditor.h"
#include "qgshighlight.h"
#include "qgsexpression.h"
Expand Down Expand Up @@ -266,6 +267,22 @@ void QgsAttributeDialog::init()
}
}

QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );

foreach ( const QgsRelation& relation, relations )
{
relation.id();

QWidget *myWidget = QgsRelationEditorWidget::createRelationEditor( relation, *mFeature, mContext );
myWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
if ( !myWidget )
continue;

mypInnerLayout->addWidget( myWidget, index, 0, 1, 2 );
mypInnerLayout->setRowStretch( index, 1 );
++index;
}

// Set focus to first widget in list, to help entering data without moving the mouse.
if ( mypInnerLayout->rowCount() > 0 )
{
Expand All @@ -274,7 +291,7 @@ void QgsAttributeDialog::init()
widget->setFocus( Qt::OtherFocusReason );
}

QSpacerItem *mypSpacer = new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding );
QSpacerItem *mypSpacer = new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
mypInnerLayout->addItem( mypSpacer, mypInnerLayout->rowCount() + 1, 0 );
}
else
Expand Down
29 changes: 21 additions & 8 deletions src/gui/qgsattributedialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,44 @@ class QgsFeature;
class QgsField;
class QgsHighlight;
class QgsVectorLayer;
class QgsVectorLayerTools;

class GUI_EXPORT QgsAttributeDialog : public QObject
{
Q_OBJECT

public:
/**
* @brief QgsAttributeDialog
* @param vl
* @param thepFeature
* @param featureOwner
* @param myDa
* @param parent
* @param showDialogButtons
* Create an attribute dialog for a given layer and feature
*
* @param vl The layer for which the dialog will be generated
* @param thepFeature A feature for which the dialog will be generated
* @param featureOwner Set to true, if the dialog should take ownership of the feature
* @param myDa A QgsDistanceArea which will be used for expressions
* @param parent A parent widget for the dialog
* @param showDialogButtons True: Show the dialog buttons accept/cancel
*
* @deprecated
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true );

/**
* Create an attribute dialog for a given layer and feature
*
* @param vl The layer for which the dialog will be generated
* @param thepFeature A feature for which the dialog will be generated
* @param featureOwner Set to true, if the dialog should take ownership of the feature
* @param parent A parent widget for the dialog
* @param showDialogButtons True: Show the dialog buttons accept/cancel
* @param context The context in which this dialog is created
*
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget* parent = 0, bool showDialogButtons = true, QgsAttributeEditorContext context = QgsAttributeEditorContext() );

~QgsAttributeDialog();

/** Saves the size and position for the next time
* this dialog box was used.
* this dialog box will be used.
*/
void saveGeometry();

Expand Down
14 changes: 13 additions & 1 deletion src/gui/qgsattributeeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include "qgseditorwidgetwrapper.h"

#include "qgsattributedialog.h"
#include "qgsattributeeditorcontext.h"
#include "qgsattributeeditor.h"
#include "qgsattributeeditorcontext.h"
#include "qgscategorizedsymbolrendererv2.h"
#include "qgscolorbutton.h"
#include "qgsexpression.h"
Expand All @@ -32,6 +32,8 @@
#include "qgslonglongvalidator.h"
#include "qgsmaplayerregistry.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsrelationeditor.h"
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

Expand Down Expand Up @@ -1430,6 +1432,16 @@ QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElemen
break;
}

case QgsAttributeEditorElement::AeTypeRelation:
{
const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );

newWidget = QgsRelationEditorWidget::createRelationEditor( relDef->relation(), feat, context );
labelText = QString::null;
labelOnTop = true;
break;
}

case QgsAttributeEditorElement::AeTypeContainer:
{
const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
Expand Down
3 changes: 2 additions & 1 deletion src/gui/qgsattributeeditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <QGridLayout>

#include "qgsfeature.h"
#include "qgsrelationmanager.h"

class QObject;
class QWidget;
Expand All @@ -31,6 +32,7 @@ class QListWidget;
class QgsAttributeEditorContext;
class QgsAttributeEditorElement;
class QgsDualView;
class QgsRelationManager;
class QgsVectorLayer;

/* \brief create attribute widget for editing */
Expand Down Expand Up @@ -67,7 +69,6 @@ class GUI_EXPORT QgsAttributeEditor : public QObject
*
*/
static QWidget* createAttributeEditor( QWidget* parent, QWidget* editor, QgsVectorLayer* vl, int idx, const QVariant& value );

/**
* Creates or prepares a attributre editor widget
* @param parent The parent object
Expand Down
40 changes: 40 additions & 0 deletions src/gui/qgsfeatureselectiondlg.cpp
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();
}


Loading