Skip to content

Commit

Permalink
Fix #2449: enables numerical sorting and automatic updates of gcp list.
Browse files Browse the repository at this point in the history
-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/qgis@13977 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mmassing committed Jul 28, 2010
1 parent 9ddae24 commit 7cc05aa
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 77 deletions.
85 changes: 29 additions & 56 deletions src/plugins/georeferencer/qgsgcplistmodel.cpp
Expand Up @@ -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 )
{
setTextAlignment( Qt::AlignCenter );
// In addition to the DisplayRole, also set the user role, which is used for sorting.
setData( QVariant( text ), Qt::UserRole);
setTextAlignment( Qt::AlignRight );
}
};

#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( 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 );
}

bool operator < ( const QStandardItem &other ) const
QgsStandardItem( double value ) : QStandardItem( QString::number( value, 'f', 2 ) )
{
const QNumericItem<T> *otherD = dynamic_cast<const QNumericItem<T> *>( &other );
if ( otherD == NULL )
return false;
return mValue < otherD->mValue;
// 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 );
}
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 )
Expand All @@ -82,7 +75,7 @@ void QgsGCPListModel::setGeorefTransform( QgsGeorefTransform *theGeorefTransform

void QgsGCPListModel::updateModel()
{
clear();
//clear();
if ( !mGCPList )
return;

Expand All @@ -92,8 +85,6 @@ void QgsGCPListModel::updateModel()
vector<QgsPoint> mapCoords, pixelCoords;
mGCPList->createGCPVectors( mapCoords, pixelCoords );



// // Setup table header
QStringList itemLabels;
QString unitType;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 -------------------------------- //
Expand All @@ -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
29 changes: 21 additions & 8 deletions src/plugins/georeferencer/qgsgcplistwidget.cpp
Expand Up @@ -18,6 +18,7 @@
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <QMenu>
#include <QSortFilterProxyModel>

#include "qgsgeorefdelegates.h"
#include "qgsgeorefdatapoint.h"
Expand All @@ -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
Expand Down Expand Up @@ -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 );

Expand All @@ -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() )
{
Expand Down Expand Up @@ -172,25 +182,27 @@ 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 );

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()
Expand All @@ -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()
Expand Down
19 changes: 6 additions & 13 deletions src/plugins/georeferencer/qgsgeorefplugingui.cpp
Expand Up @@ -61,6 +61,7 @@
#include "qgstransformsettingsdialog.h"

#include "qgsgeorefplugingui.h"
#include <assert.h>


QgsGeorefDockWidget::QgsGeorefDockWidget( const QString & title, QWidget * parent, Qt::WindowFlags flags )
Expand Down Expand Up @@ -483,27 +484,21 @@ 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;
}
}
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();
}
Expand Down Expand Up @@ -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();
}

0 comments on commit 7cc05aa

Please sign in to comment.