Skip to content

Commit 9d188a5

Browse files
author
mhugent
committed
Initial table join prototype
git-svn-id: http://svn.osgeo.org/qgis/branches/table_join_branch@13934 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 2db428e commit 9d188a5

20 files changed

+1080
-200
lines changed

src/app/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ SET(QGIS_APP_SRCS
44
qgisappinterface.cpp
55
qgsabout.cpp
66
qgsaddattrdialog.cpp
7+
qgsaddjoindialog.cpp
78
qgsannotationwidget.cpp
89
qgsattributeactiondialog.cpp
910
qgsattributedialog.cpp
@@ -130,6 +131,7 @@ SET (QGIS_APP_MOC_HDRS
130131
qgsabout.h
131132
qgsaddattrdialog.h
132133
qgsdisplayangle.h
134+
qgsaddjoindialog.h
133135
qgsannotationwidget.h
134136
qgsattributeactiondialog.h
135137
qgsattributedialog.h

src/app/attributetable/qgsattributetablemodel.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ void QgsAttributeTableModel::loadLayer()
217217
rect = QgisApp::instance()->mapCanvas()->extent();
218218
}
219219

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

222222
for ( int i = 0; mLayer->nextFeature( f ); ++i )
223223
{

src/app/qgsaddjoindialog.cpp

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/***************************************************************************
2+
qgsaddjoindialog.cpp
3+
--------------------
4+
begin : July 10, 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco dot hugentobler at sourcepole dot ch
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgsaddjoindialog.h"
19+
#include "qgsmaplayer.h"
20+
#include "qgsmaplayerregistry.h"
21+
#include "qgsvectordataprovider.h"
22+
#include "qgsvectorlayer.h"
23+
24+
QgsAddJoinDialog::QgsAddJoinDialog( QgsVectorLayer* layer, QWidget * parent, Qt::WindowFlags f ): QDialog( parent, f ), mLayer( layer )
25+
{
26+
setupUi( this );
27+
28+
if( !mLayer )
29+
{
30+
return;
31+
}
32+
33+
//insert possible vector layers into mJoinLayerComboBox
34+
35+
mJoinLayerComboBox->blockSignals( true );
36+
const QMap<QString, QgsMapLayer*>& layerList = QgsMapLayerRegistry::instance()->mapLayers();
37+
QMap<QString, QgsMapLayer*>::const_iterator layerIt = layerList.constBegin();
38+
for(; layerIt != layerList.constEnd(); ++layerIt )
39+
{
40+
QgsMapLayer* currentLayer = layerIt.value();
41+
if( currentLayer->type() == QgsMapLayer::VectorLayer )
42+
{
43+
QgsVectorLayer* currentVectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
44+
if( currentVectorLayer && currentVectorLayer != mLayer )
45+
{
46+
if( currentVectorLayer->dataProvider() && currentVectorLayer->dataProvider()->supportsSubsetString() )
47+
mJoinLayerComboBox->addItem( currentLayer->name(), QVariant(currentLayer->getLayerID() ) );
48+
}
49+
}
50+
}
51+
mJoinLayerComboBox->blockSignals( false );
52+
on_mJoinLayerComboBox_currentIndexChanged( mJoinLayerComboBox->currentIndex() );
53+
54+
//insert possible target fields
55+
const QgsFieldMap& layerFieldMap = mLayer->pendingFields();
56+
QgsFieldMap::const_iterator fieldIt = layerFieldMap.constBegin();
57+
for(; fieldIt != layerFieldMap.constEnd(); ++fieldIt )
58+
{
59+
mTargetFieldComboBox->addItem(fieldIt.value().name(), fieldIt.key() );
60+
}
61+
}
62+
63+
QgsAddJoinDialog::~QgsAddJoinDialog()
64+
{
65+
}
66+
67+
QString QgsAddJoinDialog::joinedLayerId() const
68+
{
69+
return mJoinLayerComboBox->itemData( mJoinLayerComboBox->currentIndex() ).toString();
70+
}
71+
72+
int QgsAddJoinDialog::joinField() const
73+
{
74+
return mJoinFieldComboBox->itemData( mJoinFieldComboBox->currentIndex() ).toInt();
75+
}
76+
77+
QString QgsAddJoinDialog::joinFieldName() const
78+
{
79+
return mJoinFieldComboBox->itemText( mJoinFieldComboBox->currentIndex() );
80+
}
81+
82+
int QgsAddJoinDialog::targetField() const
83+
{
84+
return mTargetFieldComboBox->itemData( mTargetFieldComboBox->currentIndex() ).toInt();
85+
}
86+
87+
QString QgsAddJoinDialog::targetFieldName() const
88+
{
89+
return mTargetFieldComboBox->itemText( mTargetFieldComboBox->currentIndex() );
90+
}
91+
92+
bool QgsAddJoinDialog::createAttributeIndex() const
93+
{
94+
return mCreateIndexCheckBox->isChecked();
95+
}
96+
97+
void QgsAddJoinDialog::on_mJoinLayerComboBox_currentIndexChanged ( int index )
98+
{
99+
mJoinFieldComboBox->clear();
100+
QString layerId = mJoinLayerComboBox->itemData( index ).toString();
101+
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
102+
if( !layer )
103+
{
104+
return;
105+
}
106+
QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( layer );
107+
if( !vLayer )
108+
{
109+
return;
110+
}
111+
112+
const QgsFieldMap& layerFieldMap = vLayer->pendingFields();
113+
QgsFieldMap::const_iterator fieldIt = layerFieldMap.constBegin();
114+
for(; fieldIt != layerFieldMap.constEnd(); ++fieldIt )
115+
{
116+
mJoinFieldComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
117+
}
118+
119+
//does provider support creation of attribute indices?
120+
QgsVectorDataProvider* dp = vLayer->dataProvider();
121+
if( dp && (dp->capabilities() & QgsVectorDataProvider::CreateAttributeIndex) )
122+
{
123+
mCreateIndexCheckBox->setEnabled( true );
124+
mCreateIndexCheckBox->setChecked( true );
125+
}
126+
else
127+
{
128+
mCreateIndexCheckBox->setEnabled( false );
129+
mCreateIndexCheckBox->setChecked( false );
130+
}
131+
}

src/app/qgsaddjoindialog.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/***************************************************************************
2+
qgsaddjoindialog.h
3+
------------------
4+
begin : July 10, 2010
5+
copyright : (C) 2010 by Marco Hugentobler
6+
email : marco dot hugentobler at sourcepole dot ch
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSADDJOINDIALOG_H
19+
#define QGSADDJOINDIALOG_H
20+
21+
#include "ui_qgsaddjoindialogbase.h"
22+
class QgsVectorLayer;
23+
24+
class QgsAddJoinDialog: public QDialog, private Ui::QgsAddJoinDialogBase
25+
{
26+
Q_OBJECT
27+
public:
28+
QgsAddJoinDialog( QgsVectorLayer* layer, QWidget * parent = 0, Qt::WindowFlags f = 0 );
29+
~QgsAddJoinDialog();
30+
31+
//retrieve results
32+
33+
/**Get the id of the layer to join*/
34+
QString joinedLayerId() const;
35+
/**Returns the index of the join field*/
36+
int joinField() const;
37+
/**Returns the name of the join field*/
38+
QString joinFieldName() const;
39+
/**Returns the index of the target field (join-to field)*/
40+
int targetField() const;
41+
/**Returns the name of the target field (join-to field)*/
42+
QString targetFieldName() const;
43+
/**Returns true if user wants to create an attribute index on the join field*/
44+
bool createAttributeIndex() const;
45+
46+
private slots:
47+
void on_mJoinLayerComboBox_currentIndexChanged ( int index );
48+
49+
private:
50+
/**Target layer*/
51+
QgsVectorLayer* mLayer;
52+
};
53+
54+
55+
#endif // QGSADDJOINDIALOG_H

src/app/qgsvectorlayerproperties.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <limits>
2222

2323
#include "qgisapp.h"
24+
#include "qgsaddjoindialog.h"
2425
#include "qgsapplication.h"
2526
#include "qgsattributeactiondialog.h"
2627
#include "qgsapplydialog.h"
@@ -33,6 +34,7 @@
3334
#include "qgslabel.h"
3435
#include "qgsgenericprojectionselector.h"
3536
#include "qgslogger.h"
37+
#include "qgsmaplayerregistry.h"
3638
#include "qgspluginmetadata.h"
3739
#include "qgspluginregistry.h"
3840
#include "qgsproject.h"
@@ -132,6 +134,13 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
132134

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

137+
//insert existing join info
138+
QList< QgsVectorJoinInfo > joins = layer->vectorJoins();
139+
for( int i = 0; i < joins.size(); ++i )
140+
{
141+
addJoinToTreeWidget( joins[i] );
142+
}
143+
135144
//for each overlay plugin create a new tab
136145
int position;
137146
QList<QgsVectorOverlayPlugin*> overlayPluginList = overlayPlugins();
@@ -1160,6 +1169,69 @@ void QgsVectorLayerProperties::setUsingNewSymbology( bool useNewSymbology )
11601169
updateSymbologyPage();
11611170
}
11621171

1172+
void QgsVectorLayerProperties::on_mButtonAddJoin_clicked()
1173+
{
1174+
QgsAddJoinDialog d( layer );
1175+
if( d.exec() == QDialog::QDialog::Accepted )
1176+
{
1177+
QgsVectorJoinInfo info;
1178+
info.targetField = d.targetField();
1179+
info.joinLayerId = d.joinedLayerId();
1180+
info.joinField = d.joinField();
1181+
if( layer )
1182+
{
1183+
//create attribute index if possible. Todo: ask user if this should be done (e.g. in QgsAddJoinDialog)
1184+
if( d.createAttributeIndex() )
1185+
{
1186+
QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( info.joinLayerId ) );
1187+
if( joinLayer )
1188+
{
1189+
joinLayer->dataProvider()->createAttributeIndex( info.joinField );
1190+
}
1191+
}
1192+
1193+
layer->addJoin( info );
1194+
loadRows(); //update attribute tab
1195+
addJoinToTreeWidget( info );
1196+
}
1197+
}
1198+
}
1199+
1200+
void QgsVectorLayerProperties::addJoinToTreeWidget( QgsVectorJoinInfo& join )
1201+
{
1202+
QTreeWidgetItem* joinItem = new QTreeWidgetItem();
1203+
1204+
QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join.joinLayerId ) );
1205+
if( !joinLayer )
1206+
{
1207+
return;
1208+
}
1209+
1210+
joinItem->setText( 0, joinLayer->name() );
1211+
joinItem->setData( 0, Qt::UserRole, join.joinLayerId );
1212+
QString joinFieldName = joinLayer->pendingFields().value( join.joinField ).name();
1213+
QString targetFieldName = layer->pendingFields().value( join.targetField ).name();
1214+
joinItem->setText( 1, joinFieldName );
1215+
joinItem->setData( 1, Qt::UserRole, join.joinField );
1216+
joinItem->setText( 2, targetFieldName );
1217+
joinItem->setData( 2, Qt::UserRole, join.targetField );
1218+
1219+
mJoinTreeWidget->addTopLevelItem( joinItem );
1220+
}
1221+
1222+
void QgsVectorLayerProperties::on_mButtonRemoveJoin_clicked()
1223+
{
1224+
QTreeWidgetItem* currentJoinItem = mJoinTreeWidget->currentItem();
1225+
if( !layer || !currentJoinItem )
1226+
{
1227+
return;
1228+
}
1229+
1230+
layer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
1231+
loadRows();
1232+
mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
1233+
}
1234+
11631235
void QgsVectorLayerProperties::useNewSymbology()
11641236
{
11651237
int res = QMessageBox::question( this, tr( "Symbology" ),

src/app/qgsvectorlayerproperties.h

+6
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
116116
void useNewSymbology();
117117
void setUsingNewSymbology( bool useNewSymbology );
118118

119+
void on_mButtonAddJoin_clicked();
120+
void on_mButtonRemoveJoin_clicked();
121+
119122
signals:
120123

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

176+
/**Adds a new join to mJoinTreeWidget*/
177+
void addJoinToTreeWidget( QgsVectorJoinInfo& join );
178+
173179
static QMap< QgsVectorLayer::EditType, QString > editTypeMap;
174180
static void setupEditTypes();
175181
static QString editTypeButtonText( QgsVectorLayer::EditType type );

src/core/qgsdataprovider.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class CORE_EXPORT QgsDataProvider : public QObject
113113
* that can be used by the data provider to create a subset.
114114
* Must be implemented in the dataprovider.
115115
*/
116-
virtual bool setSubsetString( QString subset )
116+
virtual bool setSubsetString( QString subset, bool updateFeatureCount = true )
117117
{
118118
// NOP by default
119119
Q_UNUSED( subset );

src/core/qgsproject.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
677677
bool returnStatus = true;
678678

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

681682
for ( int i = 0; i < nl.count(); i++ )
682683
{
@@ -716,6 +717,11 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
716717
if ( mapLayer->readXML( node ) )
717718
{
718719
mapLayer = QgsMapLayerRegistry::instance()->addMapLayer( mapLayer );
720+
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
721+
if( vLayer )
722+
{
723+
vLayerList.push_back( vLayer );
724+
}
719725
}
720726
else
721727
{
@@ -727,10 +733,20 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
727733

728734
brokenNodes.push_back( node );
729735
}
730-
731736
emit layerLoaded( i + 1, nl.count() );
732737
}
733738

739+
//Update field map of layers with joins.
740+
//Needs to be done here once all dependent layers are loaded
741+
QList<QgsVectorLayer*>::iterator vIt = vLayerList.begin();
742+
for(; vIt != vLayerList.end(); ++vIt )
743+
{
744+
if( (*vIt)->vectorJoins().size() > 0 )
745+
{
746+
(*vIt)->updateFieldMap();
747+
}
748+
}
749+
734750
return qMakePair( returnStatus, brokenNodes );
735751

736752
} // _getMapLayers

src/core/qgsvectordataprovider.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ bool QgsVectorDataProvider::createSpatialIndex()
126126
return false;
127127
}
128128

129+
bool QgsVectorDataProvider::createAttributeIndex( int field )
130+
{
131+
return true;
132+
}
133+
129134
int QgsVectorDataProvider::capabilities() const
130135
{
131136
return QgsVectorDataProvider::NoCapabilities;

0 commit comments

Comments
 (0)