Skip to content
Permalink
Browse files
[FEATURE] allow to disable SelectAtId capability for PostgreSQL provi…
…der to

force usage of the attribute table memory model.  Apparently the memory model
was completely disfunctional before.  Fixes included, but it probably needs
more testing.
  • Loading branch information
jef-n committed Nov 30, 2011
1 parent ee9b8d7 commit b8e5a34a922816a3a3b5ecf4b6e5e04e35e36bac
@@ -22,12 +22,20 @@
#include <QStringList>
#include <QRegExp>

QgsDataSourceURI::QgsDataSourceURI() : mSSLmode( SSLprefer ), mKeyColumn( "" ), mUseEstimatedMetadata( false )
QgsDataSourceURI::QgsDataSourceURI()
: mSSLmode( SSLprefer )
, mKeyColumn( "" )
, mUseEstimatedMetadata( false )
, mSelectAtIdDisabled( false )
{
// do nothing
}

QgsDataSourceURI::QgsDataSourceURI( QString uri ) : mSSLmode( SSLprefer ), mKeyColumn( "" ), mUseEstimatedMetadata( false )
QgsDataSourceURI::QgsDataSourceURI( QString uri )
: mSSLmode( SSLprefer )
, mKeyColumn( "" )
, mUseEstimatedMetadata( false )
, mSelectAtIdDisabled( false )
{
int i = 0;
while ( i < uri.length() )
@@ -115,6 +123,10 @@ QgsDataSourceURI::QgsDataSourceURI( QString uri ) : mSSLmode( SSLprefer ), mKeyC
{
mUseEstimatedMetadata = pval == "true";
}
else if ( pname == "selectatid" )
{
mSelectAtIdDisabled = pval == "false";
}
else if ( pname == "service" )
{
mService = pval;
@@ -309,6 +321,16 @@ bool QgsDataSourceURI::useEstimatedMetadata() const
return mUseEstimatedMetadata;
}

void QgsDataSourceURI::disableSelectAtId( bool theFlag )
{
mSelectAtIdDisabled = theFlag;
}

bool QgsDataSourceURI::selectAtIdDisabled() const
{
return mSelectAtIdDisabled;
}

void QgsDataSourceURI::setSql( QString sql )
{
mSql = sql;
@@ -461,6 +483,11 @@ QString QgsDataSourceURI::uri() const
theUri += QString( " estimatedmetadata=true" );
}

if ( mSelectAtIdDisabled )
{
theUri += QString( " selectatid=false" );
}

theUri += QString( " table=%1%2 sql=%3" )
.arg( quotedTablename() )
.arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( mGeometryColumn ) )
@@ -97,6 +97,9 @@ class CORE_EXPORT QgsDataSourceURI
void setUseEstimatedMetadata( bool theFlag );
bool useEstimatedMetadata() const;

void disableSelectAtId( bool theFlag );
bool selectAtIdDisabled() const;

void clearSchema();
void setSql( QString sql );

@@ -147,6 +150,8 @@ class CORE_EXPORT QgsDataSourceURI
QString mKeyColumn;
//Use estimated metadata flag
bool mUseEstimatedMetadata;
//Disable SelectAtId capability (eg. to trigger the attribute table memory model for expensive views)
bool mSelectAtIdDisabled;
};

#endif //QGSDATASOURCEURI_H
@@ -26,6 +26,7 @@ QgsDbTableModel::QgsDbTableModel(): QStandardItemModel(), mTableCount( 0 )
headerLabels << tr( "Type" );
headerLabels << tr( "Geometry column" );
headerLabels << tr( "Primary key column" );
headerLabels << tr( "Select at id" );
headerLabels << tr( "Sql" );
setHorizontalHeaderLabels( headerLabels );
}
@@ -60,17 +61,27 @@ void QgsDbTableModel::addTableEntry( QString type, QString schemaName, QString t
QIcon iconFile = iconForType( wkbType );

QList<QStandardItem*> childItemList;

QStandardItem* schemaNameItem = new QStandardItem( schemaName );
schemaNameItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );

QStandardItem* typeItem = new QStandardItem( QIcon( iconFile ), type );
typeItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );

QStandardItem* tableItem = new QStandardItem( tableName );
tableItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );

QStandardItem* geomItem = new QStandardItem( geometryColName );
geomItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );

QStandardItem* pkItem = new QStandardItem( "" );
pkItem->setData( pkCols );
pkItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );

QStandardItem* selItem = new QStandardItem( "" );
selItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable );
selItem->setCheckState( Qt::Checked );

QStandardItem* sqlItem = new QStandardItem( sql );
sqlItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );

@@ -79,6 +90,7 @@ void QgsDbTableModel::addTableEntry( QString type, QString schemaName, QString t
childItemList.push_back( typeItem );
childItemList.push_back( geomItem );
childItemList.push_back( pkItem );
childItemList.push_back( selItem );
childItemList.push_back( sqlItem );

schemaItem->appendRow( childItemList );
@@ -28,15 +28,19 @@ class CORE_EXPORT QgsDbTableModel : public QStandardItemModel
public:
QgsDbTableModel();
~QgsDbTableModel();

/**Adds entry for one database table to the model*/
void addTableEntry( QString type, QString schemaName, QString tableName, QString geometryColName, const QStringList &pkCols, QString Sql );

/**Sets an sql statement that belongs to a cell specified by a model index*/
void setSql( const QModelIndex& index, const QString& sql );

/**Sets one or more geometry types to a row. In case of several types, additional rows are inserted.
This is for tables where the type is dectected later by thread*/
void setGeometryTypesForTable( const QString& schema, const QString& table, const QString& attribute, const QString& type );

/**Returns the number of tables in the model*/
int tableCount() const {return mTableCount;}
int tableCount() const { return mTableCount; }

enum columns
{
@@ -45,6 +49,7 @@ class CORE_EXPORT QgsDbTableModel : public QStandardItemModel
dbtmType,
dbtmGeomCol,
dbtmPkCol,
dbtmSelectAtId,
dbtmSql,
dbtmColumns
};
@@ -55,6 +60,7 @@ class CORE_EXPORT QgsDbTableModel : public QStandardItemModel

QIcon iconForType( QGis::WkbType type ) const;
QString displayStringForType( QGis::WkbType type ) const;

/**Returns qgis wkbtype from database typename*/
QGis::WkbType qgisTypeFromDbType( const QString& dbType ) const;
};
@@ -27,27 +27,59 @@
// In-Memory model //
/////////////////////

QgsAttributeTableMemoryModel::QgsAttributeTableMemoryModel( QgsVectorLayer *theLayer )
: QgsAttributeTableModel( theLayer )
{
QgsDebugMsg( "entered." );
}

void QgsAttributeTableMemoryModel::loadLayer()
{
QgsAttributeTableModel::loadLayer();
mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
QgsDebugMsg( "entered." );

QSettings settings;
int behaviour = settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt();

QgsRectangle rect;
if ( behaviour == 2 )
{
// current canvas only
rect = mCurrentExtent;
}

mLayer->select( mLayer->pendingAllAttributesList(), rect, false );

mFeatureMap.reserve( mLayer->pendingFeatureCount() + 50 );
if( behaviour != 1 )
mFeatureMap.reserve( mLayer->pendingFeatureCount() + 50 );
else
mFeatureMap.reserve( mLayer->selectedFeatureCount() );

int n = 0;

QgsFeature f;
while ( mLayer->nextFeature( f ) )
{
if( behaviour == 1 && !mLayer->selectedFeaturesIds().contains( f.id() ) )
continue;

mIdRowMap.insert( f.id(), n );
mRowIdMap.insert( n, f.id() );
mFeatureMap.insert( f.id(), f );
n++;
}

mFieldCount = mAttributes.size();
}

QgsAttributeTableMemoryModel::QgsAttributeTableMemoryModel
( QgsVectorLayer *theLayer )
: QgsAttributeTableModel( theLayer )
int QgsAttributeTableMemoryModel::rowCount( const QModelIndex &parent ) const
{
loadLayer();
Q_UNUSED( parent );
return mFeatureMap.size();
}

bool QgsAttributeTableMemoryModel::featureAtId( QgsFeatureId fid )
bool QgsAttributeTableMemoryModel::featureAtId( QgsFeatureId fid ) const
{
QgsDebugMsg( QString( "entered featureAtId: %1." ).arg( fid ) );
if ( mFeatureMap.contains( fid ) )
{
mFeat = mFeatureMap[ fid ];
@@ -70,17 +102,14 @@ void QgsAttributeTableMemoryModel::featureDeleted( QgsFeatureId fid )
void QgsAttributeTableMemoryModel::featureAdded( QgsFeatureId fid )
{
QgsDebugMsg( "entered." );
QgsFeature f;
mLayer->featureAtId( fid, f, false, true );
mFeatureMap.insert( fid, f );
QgsAttributeTableModel::featureAdded( fid );
Q_UNUSED( fid );
loadLayer();
}

void QgsAttributeTableMemoryModel::layerDeleted()
{
QgsDebugMsg( "entered." );
mFeatureMap.clear();
QgsAttributeTableModel::layerDeleted();
loadLayer();
}

void QgsAttributeTableMemoryModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
@@ -30,7 +30,7 @@

class QgsAttributeTableMemoryModel : public QgsAttributeTableModel
{
Q_OBJECT;
Q_OBJECT

public:
/**
@@ -39,6 +39,12 @@ class QgsAttributeTableMemoryModel : public QgsAttributeTableModel
*/
QgsAttributeTableMemoryModel( QgsVectorLayer *theLayer );

/**
* Returns the number of rows
* @param parent parent index
*/
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;

/**
* Remove rows
*/
@@ -75,7 +81,7 @@ class QgsAttributeTableMemoryModel : public QgsAttributeTableModel
* @param fid feature id
* @return feature exists
*/
virtual bool featureAtId( QgsFeatureId fid );
virtual bool featureAtId( QgsFeatureId fid ) const;

/**
* Loads the layer into the model
@@ -32,6 +32,8 @@ QgsRectangle QgsAttributeTableModel::mCurrentExtent; // static member
QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayer *theLayer, QObject *parent )
: QAbstractTableModel( parent )
{
QgsDebugMsg( "entered." );

mFeat.setFeatureId( std::numeric_limits<int>::min() );
mFeatureMap.clear();
mFeatureQueue.clear();
@@ -44,8 +46,6 @@ QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayer *theLayer, QObjec
connect( mLayer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( featureDeleted( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( attributeAdded( int ) ), this, SLOT( attributeAdded( int ) ) );
connect( mLayer, SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );

loadLayer();
}

bool QgsAttributeTableModel::featureAtId( QgsFeatureId fid ) const
@@ -38,18 +38,16 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
* @param parent parent pointer
*/
QgsAttributeTableModel( QgsVectorLayer *theLayer, QObject *parent = 0 );

/**
* Returns the number of rows
* @param parent parent index
*/
int rowCount( const QModelIndex &parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;
/**
* Returns the number of columns
* @param parent parent index
*/
int columnCount( const QModelIndex &parent = QModelIndex() ) const;

/**
* Returns header data
* @param section required section
@@ -214,26 +212,26 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
*/
void initIdMaps();

/**
* Gets mFieldCount, mAttributes and mValueMaps
*/
virtual void loadAttributes();

public:
/**
* Loads the layer into the model
*/
virtual void loadLayer();

/**
* Gets mFieldCount, mAttributes and mValueMaps
*/
virtual void loadAttributes();
private:
mutable QQueue<QgsFeatureId> mFeatureQueue;

/**
* load feature fid into mFeat
* @param fid feature id
* @return feature exists
*/
virtual bool featureAtId( QgsFeatureId fid ) const;

private:
mutable QQueue<QgsFeatureId> mFeatureQueue;

};


@@ -23,9 +23,9 @@
#include "qgsattributetablememorymodel.h"
#include "qgsattributetabledelegate.h"
#include "qgsattributetablefiltermodel.h"

#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgslogger.h"

QgsAttributeTableView::QgsAttributeTableView( QWidget* parent )
: QTableView( parent ), mModel( 0 ), mFilterModel( 0 ), mActionPopup( 0 )
@@ -63,9 +63,17 @@ void QgsAttributeTableView::setLayer( QgsVectorLayer* layer )
// features in the current view. Otherwise we'll have to store
// everything in the memory because using featureAtId() would be too slow
if ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SelectAtId )
{
QgsDebugMsg( "SelectAtId supported" );
mModel = new QgsAttributeTableModel( layer );
}
else
{
QgsDebugMsg( "SelectAtId NOT supported" );
mModel = new QgsAttributeTableMemoryModel( layer );
}

mModel->loadLayer();

mFilterModel = new QgsAttributeTableFilterModel( layer );
mFilterModel->setSourceModel( mModel );

0 comments on commit b8e5a34

Please sign in to comment.