2009-03-20 18:24:19 +00:00
|
|
|
/***************************************************************************
|
|
|
|
BeataModel.cpp
|
|
|
|
--------------------------------------
|
2009-03-27 17:37:59 +00:00
|
|
|
Date : Feb 2009
|
2009-03-20 18:24:19 +00:00
|
|
|
Copyright : (C) 2009 Vita Cizek
|
|
|
|
Email : weetya (at) gmail.com
|
|
|
|
***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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 "BeataModel.h"
|
|
|
|
#include "BeataView.h"
|
|
|
|
|
|
|
|
#include "qgsvectordataprovider.h"
|
|
|
|
#include "qgsfield.h"
|
|
|
|
#include "qgsvectorlayer.h"
|
|
|
|
|
|
|
|
#include <QtGui>
|
|
|
|
#include <QVariant>
|
|
|
|
#include <QtAlgorithms>
|
2009-03-27 17:37:59 +00:00
|
|
|
#include "qgslogger.h"
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
//could be faster when type guessed before sorting
|
2009-03-27 17:37:59 +00:00
|
|
|
bool idColumnPair::operator<( const idColumnPair &b ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
//QVariat thinks gid is a string!
|
|
|
|
QVariant::Type columnType = columnItem.type();
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( columnType == QVariant::Int || columnType == QVariant::UInt || columnType == QVariant::LongLong || columnType == QVariant::ULongLong )
|
2009-03-20 18:24:19 +00:00
|
|
|
return columnItem.toLongLong() < b.columnItem.toLongLong();
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( columnType == QVariant::Double )
|
|
|
|
return columnItem.toDouble() < b.columnItem.toDouble();
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
return columnItem.toString() < b.columnItem.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////
|
|
|
|
// Filter Model //
|
|
|
|
//////////////////
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataFilterModel::sort( int column, Qt::SortOrder order )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
(( BeataModel * )sourceModel() )->sort( column, order );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
BeataFilterModel::BeataFilterModel( QgsVectorLayer* theLayer )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
mLayer = theLayer;
|
|
|
|
mHideUnselected = false;
|
2009-03-27 17:37:59 +00:00
|
|
|
setDynamicSortFilter( true );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
bool BeataFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( mHideUnselected )
|
|
|
|
// unreadable? yes, i agree :-)
|
|
|
|
return mLayer->selectedFeaturesIds().contains((( BeataModel * )sourceModel() )->rowToId( sourceRow ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
QModelIndex BeataFilterModel::mapFromSource ( const QModelIndex& sourceIndex ) const
|
|
|
|
{
|
|
|
|
return sourceIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
QModelIndex BeataFilterModel::mapToSource ( const QModelIndex& filterIndex ) const
|
|
|
|
{
|
|
|
|
return filterIndex;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
////////////////
|
|
|
|
// BeataModel //
|
|
|
|
////////////////
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
BeataModel::BeataModel( QgsVectorLayer *theLayer, QObject *parent )
|
|
|
|
: QAbstractTableModel( parent )
|
|
|
|
{
|
2009-03-20 18:24:19 +00:00
|
|
|
mLastRowId = -1;
|
|
|
|
mLastRow = NULL;
|
|
|
|
mLayer = theLayer;
|
|
|
|
mFeatureCount = mLayer->pendingFeatureCount();
|
2009-03-27 17:42:35 +00:00
|
|
|
mFieldCount = mLayer->pendingFields().size();
|
|
|
|
mAttributes = mLayer->pendingAllAttributesList();
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
connect( mLayer, SIGNAL( layerModified( bool ) ), this, SLOT( layerModified( bool ) ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
//connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT( attributeAdded(int)));
|
|
|
|
//connect(mLayer, SIGNAL(attributeDeleted(int)), this, SLOT( attributeDeleted(int)));
|
|
|
|
//connect(mLayer, SIGNAL(attributeValueChanged(int, int, const QVariant&)), this, SLOT( attributeValueChanged(int, int, const QVariant&)));
|
|
|
|
//connect(mLayer, SIGNAL(featureDeleted(int)), this, SLOT( featureDeleted(int)));
|
|
|
|
//connect(mLayer, SIGNAL(featureAdded(int)), this, SLOT( featureAdded(int)));
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
loadLayer();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::featureDeleted( int fid )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-28 02:02:00 +00:00
|
|
|
#ifdef QGISDEBUG
|
2009-03-20 18:24:19 +00:00
|
|
|
int idx = mIdRowMap[fid];
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( idx );
|
|
|
|
QgsDebugMsg( fid );
|
2009-03-28 02:02:00 +00:00
|
|
|
#endif
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
--mFeatureCount;
|
|
|
|
mIdRowMap.remove( fid );
|
|
|
|
mRowIdMap.remove( idx );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
// fill the hole in the view
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( idx != mFeatureCount )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "jo" );
|
2009-03-20 18:24:19 +00:00
|
|
|
//mRowIdMap[idx] = mRowIdMap[mFeatureCount];
|
|
|
|
//mIdRowMap[mRowIdMap[idx]] = idx;
|
|
|
|
int movedId = mRowIdMap[mFeatureCount];
|
2009-03-27 17:37:59 +00:00
|
|
|
mRowIdMap.remove( mFeatureCount );
|
|
|
|
mRowIdMap.insert( idx, movedId );
|
2009-03-20 18:24:19 +00:00
|
|
|
mIdRowMap[movedId] = idx;
|
|
|
|
//mIdRowMap.remove(mRowIdMap[idx]);
|
|
|
|
//mIdRowMap.insert(mRowIdMap[idx], idx);
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
emit layoutChanged();
|
|
|
|
//reload(index(0,0), index(rowCount(), columnCount()));
|
2009-03-27 17:37:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
QgsDebugMsg( "id->row" );
|
2009-03-20 18:24:19 +00:00
|
|
|
QMap<int, int>::iterator it;
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
|
|
|
|
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "row->id" );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
|
|
|
|
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataModel::featureAdded( int fid )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "BM feature added" );
|
2009-03-20 18:24:19 +00:00
|
|
|
++mFeatureCount;
|
2009-03-27 17:37:59 +00:00
|
|
|
mIdRowMap.insert( fid, mFeatureCount - 1 );
|
|
|
|
mRowIdMap.insert( mFeatureCount - 1, fid );
|
|
|
|
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataModel::attributeAdded( int idx )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "BM attribute added" );
|
2009-03-20 18:24:19 +00:00
|
|
|
loadLayer();
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
emit modelChanged();
|
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataModel::attributeDeleted( int idx )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "BM attribute deleted" );
|
2009-03-20 18:24:19 +00:00
|
|
|
loadLayer();
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
emit modelChanged();
|
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
void BeataModel::layerDeleted()
|
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
mIdRowMap.clear();
|
|
|
|
mRowIdMap.clear();
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "map sizes:%1, %2" ).arg( mRowIdMap.size() ).arg( mIdRowMap.size() ) );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
//TODO: check whether caching in data()/setData() doesn't cache old value
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::attributeValueChanged( int fid, int idx, const QVariant &value )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::layerModified( bool onlyGeometry )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( onlyGeometry )
|
2009-03-20 18:24:19 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
loadLayer();
|
|
|
|
emit modelChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BeataModel::loadLayer()
|
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
QgsFeature f;
|
|
|
|
bool ins = false, rm = false;
|
|
|
|
|
|
|
|
mRowIdMap.clear();
|
|
|
|
mIdRowMap.clear();
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( mFeatureCount < mLayer->pendingFeatureCount() )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "ins" );
|
|
|
|
ins = true;
|
|
|
|
beginInsertRows( QModelIndex(), mFeatureCount, mLayer->pendingFeatureCount() - 1 );
|
|
|
|
// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() - 1));
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
else if ( mFeatureCount > mLayer->pendingFeatureCount() )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "rm" );
|
|
|
|
rm = true;
|
|
|
|
beginRemoveRows( QModelIndex(), mLayer->pendingFeatureCount(), mFeatureCount - 1 );
|
|
|
|
// QgsDebugMsg(QString("%1, %2").arg(mFeatureCount).arg(mLayer->pendingFeatureCount() -1));
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->select( QgsAttributeList(), QgsRectangle(), false );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( int i = 0; mLayer->nextFeature( f ); ++i )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
mRowIdMap.insert( i, f.id() );
|
|
|
|
mIdRowMap.insert( f.id(), i );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// not needed when we have featureAdded signal
|
|
|
|
mFeatureCount = mLayer->pendingFeatureCount();
|
2009-03-27 17:42:35 +00:00
|
|
|
mFieldCount = mLayer->pendingFields().size();
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( ins )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
endInsertRows();
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "end ins" );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
else if ( rm )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
endRemoveRows();
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "end rm" );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
#if 0
|
|
|
|
QgsDebugMsg( "id->row" );
|
2009-03-20 18:24:19 +00:00
|
|
|
QMap<int, int>::iterator it;
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( it = mIdRowMap.begin(); it != mIdRowMap.end(); ++it )
|
|
|
|
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "row->id" );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( it = mRowIdMap.begin(); it != mRowIdMap.end(); ++it )
|
|
|
|
QgsDebugMsg( QString( "%1->%2" ).arg( it.key() ).arg( *it ) );
|
|
|
|
#endif
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::swapRows( int a, int b )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( a == b )
|
2009-03-20 18:24:19 +00:00
|
|
|
return;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
int rowA = idToRow( a );
|
|
|
|
int rowB = idToRow( b );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
//emit layoutAboutToBeChanged();
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
mRowIdMap.remove( rowA );
|
|
|
|
mRowIdMap.remove( rowB );
|
|
|
|
mRowIdMap.insert( rowA, b );
|
|
|
|
mRowIdMap.insert( rowB, a );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
mIdRowMap.remove( a );
|
|
|
|
mIdRowMap.remove( b );
|
|
|
|
mIdRowMap.insert( a, rowB );
|
|
|
|
mIdRowMap.insert( b, rowA );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
//emit layoutChanged();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
int BeataModel::idToRow( const int id ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mIdRowMap.contains( id ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "idToRow: id %1 not in map" ).arg( id ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mIdRowMap[id];
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
int BeataModel::rowToId( const int id ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mRowIdMap.contains( id ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( QString( "rowToId: row %1 not in map" ).arg( id ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mRowIdMap[id];
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
int BeataModel::rowCount( const QModelIndex &parent ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
return mFeatureCount;
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
int BeataModel::columnCount( const QModelIndex &parent ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
return mFieldCount;
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QVariant BeataModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( role == Qt::DisplayRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( orientation == Qt::Vertical ) //row
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( section );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-03-27 17:42:35 +00:00
|
|
|
QgsField field = mLayer->pendingFields()[ mAttributes[section] ]; //column
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( field.name() );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else return QVariant();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::sort( int column, Qt::SortOrder order )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
QgsAttributeMap row;
|
|
|
|
idColumnPair pair;
|
|
|
|
QgsAttributeList attrs;
|
|
|
|
QgsFeature f;
|
|
|
|
|
2009-04-02 12:52:34 +00:00
|
|
|
attrs.append( mAttributes[column] );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
emit layoutAboutToBeChanged();
|
2009-03-27 17:37:59 +00:00
|
|
|
// QgsDebugMsg("SORTing");
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
mSortList.clear();
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->select( attrs, QgsRectangle(), false );
|
|
|
|
while ( mLayer->nextFeature( f ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
row = f.attributeMap();
|
|
|
|
|
|
|
|
pair.id = f.id();
|
2009-03-27 17:42:35 +00:00
|
|
|
pair.columnItem = row[ mAttributes[column] ];
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
mSortList.append( pair );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( order == Qt::AscendingOrder )
|
|
|
|
qStableSort( mSortList.begin(), mSortList.end() );
|
2009-03-20 18:24:19 +00:00
|
|
|
else
|
2009-03-27 17:37:59 +00:00
|
|
|
qStableSort( mSortList.begin(), mSortList.end(), qGreater<idColumnPair>() );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
// recalculate id<->row maps
|
|
|
|
mRowIdMap.clear();
|
|
|
|
mIdRowMap.clear();
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
QList<idColumnPair>::Iterator it;
|
2009-03-27 17:37:59 +00:00
|
|
|
for ( it = mSortList.begin(); it != mSortList.end(); ++it, ++i )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
mRowIdMap.insert( i, it->id );
|
|
|
|
mIdRowMap.insert( it->id, i );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// restore selection
|
|
|
|
emit layoutChanged();
|
|
|
|
//reset();
|
|
|
|
emit modelChanged();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QVariant BeataModel::data( const QModelIndex &index, int role ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
return QVariant();
|
|
|
|
|
2009-03-27 17:42:35 +00:00
|
|
|
QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
|
2009-03-27 17:37:59 +00:00
|
|
|
bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
|
|
|
|
|
|
|
|
if ( role == Qt::TextAlignmentRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( fldNumeric )
|
|
|
|
return QVariant( Qt::AlignRight );
|
2009-03-20 18:24:19 +00:00
|
|
|
else
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( Qt::AlignLeft );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// if we don't have the row in current cache, load it from layer first
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( mLastRowId != rowToId( index.row() ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !res )
|
|
|
|
return QVariant( "ERROR" );
|
|
|
|
|
|
|
|
mLastRowId = rowToId( index.row() );
|
2009-03-27 17:42:35 +00:00
|
|
|
mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-04-03 06:54:21 +00:00
|
|
|
if ( !mLastRow )
|
2009-03-28 02:02:00 +00:00
|
|
|
return QVariant( "ERROR" );
|
|
|
|
|
2009-03-27 17:42:35 +00:00
|
|
|
QVariant& val = ( *mLastRow )[ mAttributes[index.column()] ];
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
if ( val.isNull() )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
// if the value is NULL, show that in table, but don't show "NULL" text in editor
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( role == Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return QVariant();
|
|
|
|
else
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( "NULL" );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// force also numeric data for EditRole to be strings
|
|
|
|
// otherwise it creates spinboxes instead of line edits
|
|
|
|
// (probably not what we do want)
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( fldNumeric && role == Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return val.toString();
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// convert to QString from some other representation
|
|
|
|
// this prevents displaying greater numbers in exponential format
|
|
|
|
return val.toString();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
bool BeataModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !index.isValid() || role != Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mLayer->isEditable() )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
bool res = mLayer->featureAtId( rowToId( index.row() ), mFeat, false, true );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( res )
|
|
|
|
{
|
|
|
|
mLastRowId = rowToId( index.row() );
|
|
|
|
mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
|
|
|
|
}
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mLayer->isModified() )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
emit dataChanged( index, index );
|
2009-03-20 18:24:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
Qt::ItemFlags BeataModel::flags( const QModelIndex &index ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !index.isValid() )
|
2009-03-20 18:24:19 +00:00
|
|
|
return Qt::ItemIsEnabled;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
Qt::ItemFlags flags = QAbstractItemModel::flags( index );
|
|
|
|
|
|
|
|
if ( mLayer->isEditable() )
|
2009-03-20 18:24:19 +00:00
|
|
|
flags |= Qt::ItemIsEditable;
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataModel::reload( const QModelIndex &index1, const QModelIndex &index2 )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
emit dataChanged( index1, index2 );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BeataModel::resetModel()
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BeataModel::changeLayout()
|
|
|
|
{
|
|
|
|
emit layoutChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BeataModel::incomingChangeLayout()
|
|
|
|
{
|
|
|
|
emit layoutAboutToBeChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// In-Memory model //
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
void BeataMemModel::loadLayer()
|
|
|
|
{
|
|
|
|
BeataModel::loadLayer();
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->select( mLayer->pendingAllAttributesList(), QgsRectangle(), false );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
QgsFeature f;
|
2009-03-27 17:37:59 +00:00
|
|
|
while ( mLayer->nextFeature( f ) )
|
|
|
|
mFeatureMap.insert( f.id(), f );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BeataMemModel::BeataMemModel
|
2009-03-27 17:37:59 +00:00
|
|
|
( QgsVectorLayer *theLayer )
|
|
|
|
: BeataModel( theLayer )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
loadLayer();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
QVariant BeataMemModel::data( const QModelIndex &index, int role ) const
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
return QVariant();
|
|
|
|
|
2009-03-27 17:42:35 +00:00
|
|
|
QVariant::Type fldType = mLayer->pendingFields()[ mAttributes[index.column()] ].type();
|
2009-03-27 17:37:59 +00:00
|
|
|
bool fldNumeric = ( fldType == QVariant::Int || fldType == QVariant::Double );
|
|
|
|
|
|
|
|
if ( role == Qt::TextAlignmentRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( fldNumeric )
|
|
|
|
return QVariant( Qt::AlignRight );
|
2009-03-20 18:24:19 +00:00
|
|
|
else
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( Qt::AlignLeft );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// if we don't have the row in current cache, load it from layer first
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( mLastRowId != rowToId( index.row() ) )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
//bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
|
2009-03-27 17:37:59 +00:00
|
|
|
bool res = mFeatureMap.contains( rowToId( index.row() ) );
|
|
|
|
|
|
|
|
if ( !res )
|
|
|
|
return QVariant( "ERROR" );
|
|
|
|
|
|
|
|
mLastRowId = rowToId( index.row() );
|
|
|
|
mFeat = mFeatureMap[rowToId( index.row() )];
|
2009-03-27 17:42:35 +00:00
|
|
|
mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-04-03 06:54:21 +00:00
|
|
|
if ( !mLastRow )
|
2009-03-28 02:02:00 +00:00
|
|
|
return QVariant( "ERROR" );
|
|
|
|
|
2009-03-27 17:42:35 +00:00
|
|
|
QVariant &val = ( *mLastRow )[ mAttributes[index.column()] ];
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
if ( val.isNull() )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
|
|
|
// if the value is NULL, show that in table, but don't show "NULL" text in editor
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( role == Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return QVariant();
|
|
|
|
else
|
2009-03-27 17:37:59 +00:00
|
|
|
return QVariant( "NULL" );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// force also numeric data for EditRole to be strings
|
|
|
|
// otherwise it creates spinboxes instead of line edits
|
|
|
|
// (probably not what we do want)
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( fldNumeric && role == Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return val.toString();
|
2009-03-27 17:37:59 +00:00
|
|
|
|
2009-03-20 18:24:19 +00:00
|
|
|
// convert to QString from some other representation
|
|
|
|
// this prevents displaying greater numbers in exponential format
|
|
|
|
return val.toString();
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
bool BeataMemModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !index.isValid() || role != Qt::EditRole )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mLayer->isEditable() )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
//bool res = mLayer->featureAtId(rowToId(index.row()), mFeat, false, true);
|
2009-03-27 17:37:59 +00:00
|
|
|
bool res = mFeatureMap.contains( rowToId( index.row() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( res )
|
|
|
|
{
|
|
|
|
mLastRowId = rowToId( index.row() );
|
|
|
|
mFeat = mFeatureMap[rowToId( index.row() )];
|
2009-04-03 06:54:21 +00:00
|
|
|
mLastRow = ( QgsAttributeMap * ) & mFeat.attributeMap();
|
2009-03-20 18:24:19 +00:00
|
|
|
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
// QgsDebugMsg(mFeatureMap[rowToId(index.row())].id());
|
|
|
|
mFeatureMap[rowToId( index.row() )].changeAttribute( index.column(), value );
|
2009-03-20 18:24:19 +00:00
|
|
|
// propagate back to the layer
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->changeAttributeValue( rowToId( index.row() ), index.column(), value, true );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
if ( !mLayer->isModified() )
|
2009-03-20 18:24:19 +00:00
|
|
|
return false;
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
emit dataChanged( index, index );
|
2009-03-20 18:24:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-03-27 17:37:59 +00:00
|
|
|
void BeataMemModel::featureDeleted( int fid )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
|
|
|
mFeatureMap.remove( fid );
|
|
|
|
BeataModel::featureDeleted( fid );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataMemModel::featureAdded( int fid )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
QgsFeature f;
|
2009-03-27 17:37:59 +00:00
|
|
|
mLayer->featureAtId( fid, f, false, true );
|
|
|
|
mFeatureMap.insert( fid, f );
|
|
|
|
BeataModel::featureAdded( fid );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
void BeataMemModel::attributeAdded( int idx )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
loadLayer();
|
2009-03-27 17:37:59 +00:00
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataMemModel::attributeDeleted( int idx )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
loadLayer();
|
2009-03-27 17:37:59 +00:00
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void BeataMemModel::layerDeleted()
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
2009-03-20 18:24:19 +00:00
|
|
|
mFeatureMap.clear();
|
|
|
|
BeataModel::layerDeleted();
|
|
|
|
}
|
2009-03-27 17:37:59 +00:00
|
|
|
|
|
|
|
void BeataMemModel::attributeValueChanged( int fid, int idx, const QVariant &value )
|
2009-03-20 18:24:19 +00:00
|
|
|
{
|
2009-03-27 17:37:59 +00:00
|
|
|
QgsDebugMsg( "entered." );
|
|
|
|
mFeatureMap[fid].changeAttribute( idx, value );
|
|
|
|
reload( index( 0, 0 ), index( rowCount(), columnCount() ) );
|
2009-03-20 18:24:19 +00:00
|
|
|
}
|