Skip to content

Commit f1a655f

Browse files
author
mhugent
committed
[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
1 parent 9f1a59f commit f1a655f

26 files changed

+1325
-61
lines changed

images/images.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@
269269
<file>themes/default/propertyicons/digitising.png</file>
270270
<file>themes/default/propertyicons/general.png</file>
271271
<file>themes/default/propertyicons/histogram.png</file>
272+
<file>themes/default/propertyicons/join.png</file>
272273
<file>themes/default/propertyicons/labels.png</file>
273274
<file>themes/default/propertyicons/locale.png</file>
274275
<file>themes/default/propertyicons/map_tools.png</file>
3.92 KB
Loading

src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
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
@@ -144,6 +145,7 @@ SET (QGIS_APP_MOC_HDRS
144145
qgsabout.h
145146
qgsaddattrdialog.h
146147
qgsdisplayangle.h
148+
qgsaddjoindialog.h
147149
qgsannotationwidget.h
148150
qgsattributeactiondialog.h
149151
qgsattributedialog.h

src/app/attributetable/qgsattributetablemodel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void QgsAttributeTableModel::loadLayer()
234234
rect = QgisApp::instance()->mapCanvas()->extent();
235235
}
236236

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

239239
QgsFeature f;
240240
for ( int i = 0; mLayer->nextFeature( f ); ++i )

src/app/qgsaddjoindialog.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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+
mCacheInMemoryCheckBox->setChecked( true );
63+
}
64+
65+
QgsAddJoinDialog::~QgsAddJoinDialog()
66+
{
67+
}
68+
69+
QString QgsAddJoinDialog::joinedLayerId() const
70+
{
71+
return mJoinLayerComboBox->itemData( mJoinLayerComboBox->currentIndex() ).toString();
72+
}
73+
74+
int QgsAddJoinDialog::joinField() const
75+
{
76+
return mJoinFieldComboBox->itemData( mJoinFieldComboBox->currentIndex() ).toInt();
77+
}
78+
79+
QString QgsAddJoinDialog::joinFieldName() const
80+
{
81+
return mJoinFieldComboBox->itemText( mJoinFieldComboBox->currentIndex() );
82+
}
83+
84+
int QgsAddJoinDialog::targetField() const
85+
{
86+
return mTargetFieldComboBox->itemData( mTargetFieldComboBox->currentIndex() ).toInt();
87+
}
88+
89+
QString QgsAddJoinDialog::targetFieldName() const
90+
{
91+
return mTargetFieldComboBox->itemText( mTargetFieldComboBox->currentIndex() );
92+
}
93+
94+
bool QgsAddJoinDialog::cacheInMemory() const
95+
{
96+
return mCacheInMemoryCheckBox->isChecked();
97+
}
98+
99+
bool QgsAddJoinDialog::createAttributeIndex() const
100+
{
101+
return mCreateIndexCheckBox->isChecked();
102+
}
103+
104+
void QgsAddJoinDialog::on_mJoinLayerComboBox_currentIndexChanged( int index )
105+
{
106+
mJoinFieldComboBox->clear();
107+
QString layerId = mJoinLayerComboBox->itemData( index ).toString();
108+
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId );
109+
if ( !layer )
110+
{
111+
return;
112+
}
113+
QgsVectorLayer* vLayer = dynamic_cast<QgsVectorLayer*>( layer );
114+
if ( !vLayer )
115+
{
116+
return;
117+
}
118+
119+
const QgsFieldMap& layerFieldMap = vLayer->pendingFields();
120+
QgsFieldMap::const_iterator fieldIt = layerFieldMap.constBegin();
121+
for ( ; fieldIt != layerFieldMap.constEnd(); ++fieldIt )
122+
{
123+
mJoinFieldComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
124+
}
125+
126+
//does provider support creation of attribute indices?
127+
QgsVectorDataProvider* dp = vLayer->dataProvider();
128+
if ( dp && ( dp->capabilities() & QgsVectorDataProvider::CreateAttributeIndex ) )
129+
{
130+
mCreateIndexCheckBox->setEnabled( true );
131+
}
132+
else
133+
{
134+
mCreateIndexCheckBox->setEnabled( false );
135+
mCreateIndexCheckBox->setChecked( false );
136+
}
137+
}

src/app/qgsaddjoindialog.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
/**True if joined layer should be cached in virtual memory*/
44+
bool cacheInMemory() const;
45+
/**Returns true if user wants to create an attribute index on the join field*/
46+
bool createAttributeIndex() const;
47+
48+
private slots:
49+
void on_mJoinLayerComboBox_currentIndexChanged( int index );
50+
51+
private:
52+
/**Target layer*/
53+
QgsVectorLayer* mLayer;
54+
};
55+
56+
57+
#endif // QGSADDJOINDIALOG_H

src/app/qgsvectorlayerproperties.cpp

Lines changed: 73 additions & 3 deletions
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"
@@ -133,6 +135,13 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
133135

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

138+
//insert existing join info
139+
const QList< QgsVectorJoinInfo >& joins = layer->vectorJoins();
140+
for ( int i = 0; i < joins.size(); ++i )
141+
{
142+
addJoinToTreeWidget( joins[i] );
143+
}
144+
136145
//for each overlay plugin create a new tab
137146
int position;
138147
QList<QgsVectorOverlayPlugin*> overlayPluginList = overlayPlugins();
@@ -813,7 +822,6 @@ QString QgsVectorLayerProperties::metadata()
813822
{
814823
xMin = QString( "%1" ).arg( myExtent.xMinimum() );
815824
}
816-
817825
if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
818826
{
819827
yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
@@ -822,7 +830,6 @@ QString QgsVectorLayerProperties::metadata()
822830
{
823831
yMin = QString( "%1" ).arg( myExtent.yMinimum() );
824832
}
825-
826833
if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
827834
{
828835
xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
@@ -831,7 +838,6 @@ QString QgsVectorLayerProperties::metadata()
831838
{
832839
xMax = QString( "%1" ).arg( myExtent.xMaximum() );
833840
}
834-
835841
if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
836842
{
837843
yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
@@ -1171,6 +1177,70 @@ void QgsVectorLayerProperties::setUsingNewSymbology( bool useNewSymbology )
11711177
updateSymbologyPage();
11721178
}
11731179

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

src/app/qgsvectorlayerproperties.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
117117
void useNewSymbology();
118118
void setUsingNewSymbology( bool useNewSymbology );
119119

120+
void on_mButtonAddJoin_clicked();
121+
void on_mButtonRemoveJoin_clicked();
122+
120123
signals:
121124

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

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

src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ SET(QGIS_CORE_SRCS
8989
qgsvectordataprovider.cpp
9090
qgsvectorfilewriter.cpp
9191
qgsvectorlayer.cpp
92+
qgsvectorlayerjoinbuffer.cpp
9293
qgsvectorlayerundocommand.cpp
9394
qgsvectoroverlay.cpp
9495

src/core/qgsdataprovider.h

Lines changed: 1 addition & 1 deletion
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 );

0 commit comments

Comments
 (0)