[QGIS Commit] r13934 - in branches/table_join_branch/src: app
app/attributetable core providers/ogr providers/postgres
providers/spatialite ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Mon Jul 19 02:21:39 EDT 2010
Author: mhugent
Date: 2010-07-19 06:21:39 +0000 (Mon, 19 Jul 2010)
New Revision: 13934
Added:
branches/table_join_branch/src/app/qgsaddjoindialog.cpp
branches/table_join_branch/src/app/qgsaddjoindialog.h
branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui
Modified:
branches/table_join_branch/src/app/CMakeLists.txt
branches/table_join_branch/src/app/attributetable/qgsattributetablemodel.cpp
branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp
branches/table_join_branch/src/app/qgsvectorlayerproperties.h
branches/table_join_branch/src/core/qgsdataprovider.h
branches/table_join_branch/src/core/qgsproject.cpp
branches/table_join_branch/src/core/qgsvectordataprovider.cpp
branches/table_join_branch/src/core/qgsvectordataprovider.h
branches/table_join_branch/src/core/qgsvectorlayer.cpp
branches/table_join_branch/src/core/qgsvectorlayer.h
branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp
branches/table_join_branch/src/providers/ogr/qgsogrprovider.h
branches/table_join_branch/src/providers/postgres/qgspostgresprovider.cpp
branches/table_join_branch/src/providers/postgres/qgspostgresprovider.h
branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.cpp
branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.h
branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui
Log:
Initial table join prototype
Modified: branches/table_join_branch/src/app/CMakeLists.txt
===================================================================
--- branches/table_join_branch/src/app/CMakeLists.txt 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/app/CMakeLists.txt 2010-07-19 06:21:39 UTC (rev 13934)
@@ -4,6 +4,7 @@
qgisappinterface.cpp
qgsabout.cpp
qgsaddattrdialog.cpp
+ qgsaddjoindialog.cpp
qgsannotationwidget.cpp
qgsattributeactiondialog.cpp
qgsattributedialog.cpp
@@ -130,6 +131,7 @@
qgsabout.h
qgsaddattrdialog.h
qgsdisplayangle.h
+ qgsaddjoindialog.h
qgsannotationwidget.h
qgsattributeactiondialog.h
qgsattributedialog.h
Modified: branches/table_join_branch/src/app/attributetable/qgsattributetablemodel.cpp
===================================================================
--- branches/table_join_branch/src/app/attributetable/qgsattributetablemodel.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/app/attributetable/qgsattributetablemodel.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -217,7 +217,7 @@
rect = QgisApp::instance()->mapCanvas()->extent();
}
- mLayer->select( mAttributes, rect, false );
+ mLayer->select( QgsAttributeList(), rect, false );
for ( int i = 0; mLayer->nextFeature( f ); ++i )
{
Added: branches/table_join_branch/src/app/qgsaddjoindialog.cpp
===================================================================
--- branches/table_join_branch/src/app/qgsaddjoindialog.cpp (rev 0)
+++ branches/table_join_branch/src/app/qgsaddjoindialog.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -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 );
+ }
+}
Added: branches/table_join_branch/src/app/qgsaddjoindialog.h
===================================================================
--- branches/table_join_branch/src/app/qgsaddjoindialog.h (rev 0)
+++ branches/table_join_branch/src/app/qgsaddjoindialog.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -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
Modified: branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -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"
@@ -132,6 +134,13 @@
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();
@@ -1160,6 +1169,69 @@
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" ),
Modified: branches/table_join_branch/src/app/qgsvectorlayerproperties.h
===================================================================
--- branches/table_join_branch/src/app/qgsvectorlayerproperties.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/app/qgsvectorlayerproperties.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -116,6 +116,9 @@
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 */
@@ -170,6 +173,9 @@
/**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 );
Modified: branches/table_join_branch/src/core/qgsdataprovider.h
===================================================================
--- branches/table_join_branch/src/core/qgsdataprovider.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsdataprovider.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -113,7 +113,7 @@
* 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 );
Modified: branches/table_join_branch/src/core/qgsproject.cpp
===================================================================
--- branches/table_join_branch/src/core/qgsproject.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsproject.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -677,6 +677,7 @@
bool returnStatus = true;
emit layerLoaded( 0, nl.count() );
+ QList<QgsVectorLayer*> vLayerList; //collect
for ( int i = 0; i < nl.count(); i++ )
{
@@ -716,6 +717,11 @@
if ( mapLayer->readXML( node ) )
{
mapLayer = QgsMapLayerRegistry::instance()->addMapLayer( mapLayer );
+ QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
+ if( vLayer )
+ {
+ vLayerList.push_back( vLayer );
+ }
}
else
{
@@ -727,10 +733,20 @@
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
Modified: branches/table_join_branch/src/core/qgsvectordataprovider.cpp
===================================================================
--- branches/table_join_branch/src/core/qgsvectordataprovider.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsvectordataprovider.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -126,6 +126,11 @@
return false;
}
+bool QgsVectorDataProvider::createAttributeIndex( int field )
+{
+ return true;
+}
+
int QgsVectorDataProvider::capabilities() const
{
return QgsVectorDataProvider::NoCapabilities;
Modified: branches/table_join_branch/src/core/qgsvectordataprovider.h
===================================================================
--- branches/table_join_branch/src/core/qgsvectordataprovider.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsvectordataprovider.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -74,6 +74,7 @@
RandomSelectGeometryAtId = 1 << 10,
/** DEPRECATED - do not use */
SequentialSelectGeometryAtId = 1 << 11,
+ CreateAttributeIndex = 1 << 12
};
/** bitmask of all provider's editing capabilities */
@@ -272,6 +273,9 @@
*/
virtual bool createSpatialIndex();
+ /**Create an attribute index on the datasource*/
+ virtual bool createAttributeIndex( int field );
+
/** Returns a bitmask containing the supported capabilities
Note, some capabilities may change depending on whether
a spatial filter is active on this provider, so it may
Modified: branches/table_join_branch/src/core/qgsvectorlayer.cpp
===================================================================
--- branches/table_join_branch/src/core/qgsvectorlayer.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsvectorlayer.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -153,6 +153,9 @@
}
}
+ connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved(QString) ), this, SLOT( checkJoinLayerRemove(QString) ) );
+ updateFieldMap();
+
// Get the update threshold from user settings. We
// do this only on construction to avoid the penality of
// fetching this each time the layer is drawn. If the user
@@ -1453,6 +1456,119 @@
void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f, bool all )
{
+ if( mDataProvider && ( mFetchAttributes.size() > 0 || all ) )
+ {
+
+ if( all )
+ {
+ int index = 0;
+ int currentMaxIndex;
+ maxIndex( mDataProvider->fields(), index);
+ index += 1;
+ QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
+ for(; joinIt != mVectorJoins.constEnd(); ++joinIt )
+ {
+ QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
+ if( !joinLayer )
+ {
+ continue;
+ }
+
+ QString joinFieldName = joinLayer->pendingFields().value( joinIt->joinField ).name();
+ if( joinFieldName.isEmpty() )
+ {
+ continue;
+ }
+
+ QVariant targetFieldValue = f.attributeMap().value( joinIt->targetField );
+ if( !targetFieldValue.isValid() )
+ {
+ continue;
+ }
+
+ //set subset string
+ QString bkSubsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
+ QString subsetString;
+ if( !bkSubsetString.isEmpty() )
+ {
+ subsetString.append(" AND ");
+ }
+ subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + targetFieldValue.toString() + "\"" );
+ joinLayer->dataProvider()->setSubsetString( subsetString, false );
+
+ //select (no geometry)
+ joinLayer->select( joinLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
+
+ //get first feature
+ QgsFeature fet;
+ if( joinLayer->nextFeature( fet ) )
+ {
+ QgsAttributeMap attMap = fet.attributeMap();
+ QgsAttributeMap::const_iterator attIt = attMap.constBegin();
+ for(; attIt != attMap.constEnd(); ++attIt )
+ {
+ f.addAttribute( attIt.key() + index, attIt.value() );
+ }
+ }
+ joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
+ maxIndex( joinLayer->pendingFields(), currentMaxIndex );
+ index += ( currentMaxIndex + 1 );
+ }
+ }
+ else
+ {
+ QMap<QgsVectorLayer*, QgsFetchJoinInfo>::const_iterator joinIt = mFetchJoinInfos.constBegin();
+ for(; joinIt != mFetchJoinInfos.constEnd(); ++joinIt )
+ {
+ QgsVectorLayer* joinLayer = joinIt.key();
+ if( !joinLayer )
+ {
+ continue;
+ }
+
+ QString joinFieldName = joinLayer->pendingFields().value( joinIt.value().joinInfo.joinField ).name();
+ if( joinFieldName.isEmpty() )
+ {
+ continue;
+ }
+
+ QVariant targetFieldValue = f.attributeMap().value( joinIt->joinInfo.targetField );
+ if( !targetFieldValue.isValid() )
+ {
+ continue;
+ }
+
+ //set subset string
+ QString bkSubsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
+ QString subsetString;
+ if( !bkSubsetString.isEmpty() )
+ {
+ subsetString.append(" AND ");
+ }
+ subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + targetFieldValue.toString() + "\"" );
+ joinLayer->dataProvider()->setSubsetString( subsetString, false );
+
+ //select (no geometry)
+ joinLayer->select( joinIt.value().attributes, QgsRectangle(), false, false );
+
+ //get first feature
+ QgsFeature fet;
+ if( joinLayer->nextFeature( fet ) )
+ {
+ QgsAttributeMap attMap = fet.attributeMap();
+ QgsAttributeMap::const_iterator attIt = attMap.constBegin();
+ for(; attIt != attMap.constEnd(); ++attIt )
+ {
+ f.addAttribute( attIt.key() + joinIt.value().indexOffset, attIt.value() );
+ }
+ }
+
+ joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
+ }
+ }
+ }
+
+
// do not update when we aren't in editing mode
if ( !mEditable )
return;
@@ -1492,8 +1608,8 @@
mFetchRect = rect;
mFetchAttributes = attributes;
mFetchGeometry = fetchGeometries;
-
mFetchConsidered = mDeletedFeatureIds;
+ QgsAttributeList targetJoinFieldList;
if ( mEditable )
{
@@ -1504,24 +1620,47 @@
//look in the normal features of the provider
if ( mFetchAttributes.size() > 0 )
{
- if ( mEditable )
+ if( mEditable || mVectorJoins.size() > 0)
{
- // fetch only available field from provider
mFetchProvAttributes.clear();
+ mFetchJoinInfos.clear();
for ( QgsAttributeList::iterator it = mFetchAttributes.begin(); it != mFetchAttributes.end(); it++ )
{
- if ( !mUpdatedFields.contains( *it ) || mAddedAttributeIds.contains( *it ) )
- continue;
-
- mFetchProvAttributes << *it;
+ if( mDataProvider->fields().contains( *it ) )
+ {
+ mFetchProvAttributes << *it;
+ }
+ else
+ {
+ QgsVectorJoinInfo joinInfo;
+ int indexOffset;
+ if( joinForFieldIndex( *it, joinInfo, indexOffset ) )
+ {
+ QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
+ if( joinLayer )
+ {
+ mFetchJoinInfos[ joinLayer ].joinInfo = joinInfo;
+ mFetchJoinInfos[ joinLayer].attributes.push_back( *it - indexOffset ); //store provider index
+ mFetchJoinInfos[ joinLayer ].indexOffset = indexOffset;
+ //for joined fields, we always need to request the targetField from the provider too
+ if( !mFetchAttributes.contains( joinInfo.targetField ))
+ {
+ targetJoinFieldList << joinInfo.targetField;
+ mFetchProvAttributes << joinInfo.targetField;
+ }
+ }
+ }
+ }
}
-
+ mFetchAttributes.append( targetJoinFieldList );
mDataProvider->select( mFetchProvAttributes, rect, fetchGeometries, useIntersect );
}
else
+ {
mDataProvider->select( mFetchAttributes, rect, fetchGeometries, useIntersect );
+ }
}
- else
+ else //we don't need any attributes at all
{
mDataProvider->select( QgsAttributeList(), rect, fetchGeometries, useIntersect );
}
@@ -1570,6 +1709,7 @@
{
found = true;
f.setAttributeMap( it->attributeMap() );
+ updateFeatureAttributes( f );
break;
}
}
@@ -1631,12 +1771,13 @@
while ( dataProvider()->nextFeature( f ) )
{
if ( mFetchConsidered.contains( f.id() ) )
+ {
continue;
-
- if ( mEditable )
- updateFeatureAttributes( f );
-
- // found it
+ }
+ if( mFetchAttributes.size() > 0 )
+ {
+ updateFeatureAttributes( f ); //check joined attributes / changed attributes
+ }
return true;
}
@@ -2415,10 +2556,10 @@
mEditable = true;
- mUpdatedFields = mDataProvider->fields();
+ mAddedAttributeIds.clear();
+ mDeletedAttributeIds.clear();
+ updateFieldMap();
- mMaxUpdatedIndex = -1;
-
for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
if ( it.key() > mMaxUpdatedIndex )
mMaxUpdatedIndex = it.key();
@@ -2475,12 +2616,30 @@
}
}
+ //load vector joins
+ QDomElement vectorJoinsElem = layer_node.firstChildElement("vectorjoins");
+ if( !vectorJoinsElem.isNull() )
+ {
+ QDomNodeList joinList = vectorJoinsElem.elementsByTagName("join");
+ for( int i = 0; i < joinList.size(); ++i )
+ {
+ QDomElement infoElem = joinList.at( i ).toElement();
+ QgsVectorJoinInfo info;
+ info.joinField = infoElem.attribute("joinField").toInt();
+ info.joinLayerId = infoElem.attribute("joinLayerId");
+ info.targetField = infoElem.attribute("targetField").toInt();
+ addJoin( info );
+ }
+ }
+
QString errorMsg;
if ( !readSymbology( layer_node, errorMsg ) )
{
return false;
}
+ updateFieldMap();
+
return mValid; // should be true if read successfully
} // void QgsVectorLayer::readXml
@@ -2618,6 +2777,19 @@
layer_node.appendChild( provider );
}
+ //save joins
+ QDomElement vectorJoinsElem = document.createElement( "vectorjoins" );
+ layer_node.appendChild( vectorJoinsElem );
+ QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
+ for(; joinIt != mVectorJoins.constEnd(); ++joinIt )
+ {
+ QDomElement joinElem = document.createElement("join");
+ joinElem.setAttribute( "targetField", joinIt->targetField );
+ joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId );
+ joinElem.setAttribute( "joinField", joinIt->joinField);
+ vectorJoinsElem.appendChild( joinElem );
+ }
+
// renderer specific settings
QString errorMsg;
if ( !writeSymbology( layer_node, document, errorMsg ) )
@@ -3156,12 +3328,12 @@
const QgsFieldMap &QgsVectorLayer::pendingFields() const
{
- return isEditable() ? mUpdatedFields : mDataProvider->fields();
+ return mUpdatedFields;
}
QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
{
- return isEditable() ? mUpdatedFields.keys() : mDataProvider->attributeIndexes();
+ return mUpdatedFields.keys();
}
int QgsVectorLayer::pendingFeatureCount()
@@ -3219,9 +3391,12 @@
if ( mAddedAttributeIds.size() > 0 )
{
QList<QgsField> addedAttributes;
- for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.begin(); it != mAddedAttributeIds.end(); it++ )
- addedAttributes << mUpdatedFields[ *it ];
+ for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
+ {
+ addedAttributes << mUpdatedFields[*it];
+ }
+
if (( cap & QgsVectorDataProvider::AddAttributes ) && mDataProvider->addAttributes( addedAttributes ) )
{
mCommitErrors << tr( "SUCCESS: %n attribute(s) added.", "added attributes count", mAddedAttributeIds.size() );
@@ -3264,7 +3439,7 @@
// (otherwise we'll loose updates when doing the remapping)
if ( mAddedAttributeIds.size() > 0 )
{
- for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.begin(); it != mAddedAttributeIds.end(); it++ )
+ for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.constBegin(); it != mAddedAttributeIds.constEnd(); it++ )
{
QString name = mUpdatedFields[ *it ].name();
if ( dst.contains( name ) )
@@ -3434,13 +3609,11 @@
{
mEditable = false;
setModified( false );
-
- mUpdatedFields.clear();
- mMaxUpdatedIndex = -1;
undoStack()->clear();
emit editingStopped();
}
+ updateFieldMap();
mDataProvider->updateExtents();
triggerRepaint();
@@ -3492,9 +3665,7 @@
// Roll back deleted features
mDeletedFeatureIds.clear();
- // clear private field map
- mUpdatedFields.clear();
- mMaxUpdatedIndex = -1;
+ updateFieldMap();
}
deleteCachedGeometries();
@@ -3545,6 +3716,7 @@
QgsFeatureList features;
QgsAttributeList allAttrs = mDataProvider->attributeIndexes();
+ mFetchAttributes = pendingAllAttributesList();
for ( QgsFeatureIds::iterator it = mSelectedFeatureIds.begin(); it != mSelectedFeatureIds.end(); ++it )
{
@@ -4574,6 +4746,109 @@
return -1;
}
+void QgsVectorLayer::addJoin( QgsVectorJoinInfo joinInfo )
+{
+ mVectorJoins.push_back( joinInfo );
+ updateFieldMap();
+}
+
+void QgsVectorLayer::checkJoinLayerRemove( QString theLayerId )
+{
+ removeJoin( theLayerId );
+}
+
+void QgsVectorLayer::removeJoin( const QString& joinLayerId )
+{
+ for( int i = 0; i < mVectorJoins.size(); ++i )
+ {
+ if( mVectorJoins.at( i ).joinLayerId == joinLayerId )
+ {
+ mVectorJoins.removeAt( i );
+ updateFieldMap();
+ return;
+ }
+ }
+}
+
+void QgsVectorLayer::updateFieldMap()
+{
+ //first backup mAddedAttributes
+ QgsFieldMap bkAddedAttributes;
+ QgsAttributeIds::const_iterator attIdIt = mAddedAttributeIds.constBegin();
+ for(; attIdIt != mAddedAttributeIds.constEnd(); ++attIdIt )
+ {
+ bkAddedAttributes.insert( *attIdIt, mUpdatedFields.value(*attIdIt) );
+ }
+
+ mUpdatedFields = QgsFieldMap();
+ if( mDataProvider )
+ {
+ mUpdatedFields = mDataProvider->fields();
+ }
+
+ int currentMaxIndex = 0; //maximum index of current layer
+ if( !maxIndex( mUpdatedFields, currentMaxIndex ) )
+ {
+ return;
+ }
+
+ mMaxUpdatedIndex = currentMaxIndex;
+
+ QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
+ for(; joinIt != mVectorJoins.constEnd(); ++joinIt )
+ {
+ QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
+ if( !joinLayer )
+ {
+ continue;
+ }
+
+ const QgsFieldMap& joinFields = joinLayer->pendingFields();
+ QgsFieldMap::const_iterator fieldIt = joinFields.constBegin();
+ for(; fieldIt != joinFields.constEnd(); ++fieldIt )
+ {
+ mUpdatedFields.insert( mMaxUpdatedIndex + 1 + fieldIt.key(), fieldIt.value() );
+ }
+
+ if( maxIndex( joinFields, currentMaxIndex ) )
+ {
+ mMaxUpdatedIndex += (currentMaxIndex + 1); //+1 because there are fields with index 0
+ }
+ }
+
+ //insert added attributes after provider fields and joined fields
+ mAddedAttributeIds.clear();
+ QgsFieldMap::const_iterator fieldIt = bkAddedAttributes.constBegin();
+ for(; fieldIt != bkAddedAttributes.constEnd(); ++fieldIt )
+ {
+ ++mMaxUpdatedIndex;
+ mUpdatedFields.insert( mMaxUpdatedIndex, fieldIt.value() );
+ mAddedAttributeIds.insert( mMaxUpdatedIndex );
+
+ //go through the changed attributes map and adapt indices of added attributes
+ for( int i = 0; i < mChangedAttributeValues.size(); ++i )
+ {
+ updateAttributeMapIndex( mChangedAttributeValues[i], fieldIt.key(), mMaxUpdatedIndex );
+ }
+
+ //go through added features and adapt attribute maps
+ QgsFeatureList::iterator featureIt = mAddedFeatures.begin();
+ for(; featureIt != mAddedFeatures.end(); ++featureIt )
+ {
+ QgsAttributeMap attMap = featureIt->attributeMap();
+ updateAttributeMapIndex( attMap, fieldIt.key(), mMaxUpdatedIndex );
+ featureIt->setAttributeMap( attMap );
+ }
+ }
+
+ //remove deleted attributes
+ QgsAttributeIds::const_iterator deletedIt = mDeletedAttributeIds.constBegin();
+ for(; deletedIt != mDeletedAttributeIds.constEnd(); ++deletedIt )
+ {
+ mUpdatedFields.remove( *deletedIt );
+ }
+}
+
void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
{
mRendererV2->stopRender( rendererContext );
@@ -4583,3 +4858,68 @@
delete selRenderer;
}
}
+
+bool QgsVectorLayer::maxIndex( const QgsFieldMap& fMap, int& index ) const
+{
+ if( fMap.size() < 1 )
+ {
+ return false;
+ }
+ QgsFieldMap::const_iterator endIt = fMap.constEnd();
+ --endIt;
+ index = endIt.key();
+ return true;
+}
+
+void QgsVectorLayer::updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const
+{
+ QgsAttributeMap::const_iterator it = map.find( oldIndex );
+ if( it == map.constEnd() )
+ {
+ return;
+ }
+
+ map.insert( newIndex, it.value() );
+ map.remove( oldIndex );
+}
+
+bool QgsVectorLayer::joinForFieldIndex( int index, QgsVectorJoinInfo& joinInfo, int& indexOffset ) const
+{
+ int currentMaxIndex = 0;
+ int totIndex = 0;
+
+ //a provider field?
+ if( mDataProvider )
+ {
+ if( mDataProvider->fields().contains( index ) )
+ {
+ return false;
+ }
+ }
+ maxIndex( mDataProvider->fields(), totIndex );
+ ++totIndex;
+
+ //go through the joins
+ QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
+ for(; joinIt != mVectorJoins.constEnd(); ++joinIt )
+ {
+ QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
+ if( !joinLayer )
+ {
+ continue;
+ }
+
+ if( joinLayer->pendingFields().contains( index - totIndex ) )
+ {
+ joinInfo = *joinIt;
+ indexOffset = totIndex;
+ return true;
+ }
+
+ maxIndex(joinLayer->pendingFields(), currentMaxIndex );
+ totIndex += (currentMaxIndex + 1);
+ }
+
+ //else an added field
+ return false;
+}
Modified: branches/table_join_branch/src/core/qgsvectorlayer.h
===================================================================
--- branches/table_join_branch/src/core/qgsvectorlayer.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/core/qgsvectorlayer.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -54,7 +54,24 @@
typedef QSet<int> QgsFeatureIds;
typedef QSet<int> QgsAttributeIds;
+struct QgsVectorJoinInfo
+{
+ /**Join field in the target layer*/
+ int targetField;
+ /**Source layer*/
+ QString joinLayerId;
+ /**Join field in the source layer*/
+ int joinField;
+};
+struct QgsFetchJoinInfo
+{
+ QgsVectorJoinInfo joinInfo;
+ QgsAttributeList attributes; //attributes to fetch
+ int indexOffset; //index offset between this layer and join layer
+};
+
+
/** \ingroup core
* Vector layer backed by a data source provider.
*/
@@ -127,6 +144,15 @@
/** Setup the coordinate system tranformation for the layer */
void setCoordinateSystem();
+ /**Joins another vector layer to this layer*/
+ void addJoin( QgsVectorJoinInfo joinInfo );
+
+ /**Removes a vector layer join*/
+ void removeJoin( const QString& joinLayerId );
+
+ /**Returns the joins on this layer*/
+ QList< QgsVectorJoinInfo > vectorJoins() const { return mVectorJoins; }
+
/** Get the label object associated with this layer */
QgsLabel *label();
@@ -555,6 +581,12 @@
@note public and static from version 1.4 */
static void drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int vertexSize );
+ /**Assembles mUpdatedFields considering provider fields, joined fields and added fields
+ @note added in version 1.6*/
+ void updateFieldMap();
+
+
+
public slots:
/** Select feature by its ID, optionally emit signal selectionChanged() */
void select( int featureId, bool emitSignal = true );
@@ -572,6 +604,9 @@
*/
virtual void updateExtents();
+ /**Check if there is a join with a layer that will be removed*/
+ void checkJoinLayerRemove( QString theLayerId );
+
signals:
/** This signal is emited when selection was changed */
@@ -672,6 +707,21 @@
/** Stop version 2 renderer and selected renderer (if required) */
void stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer );
+ /** Helper function to find out the maximum index of a field map
+ @return true in case of success, otherwise false (e.g. empty map)*/
+ bool maxIndex( const QgsFieldMap& fMap, int& index ) const;
+
+ /**Updates an index in an attribute map to a new value (usually necessary because of a join operation)*/
+ void updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const;
+
+ /**Finds the vector join for a layer field index.
+ @param attribute index
+ @param info out: join info for the attribute
+ @param indexOffset out: offset between layer index and original provider index
+ @return true if the index belongs to a joined field, otherwise false (possibily provider field or added field)*/
+ bool joinForFieldIndex( int index, QgsVectorJoinInfo& info, int& indexOffset ) const;
+
+
private: // Private attributes
/** Update threshold for drawing features as they are read. A value of zero indicates
@@ -735,6 +785,9 @@
/** field map to commit */
QgsFieldMap mUpdatedFields;
+ /**Joined vector layers*/
+ QList< QgsVectorJoinInfo > mVectorJoins;
+
/**Map that stores the aliases for attributes. Key is the attribute index and value the alias for that attribute*/
QMap<int, QString> mAttributeAliasMap;
@@ -790,6 +843,9 @@
QgsAttributeList mFetchProvAttributes;
bool mFetchGeometry;
+ //Information about fetched joins
+ QMap<QgsVectorLayer*, QgsFetchJoinInfo> mFetchJoinInfos;
+
QSet<int> mFetchConsidered;
QgsGeometryMap::iterator mFetchChangedGeomIt;
QgsFeatureList::iterator mFetchAddedFeaturesIt;
Modified: branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp
===================================================================
--- branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -220,7 +220,7 @@
}
}
-bool QgsOgrProvider::setSubsetString( QString theSQL )
+bool QgsOgrProvider::setSubsetString( QString theSQL, bool updateFeatureCount )
{
QgsCPLErrorHandler handler;
@@ -277,7 +277,10 @@
// getting the total number of features in the layer
// TODO: This can be expensive, do we really need it!
- recalculateFeatureCount();
+ if( updateFeatureCount )
+ {
+ recalculateFeatureCount();
+ }
// check the validity of the layer
QgsDebugMsg( "checking validity" );
@@ -1023,6 +1026,20 @@
return indexfile.exists();
}
+bool QgsOgrProvider::createAttributeIndex( int field )
+{
+ QString layerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrOrigLayer ) );
+ QString dropSql = QString( "DROP INDEX ON %1" ).arg( quotedIdentifier( layerName ) );
+ QString createSql = QString( "CREATE INDEX ON %1 USING %2" ).arg( quotedIdentifier( layerName ) ).arg( fields()[field].name() );
+ OGR_DS_ExecuteSQL( ogrDataSource, mEncoding->fromUnicode( dropSql ).data(), OGR_L_GetSpatialFilter( ogrOrigLayer ), "SQL" );
+ OGR_DS_ExecuteSQL( ogrDataSource, mEncoding->fromUnicode( createSql ).data(), OGR_L_GetSpatialFilter( ogrOrigLayer ), "SQL" );
+
+ QFileInfo fi( mFilePath ); // to get the base name
+ //find out, if the .idm file is there
+ QFile indexfile( fi.path().append( "/" ).append( fi.completeBaseName() ).append( ".idm" ) );
+ return indexfile.exists();
+}
+
bool QgsOgrProvider::deleteFeatures( const QgsFeatureIds & id )
{
QgsCPLErrorHandler handler;
@@ -1157,6 +1174,7 @@
// adding attributes was added in GDAL 1.6
ability |= AddAttributes;
#endif
+ ability |= CreateAttributeIndex;
if ( mAttributeFields.size() == 0 )
{
Modified: branches/table_join_branch/src/providers/ogr/qgsogrprovider.h
===================================================================
--- branches/table_join_branch/src/providers/ogr/qgsogrprovider.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/ogr/qgsogrprovider.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -98,7 +98,7 @@
virtual bool supportsSubsetString() { return true; }
/** mutator for sql where clause used to limit dataset size */
- virtual bool setSubsetString( QString theSQL );
+ virtual bool setSubsetString( QString theSQL, bool updateFeatureCount = true );
/**
* Get feature type.
@@ -155,6 +155,9 @@
@return true in case of success*/
virtual bool createSpatialIndex();
+ /**Create an attribute index on the datasource*/
+ virtual bool createAttributeIndex( int field );
+
/** Returns a bitmask containing the supported capabilities
Note, some capabilities may change depending on whether
a spatial filter is active on this provider, so it may
Modified: branches/table_join_branch/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- branches/table_join_branch/src/providers/postgres/qgspostgresprovider.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/postgres/qgspostgresprovider.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -2748,7 +2748,7 @@
return enabledCapabilities;
}
-bool QgsPostgresProvider::setSubsetString( QString theSQL )
+bool QgsPostgresProvider::setSubsetString( QString theSQL, bool updateFeatureCount )
{
QString prevWhere = sqlWhereClause;
@@ -2766,7 +2766,10 @@
// uri? Perhaps this needs some rationalisation.....
setDataSourceUri( mUri.uri() );
- featuresCounted = -1;
+ if( updateFeatureCount )
+ {
+ featuresCounted = -1;
+ }
layerExtent.setMinimal();
return true;
Modified: branches/table_join_branch/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- branches/table_join_branch/src/providers/postgres/qgspostgresprovider.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/postgres/qgspostgresprovider.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -250,7 +250,7 @@
QString subsetString();
/** mutator for sql where clause used to limit dataset size */
- bool setSubsetString( QString theSQL );
+ bool setSubsetString( QString theSQL, bool updateFeatureCount = true );
virtual bool supportsSubsetString() { return true; }
Modified: branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.cpp
===================================================================
--- branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.cpp 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.cpp 2010-07-19 06:21:39 UTC (rev 13934)
@@ -479,7 +479,7 @@
return mSubsetString;
}
-bool QgsSpatiaLiteProvider::setSubsetString( QString theSQL )
+bool QgsSpatiaLiteProvider::setSubsetString( QString theSQL, bool updateFeatureCount )
{
QString prevSubsetString = mSubsetString;
mSubsetString = theSQL;
@@ -490,8 +490,10 @@
setDataSourceUri( uri.uri() );
// update feature count and extents
- if ( getTableSummary() )
+ if ( updateFeatureCount && getTableSummary() )
+ {
return true;
+ }
mSubsetString = prevSubsetString;
Modified: branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.h
===================================================================
--- branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.h 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/providers/spatialite/qgsspatialiteprovider.h 2010-07-19 06:21:39 UTC (rev 13934)
@@ -79,7 +79,7 @@
virtual QString subsetString();
/** mutator for sql where clause used to limit dataset size */
- virtual bool setSubsetString( QString theSQL );
+ virtual bool setSubsetString( QString theSQL, bool updateFeatureCount = true );
virtual bool supportsSubsetString() { return true; }
Added: branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui
===================================================================
--- branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui (rev 0)
+++ branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui 2010-07-19 06:21:39 UTC (rev 13934)
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QgsAddJoinDialogBase</class>
+ <widget class="QDialog" name="QgsAddJoinDialogBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>281</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Add vector join</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="mJoinLayerLabel">
+ <property name="text">
+ <string>Join layer: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="mJoinLayerComboBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="mJoinFieldLabel">
+ <property name="text">
+ <string>Join field:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="mJoinFieldComboBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="mTargetFieldLabel">
+ <property name="text">
+ <string>Target field:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="mTargetFieldComboBox"/>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="mCreateIndexCheckBox">
+ <property name="text">
+ <string>Create attribute index on join field</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QgsAddJoinDialogBase</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QgsAddJoinDialogBase</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Modified: branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui
===================================================================
--- branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui 2010-07-19 05:42:17 UTC (rev 13933)
+++ branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui 2010-07-19 06:21:39 UTC (rev 13934)
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>668</width>
+ <width>589</width>
<height>426</height>
</rect>
</property>
@@ -21,166 +21,10 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QListWidget" name="listWidget">
- <property name="minimumSize">
- <size>
- <width>110</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>110</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- <property name="editTriggers">
- <set>QAbstractItemView::NoEditTriggers</set>
- </property>
- <property name="showDropIndicator" stdset="0">
- <bool>false</bool>
- </property>
- <property name="iconSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="textElideMode">
- <enum>Qt::ElideNone</enum>
- </property>
- <property name="flow">
- <enum>QListView::TopToBottom</enum>
- </property>
- <property name="isWrapping" stdset="0">
- <bool>false</bool>
- </property>
- <property name="resizeMode">
- <enum>QListView::Adjust</enum>
- </property>
- <property name="spacing">
- <number>9</number>
- </property>
- <property name="viewMode">
- <enum>QListView::IconMode</enum>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <item>
- <property name="text">
- <string>Symbology</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/symbology.png</normaloff>:/images/themes/default/propertyicons/symbology.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Labels</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/labels.png</normaloff>:/images/themes/default/propertyicons/labels.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Attributes</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/attributes.png</normaloff>:/images/themes/default/propertyicons/attributes.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string>General</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/general.png</normaloff>:/images/themes/default/propertyicons/general.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Metadata</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/metadata.png</normaloff>:/images/themes/default/propertyicons/metadata.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Actions</string>
- </property>
- <property name="textAlignment">
- <set>AlignHCenter|AlignVCenter|AlignCenter</set>
- </property>
- <property name="icon">
- <iconset resource="../../images/images.qrc">
- <normaloff>:/images/themes/default/propertyicons/action.png</normaloff>:/images/themes/default/propertyicons/action.png</iconset>
- </property>
- <property name="flags">
- <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
- </property>
- </item>
- <item>
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="flags">
- <set>NoItemFlags</set>
- </property>
- </item>
- </widget>
- </item>
<item row="0" column="1">
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
- <number>3</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="page_3">
<layout class="QGridLayout" name="gridLayout_4">
@@ -458,8 +302,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>514</width>
- <height>378</height>
+ <width>439</width>
+ <height>419</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
@@ -689,6 +533,67 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="mJoinPage">
+ <layout class="QGridLayout" name="gridLayout_10">
+ <item row="0" column="0">
+ <widget class="QPushButton" name="mButtonAddJoin">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="mButtonRemoveJoin">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>354</width>
+ <height>23</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QTreeWidget" name="mJoinTreeWidget">
+ <property name="columnCount">
+ <number>3</number>
+ </property>
+ <column>
+ <property name="text">
+ <string>Join layer</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Join field</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Target field</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item row="1" column="0" colspan="2">
@@ -733,6 +638,167 @@
</property>
</widget>
</item>
+ <item row="0" column="0">
+ <widget class="QListWidget" name="listWidget">
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>110</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="showDropIndicator" stdset="0">
+ <bool>false</bool>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideNone</enum>
+ </property>
+ <property name="flow">
+ <enum>QListView::TopToBottom</enum>
+ </property>
+ <property name="isWrapping" stdset="0">
+ <bool>false</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>QListView::Adjust</enum>
+ </property>
+ <property name="spacing">
+ <number>9</number>
+ </property>
+ <property name="viewMode">
+ <enum>QListView::IconMode</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Symbology</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/symbology.png</normaloff>:/images/themes/default/propertyicons/symbology.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Labels</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/labels.png</normaloff>:/images/themes/default/propertyicons/labels.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Attributes</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/attributes.png</normaloff>:/images/themes/default/propertyicons/attributes.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>General</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/general.png</normaloff>:/images/themes/default/propertyicons/general.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Metadata</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/metadata.png</normaloff>:/images/themes/default/propertyicons/metadata.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Actions</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/action.png</normaloff>:/images/themes/default/propertyicons/action.png</iconset>
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joins</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="flags">
+ <set>NoItemFlags</set>
+ </property>
+ </item>
+ </widget>
+ </item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
More information about the QGIS-commit
mailing list