Skip to content
Permalink
Browse files

[FEATURE]: experimental table join support refactored and ported from…

… branch to trunk

git-svn-id: http://svn.osgeo.org/qgis/trunk@15155 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent
mhugent committed Feb 11, 2011
1 parent 9f1a59f commit f1a655f4809f083a10e1ca88738e91a8e3b6cd26
@@ -269,6 +269,7 @@
<file>themes/default/propertyicons/digitising.png</file>
<file>themes/default/propertyicons/general.png</file>
<file>themes/default/propertyicons/histogram.png</file>
<file>themes/default/propertyicons/join.png</file>
<file>themes/default/propertyicons/labels.png</file>
<file>themes/default/propertyicons/locale.png</file>
<file>themes/default/propertyicons/map_tools.png</file>
Binary file not shown.
@@ -4,6 +4,7 @@ SET(QGIS_APP_SRCS
qgisappinterface.cpp
qgsabout.cpp
qgsaddattrdialog.cpp
qgsaddjoindialog.cpp
qgsannotationwidget.cpp
qgsattributeactiondialog.cpp
qgsattributedialog.cpp
@@ -144,6 +145,7 @@ SET (QGIS_APP_MOC_HDRS
qgsabout.h
qgsaddattrdialog.h
qgsdisplayangle.h
qgsaddjoindialog.h
qgsannotationwidget.h
qgsattributeactiondialog.h
qgsattributedialog.h
@@ -234,7 +234,7 @@ void QgsAttributeTableModel::loadLayer()
rect = QgisApp::instance()->mapCanvas()->extent();
}

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

QgsFeature f;
for ( int i = 0; mLayer->nextFeature( f ); ++i )
@@ -0,0 +1,137 @@
/***************************************************************************
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() );
}

mCacheInMemoryCheckBox->setChecked( true );
}

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::cacheInMemory() const
{
return mCacheInMemoryCheckBox->isChecked();
}

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 );
}
else
{
mCreateIndexCheckBox->setEnabled( false );
mCreateIndexCheckBox->setChecked( false );
}
}
@@ -0,0 +1,57 @@
/***************************************************************************
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;
/**True if joined layer should be cached in virtual memory*/
bool cacheInMemory() 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
@@ -21,6 +21,7 @@
#include <limits>

#include "qgisapp.h"
#include "qgsaddjoindialog.h"
#include "qgsapplication.h"
#include "qgsattributeactiondialog.h"
#include "qgsapplydialog.h"
@@ -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"
@@ -133,6 +135,13 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

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

//insert existing join info
const 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();
@@ -813,7 +822,6 @@ QString QgsVectorLayerProperties::metadata()
{
xMin = QString( "%1" ).arg( myExtent.xMinimum() );
}

if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
{
yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
@@ -822,7 +830,6 @@ QString QgsVectorLayerProperties::metadata()
{
yMin = QString( "%1" ).arg( myExtent.yMinimum() );
}

if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
{
xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
@@ -831,7 +838,6 @@ QString QgsVectorLayerProperties::metadata()
{
xMax = QString( "%1" ).arg( myExtent.xMaximum() );
}

if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
{
yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
@@ -1171,6 +1177,70 @@ void QgsVectorLayerProperties::setUsingNewSymbology( bool useNewSymbology )
updateSymbologyPage();
}

void QgsVectorLayerProperties::on_mButtonAddJoin_clicked()
{
QgsAddJoinDialog d( layer );
if ( d.exec() == QDialog::Accepted )
{
QgsVectorJoinInfo info;
info.targetField = d.targetField();
info.joinLayerId = d.joinedLayerId();
info.joinField = d.joinField();
info.memoryCache = d.cacheInMemory();
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( const 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" ),
@@ -117,6 +117,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 */
@@ -171,6 +174,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( const QgsVectorJoinInfo& join );

static QMap< QgsVectorLayer::EditType, QString > editTypeMap;
static void setupEditTypes();
static QString editTypeButtonText( QgsVectorLayer::EditType type );
@@ -89,6 +89,7 @@ SET(QGIS_CORE_SRCS
qgsvectordataprovider.cpp
qgsvectorfilewriter.cpp
qgsvectorlayer.cpp
qgsvectorlayerjoinbuffer.cpp
qgsvectorlayerundocommand.cpp
qgsvectoroverlay.cpp

@@ -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 );

0 comments on commit f1a655f

Please sign in to comment.
You can’t perform that action at this time.