Skip to content

Commit

Permalink
Initial table join prototype
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/branches/table_join_branch@13934 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Jul 19, 2010
1 parent 2db428e commit 9d188a5
Show file tree
Hide file tree
Showing 20 changed files with 1,080 additions and 200 deletions.
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@ SET(QGIS_APP_SRCS
qgisappinterface.cpp
qgsabout.cpp
qgsaddattrdialog.cpp
qgsaddjoindialog.cpp
qgsannotationwidget.cpp
qgsattributeactiondialog.cpp
qgsattributedialog.cpp
Expand Down Expand Up @@ -130,6 +131,7 @@ SET (QGIS_APP_MOC_HDRS
qgsabout.h
qgsaddattrdialog.h
qgsdisplayangle.h
qgsaddjoindialog.h
qgsannotationwidget.h
qgsattributeactiondialog.h
qgsattributedialog.h
Expand Down
2 changes: 1 addition & 1 deletion src/app/attributetable/qgsattributetablemodel.cpp
Expand Up @@ -217,7 +217,7 @@ void QgsAttributeTableModel::loadLayer()
rect = QgisApp::instance()->mapCanvas()->extent();
}

mLayer->select( mAttributes, rect, false );
mLayer->select( QgsAttributeList(), rect, false );

for ( int i = 0; mLayer->nextFeature( f ); ++i )
{
Expand Down
131 changes: 131 additions & 0 deletions src/app/qgsaddjoindialog.cpp
@@ -0,0 +1,131 @@
/***************************************************************************
qgsaddjoindialog.cpp
--------------------
begin : July 10, 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at sourcepole 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 "qgsaddjoindialog.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

QgsAddJoinDialog::QgsAddJoinDialog( QgsVectorLayer* layer, QWidget * parent, Qt::WindowFlags f ): QDialog( parent, f ), mLayer( layer )
{
setupUi( this );

if( !mLayer )
{
return;
}

//insert possible vector layers into mJoinLayerComboBox

mJoinLayerComboBox->blockSignals( true );
const QMap<QString, QgsMapLayer*>& layerList = QgsMapLayerRegistry::instance()->mapLayers();
QMap<QString, QgsMapLayer*>::const_iterator layerIt = layerList.constBegin();
for(; layerIt != layerList.constEnd(); ++layerIt )
{
QgsMapLayer* currentLayer = layerIt.value();
if( currentLayer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* currentVectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
if( currentVectorLayer && currentVectorLayer != mLayer )
{
if( currentVectorLayer->dataProvider() && currentVectorLayer->dataProvider()->supportsSubsetString() )
mJoinLayerComboBox->addItem( currentLayer->name(), QVariant(currentLayer->getLayerID() ) );
}
}
}
mJoinLayerComboBox->blockSignals( false );
on_mJoinLayerComboBox_currentIndexChanged( mJoinLayerComboBox->currentIndex() );

//insert possible target fields
const QgsFieldMap& layerFieldMap = mLayer->pendingFields();
QgsFieldMap::const_iterator fieldIt = layerFieldMap.constBegin();
for(; fieldIt != layerFieldMap.constEnd(); ++fieldIt )
{
mTargetFieldComboBox->addItem(fieldIt.value().name(), fieldIt.key() );
}
}

QgsAddJoinDialog::~QgsAddJoinDialog()
{
}

QString QgsAddJoinDialog::joinedLayerId() const
{
return mJoinLayerComboBox->itemData( mJoinLayerComboBox->currentIndex() ).toString();
}

int QgsAddJoinDialog::joinField() const
{
return mJoinFieldComboBox->itemData( mJoinFieldComboBox->currentIndex() ).toInt();
}

QString QgsAddJoinDialog::joinFieldName() const
{
return mJoinFieldComboBox->itemText( mJoinFieldComboBox->currentIndex() );
}

int QgsAddJoinDialog::targetField() const
{
return mTargetFieldComboBox->itemData( mTargetFieldComboBox->currentIndex() ).toInt();
}

QString QgsAddJoinDialog::targetFieldName() const
{
return mTargetFieldComboBox->itemText( mTargetFieldComboBox->currentIndex() );
}

bool QgsAddJoinDialog::createAttributeIndex() const
{
return mCreateIndexCheckBox->isChecked();
}

void QgsAddJoinDialog::on_mJoinLayerComboBox_currentIndexChanged ( int index )
{
mJoinFieldComboBox->clear();
QString layerId = mJoinLayerComboBox->itemData( index ).toString();
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
if( !layer )
{
return;
}
QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( layer );
if( !vLayer )
{
return;
}

const QgsFieldMap& layerFieldMap = vLayer->pendingFields();
QgsFieldMap::const_iterator fieldIt = layerFieldMap.constBegin();
for(; fieldIt != layerFieldMap.constEnd(); ++fieldIt )
{
mJoinFieldComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
}

//does provider support creation of attribute indices?
QgsVectorDataProvider* dp = vLayer->dataProvider();
if( dp && (dp->capabilities() & QgsVectorDataProvider::CreateAttributeIndex) )
{
mCreateIndexCheckBox->setEnabled( true );
mCreateIndexCheckBox->setChecked( true );
}
else
{
mCreateIndexCheckBox->setEnabled( false );
mCreateIndexCheckBox->setChecked( false );
}
}
55 changes: 55 additions & 0 deletions src/app/qgsaddjoindialog.h
@@ -0,0 +1,55 @@
/***************************************************************************
qgsaddjoindialog.h
------------------
begin : July 10, 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at sourcepole 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 QGSADDJOINDIALOG_H
#define QGSADDJOINDIALOG_H

#include "ui_qgsaddjoindialogbase.h"
class QgsVectorLayer;

class QgsAddJoinDialog: public QDialog, private Ui::QgsAddJoinDialogBase
{
Q_OBJECT
public:
QgsAddJoinDialog( QgsVectorLayer* layer, QWidget * parent = 0, Qt::WindowFlags f = 0 );
~QgsAddJoinDialog();

//retrieve results

/**Get the id of the layer to join*/
QString joinedLayerId() const;
/**Returns the index of the join field*/
int joinField() const;
/**Returns the name of the join field*/
QString joinFieldName() const;
/**Returns the index of the target field (join-to field)*/
int targetField() const;
/**Returns the name of the target field (join-to field)*/
QString targetFieldName() const;
/**Returns true if user wants to create an attribute index on the join field*/
bool createAttributeIndex() const;

private slots:
void on_mJoinLayerComboBox_currentIndexChanged ( int index );

private:
/**Target layer*/
QgsVectorLayer* mLayer;
};


#endif // QGSADDJOINDIALOG_H
72 changes: 72 additions & 0 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -21,6 +21,7 @@
#include <limits>

#include "qgisapp.h"
#include "qgsaddjoindialog.h"
#include "qgsapplication.h"
#include "qgsattributeactiondialog.h"
#include "qgsapplydialog.h"
Expand All @@ -33,6 +34,7 @@
#include "qgslabel.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgspluginmetadata.h"
#include "qgspluginregistry.h"
#include "qgsproject.h"
Expand Down Expand Up @@ -132,6 +134,13 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

connect( sliderTransparency, SIGNAL( valueChanged( int ) ), this, SLOT( sliderTransparency_valueChanged( int ) ) );

//insert existing join info
QList< QgsVectorJoinInfo > joins = layer->vectorJoins();
for( int i = 0; i < joins.size(); ++i )
{
addJoinToTreeWidget( joins[i] );
}

//for each overlay plugin create a new tab
int position;
QList<QgsVectorOverlayPlugin*> overlayPluginList = overlayPlugins();
Expand Down Expand Up @@ -1160,6 +1169,69 @@ void QgsVectorLayerProperties::setUsingNewSymbology( bool useNewSymbology )
updateSymbologyPage();
}

void QgsVectorLayerProperties::on_mButtonAddJoin_clicked()
{
QgsAddJoinDialog d( layer );
if( d.exec() == QDialog::QDialog::Accepted )
{
QgsVectorJoinInfo info;
info.targetField = d.targetField();
info.joinLayerId = d.joinedLayerId();
info.joinField = d.joinField();
if( layer )
{
//create attribute index if possible. Todo: ask user if this should be done (e.g. in QgsAddJoinDialog)
if( d.createAttributeIndex() )
{
QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( info.joinLayerId ) );
if( joinLayer )
{
joinLayer->dataProvider()->createAttributeIndex( info.joinField );
}
}

layer->addJoin( info );
loadRows(); //update attribute tab
addJoinToTreeWidget( info );
}
}
}

void QgsVectorLayerProperties::addJoinToTreeWidget( QgsVectorJoinInfo& join )
{
QTreeWidgetItem* joinItem = new QTreeWidgetItem();

QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join.joinLayerId ) );
if( !joinLayer )
{
return;
}

joinItem->setText( 0, joinLayer->name() );
joinItem->setData( 0, Qt::UserRole, join.joinLayerId );
QString joinFieldName = joinLayer->pendingFields().value( join.joinField ).name();
QString targetFieldName = layer->pendingFields().value( join.targetField ).name();
joinItem->setText( 1, joinFieldName );
joinItem->setData( 1, Qt::UserRole, join.joinField );
joinItem->setText( 2, targetFieldName );
joinItem->setData( 2, Qt::UserRole, join.targetField );

mJoinTreeWidget->addTopLevelItem( joinItem );
}

void QgsVectorLayerProperties::on_mButtonRemoveJoin_clicked()
{
QTreeWidgetItem* currentJoinItem = mJoinTreeWidget->currentItem();
if( !layer || !currentJoinItem )
{
return;
}

layer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
loadRows();
mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
}

void QgsVectorLayerProperties::useNewSymbology()
{
int res = QMessageBox::question( this, tr( "Symbology" ),
Expand Down
6 changes: 6 additions & 0 deletions src/app/qgsvectorlayerproperties.h
Expand Up @@ -116,6 +116,9 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
void useNewSymbology();
void setUsingNewSymbology( bool useNewSymbology );

void on_mButtonAddJoin_clicked();
void on_mButtonRemoveJoin_clicked();

signals:

/** emitted when changes to layer were saved to update legend */
Expand Down Expand Up @@ -170,6 +173,9 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
/**Buffer pixmap which takes the picture of renderers before they are assigned to the vector layer*/
//QPixmap bufferPixmap;

/**Adds a new join to mJoinTreeWidget*/
void addJoinToTreeWidget( QgsVectorJoinInfo& join );

static QMap< QgsVectorLayer::EditType, QString > editTypeMap;
static void setupEditTypes();
static QString editTypeButtonText( QgsVectorLayer::EditType type );
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsdataprovider.h
Expand Up @@ -113,7 +113,7 @@ class CORE_EXPORT QgsDataProvider : public QObject
* that can be used by the data provider to create a subset.
* Must be implemented in the dataprovider.
*/
virtual bool setSubsetString( QString subset )
virtual bool setSubsetString( QString subset, bool updateFeatureCount = true )
{
// NOP by default
Q_UNUSED( subset );
Expand Down
18 changes: 17 additions & 1 deletion src/core/qgsproject.cpp
Expand Up @@ -677,6 +677,7 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
bool returnStatus = true;

emit layerLoaded( 0, nl.count() );
QList<QgsVectorLayer*> vLayerList; //collect

for ( int i = 0; i < nl.count(); i++ )
{
Expand Down Expand Up @@ -716,6 +717,11 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
if ( mapLayer->readXML( node ) )
{
mapLayer = QgsMapLayerRegistry::instance()->addMapLayer( mapLayer );
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
if( vLayer )
{
vLayerList.push_back( vLayer );
}
}
else
{
Expand All @@ -727,10 +733,20 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do

brokenNodes.push_back( node );
}

emit layerLoaded( i + 1, nl.count() );
}

//Update field map of layers with joins.
//Needs to be done here once all dependent layers are loaded
QList<QgsVectorLayer*>::iterator vIt = vLayerList.begin();
for(; vIt != vLayerList.end(); ++vIt )
{
if( (*vIt)->vectorJoins().size() > 0 )
{
(*vIt)->updateFieldMap();
}
}

return qMakePair( returnStatus, brokenNodes );

} // _getMapLayers
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Expand Up @@ -126,6 +126,11 @@ bool QgsVectorDataProvider::createSpatialIndex()
return false;
}

bool QgsVectorDataProvider::createAttributeIndex( int field )
{
return true;
}

int QgsVectorDataProvider::capabilities() const
{
return QgsVectorDataProvider::NoCapabilities;
Expand Down

0 comments on commit 9d188a5

Please sign in to comment.