[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