Fix #2449: enables numerical sorting and automatic updates of gcp list.

-Use proxy model to implement dynamic sorting.
-Remove some legacy code.
-Employ user role for correct numerical sorting.

git-svn-id: http://svn.osgeo.org/qgis/trunk@13977 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
mmassing 2010-07-28 22:14:12 +00:00
parent b2d52b7df8
commit b81bf5f8cd
3 changed files with 58 additions and 79 deletions

View File

@ -27,44 +27,37 @@ using namespace std;
class QgsStandardItem : public QStandardItem
{
public:
QgsStandardItem( QString text ) : QStandardItem( text ) { init(); }
QgsStandardItem( int value ) : QStandardItem( QString::number( value ) ) { init(); }
QgsStandardItem( double value ) : QStandardItem( QString::number( value, 'f', 2 ) ) { init(); }
private:
void init()
QgsStandardItem( QString text ) : QStandardItem( text )
{
// In addition to the DisplayRole, also set the user role, which is used for sorting.
setData( QVariant( text ), Qt::UserRole);
setTextAlignment( Qt::AlignRight );
}
QgsStandardItem( int value ) : QStandardItem( QString::number( value ) )
{
// In addition to the DisplayRole, also set the user role, which is used for sorting.
// This is needed for numerical sorting to work corretly (otherwise sorting is lexicographic).
setData( QVariant( value ), Qt::UserRole);
setTextAlignment( Qt::AlignCenter );
}
};
#define QGSSTANDARDITEM(value) (new QgsStandardItem(value))
#if 0
template <class T> class QNumericItem : public QStandardItem
{
public:
QNumericItem( T value ) : QStandardItem( QString( "%1" ).arg( value ) ), mValue( value )
QgsStandardItem( double value ) : QStandardItem( QString::number( value, 'f', 2 ) )
{
// In addition to the DisplayRole, also set the user role, which is used for sorting.
// This is needed for numerical sorting to work corretly (otherwise sorting is lexicographic).
setData( QVariant( value ), Qt::UserRole);
setTextAlignment( Qt::AlignRight );
}
bool operator < ( const QStandardItem &other ) const
{
const QNumericItem<T> *otherD = dynamic_cast<const QNumericItem<T> *>( &other );
if ( otherD == NULL )
return false;
return mValue < otherD->mValue;
}
private:
T mValue;
};
#endif
QgsGCPListModel::QgsGCPListModel( QObject *parent )
: QStandardItemModel( parent )
, mGCPList( 0 )
, mGeorefTransform( 0 )
{
// Use data provided by Qt::UserRole as sorting key (needed for numerical sorting).
setSortRole( Qt::UserRole );
}
void QgsGCPListModel::setGCPList( QgsGCPList *theGCPList )
@ -82,7 +75,7 @@ void QgsGCPListModel::setGeorefTransform( QgsGeorefTransform *theGeorefTransform
void QgsGCPListModel::updateModel()
{
clear();
//clear();
if ( !mGCPList )
return;
@ -92,8 +85,6 @@ void QgsGCPListModel::updateModel()
vector<QgsPoint> mapCoords, pixelCoords;
mGCPList->createGCPVectors( mapCoords, pixelCoords );
// // Setup table header
QStringList itemLabels;
QString unitType;
@ -136,11 +127,11 @@ void QgsGCPListModel::updateModel()
si->setCheckState( Qt::Unchecked );
setItem( i, j++, si );
setItem( i, j++, QGSSTANDARDITEM( i ) /*create_item<int>(i)*/ );
setItem( i, j++, QGSSTANDARDITEM( p->pixelCoords().x() ) /*create_item<double>( p->pixelCoords().x() )*/ );
setItem( i, j++, QGSSTANDARDITEM( -p->pixelCoords().y() ) /*create_item<double>(-p->pixelCoords().y() )*/ );
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().x() ) /*create_item<double>( p->mapCoords().x() )*/ );
setItem( i, j++, QGSSTANDARDITEM( p->mapCoords().y() ) /*create_item<double>( p->mapCoords().y() )*/ );
setItem( i, j++, new QgsStandardItem( i ) );
setItem( i, j++, new QgsStandardItem( p->pixelCoords().x() ) );
setItem( i, j++, new QgsStandardItem( -p->pixelCoords().y() ) );
setItem( i, j++, new QgsStandardItem( p->mapCoords().x() ) );
setItem( i, j++, new QgsStandardItem( p->mapCoords().y() ) );
double residual;
double dX = 0;
@ -179,19 +170,17 @@ void QgsGCPListModel::updateModel()
if ( residual >= 0.f )
{
setItem( i, j++, QGSSTANDARDITEM( dX ) /*create_item<double>(dX)*/ );
setItem( i, j++, QGSSTANDARDITEM( dY ) /*create_item<double>(-dY)*/ );
setItem( i, j++, QGSSTANDARDITEM( residual ) /*create_item<double>(residual)*/ );
setItem( i, j++, new QgsStandardItem( dX ) );
setItem( i, j++, new QgsStandardItem( dY ) );
setItem( i, j++, new QgsStandardItem( residual ) );
}
else
{
setItem( i, j++, QGSSTANDARDITEM( "n/a" ) /*create_std_item("n/a")*/ );
setItem( i, j++, QGSSTANDARDITEM( "n/a" ) /*create_std_item("n/a")*/ );
setItem( i, j++, QGSSTANDARDITEM( "n/a" ) /*create_std_item("n/a")*/ );
setItem( i, j++, new QgsStandardItem( "n/a" ) );
setItem( i, j++, new QgsStandardItem( "n/a" ) );
setItem( i, j++, new QgsStandardItem( "n/a" ) );
}
}
//sort(); // Sort data
//reset(); // Signal to views that the model has changed
}
// --------------------------- public slots -------------------------------- //
@ -207,19 +196,3 @@ void QgsGCPListModel::onGCPListModified()
void QgsGCPListModel::onTransformationModified()
{
}
#if 0
template <class T> QNumericItem<T> *create_item( const T value, bool isEditable = true )
{
QNumericItem<T> *item = new QNumericItem<T>( value );
item->setEditable( isEditable );
return item;
}
QStandardItem *create_std_item( const QString &S, bool isEditable = false )
{
QStandardItem *std_item = new QStandardItem( S );
std_item->setEditable( isEditable );
return std_item;
}
#endif

View File

@ -18,6 +18,7 @@
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <QMenu>
#include <QSortFilterProxyModel>
#include "qgsgeorefdelegates.h"
#include "qgsgeorefdatapoint.h"
@ -35,12 +36,19 @@ QgsGCPListWidget::QgsGCPListWidget( QWidget *parent )
, mPrevRow( 0 )
, mPrevColumn( 0 )
{
setModel( mGCPListModel );
// Create a proxy model, which will handle dynamic sorting
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel( this );
proxyModel->setSourceModel( mGCPListModel );
proxyModel->setDynamicSortFilter( true );
proxyModel->setSortRole( Qt::UserRole );
setModel( proxyModel );
setSortingEnabled( true );
setContextMenuPolicy( Qt::CustomContextMenu );
setFocusPolicy( Qt::NoFocus );
verticalHeader()->hide();
setAlternatingRowColors( true );
// set delegates for items
setItemDelegateForColumn( 1, mNonEditableDelegate ); // id
@ -90,7 +98,8 @@ void QgsGCPListWidget::updateGCPList()
void QgsGCPListWidget::itemDoubleClicked( QModelIndex index )
{
QStandardItem *item = mGCPListModel->item( index.row(), 1 );
index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( index );
QStandardItem *item = mGCPListModel->item( index.row(), 1);
bool ok;
int id = item->text().toInt( &ok );
@ -102,6 +111,7 @@ void QgsGCPListWidget::itemDoubleClicked( QModelIndex index )
void QgsGCPListWidget::itemClicked( QModelIndex index )
{
index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( index );
QStandardItem *item = mGCPListModel->item( index.row(), index.column() );
if ( item->isCheckable() )
{
@ -172,6 +182,9 @@ void QgsGCPListWidget::showContextMenu( QPoint p )
if ( index == QModelIndex() )
return;
// Select the right-clicked item
setCurrentIndex( index );
QAction *jumpToPointAction = new QAction( tr( "Recenter" ), this );
connect( jumpToPointAction, SIGNAL( triggered() ), this, SLOT( jumpToPoint() ) );
m.addAction( jumpToPointAction );
@ -179,18 +192,17 @@ void QgsGCPListWidget::showContextMenu( QPoint p )
QAction *removeAction = new QAction( tr( "Remove" ), this );
connect( removeAction, SIGNAL( triggered() ), this, SLOT( removeRow() ) );
m.addAction( removeAction );
setCurrentIndex( index );
m.exec( QCursor::pos(), removeAction );
index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( index );
mPrevRow = index.row();
mPrevColumn = index.column();
}
void QgsGCPListWidget::removeRow()
{
// QgsGeorefDataPoint *p = mGCPList->at(currentIndex().row());
emit deleteDataPoint( currentIndex().row() );
QModelIndex index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( currentIndex() );
emit deleteDataPoint( index.row() );
}
void QgsGCPListWidget::editCell()
@ -200,7 +212,8 @@ void QgsGCPListWidget::editCell()
void QgsGCPListWidget::jumpToPoint()
{
emit jumpToGCP( currentIndex().row() );
QModelIndex index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( currentIndex() );
emit jumpToGCP( index.row() );
}
void QgsGCPListWidget::adjustTableContent()

View File

@ -61,6 +61,7 @@
#include "qgstransformsettingsdialog.h"
#include "qgsgeorefplugingui.h"
#include <assert.h>
QgsGeorefDockWidget::QgsGeorefDockWidget( const QString & title, QWidget * parent, Qt::WindowFlags flags )
@ -483,16 +484,10 @@ void QgsGeorefPluginGui::deleteDataPoint( const QPoint &coords )
QgsGeorefDataPoint* pt = *it;
if ( /*pt->pixelCoords() == coords ||*/ pt->contains( coords, true ) ) // first operand for removing from GCP table
{
int row = mPoints.indexOf( *it );
mGCPListWidget->model()->removeRow( row );
delete *it;
mPoints.erase( it );
mGCPListWidget->updateGCPList();
// mGCPListWidget->setGCPList(&mPoints);
// logRequaredGCPs();
mCanvas->refresh();
break;
}
@ -500,10 +495,10 @@ void QgsGeorefPluginGui::deleteDataPoint( const QPoint &coords )
updateGeorefTransform();
}
void QgsGeorefPluginGui::deleteDataPoint( int index )
void QgsGeorefPluginGui::deleteDataPoint( int theGCPIndex )
{
mGCPListWidget->model()->removeRow( index );
delete mPoints.takeAt( index );
assert( theGCPIndex >= 0 );
delete mPoints.takeAt( theGCPIndex );
mGCPListWidget->updateGCPList();
updateGeorefTransform();
}
@ -1932,11 +1927,9 @@ bool QgsGeorefPluginGui::equalGCPlists( const QgsGCPList &list1, const QgsGCPLis
void QgsGeorefPluginGui::clearGCPData()
{
int rowCount = mGCPListWidget->model()->rowCount();
mGCPListWidget->model()->removeRows( 0, rowCount );
qDeleteAll( mPoints );
mPoints.clear();
mGCPListWidget->updateGCPList();
mIface->mapCanvas()->refresh();
}