[QGIS Commit] r13977 - trunk/qgis/src/plugins/georeferencer

svn_qgis at osgeo.org svn_qgis at osgeo.org
Wed Jul 28 18:14:12 EDT 2010


Author: mmassing
Date: 2010-07-28 22:14:12 +0000 (Wed, 28 Jul 2010)
New Revision: 13977

Modified:
   trunk/qgis/src/plugins/georeferencer/qgsgcplistmodel.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgcplistwidget.cpp
   trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp
Log:
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.

Modified: trunk/qgis/src/plugins/georeferencer/qgsgcplistmodel.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgcplistmodel.cpp	2010-07-28 15:00:55 UTC (rev 13976)
+++ trunk/qgis/src/plugins/georeferencer/qgsgcplistmodel.cpp	2010-07-28 22:14:12 UTC (rev 13977)
@@ -27,44 +27,37 @@
 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 )
@@ -82,7 +75,7 @@
 
 void QgsGCPListModel::updateModel()
 {
-  clear();
+  //clear();
   if ( !mGCPList )
     return;
 
@@ -92,8 +85,6 @@
   vector<QgsPoint> mapCoords, pixelCoords;
   mGCPList->createGCPVectors( mapCoords, pixelCoords );
 
-
-
   //  // Setup table header
   QStringList itemLabels;
   QString unitType;
@@ -136,11 +127,11 @@
       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 @@
 
     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::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

Modified: trunk/qgis/src/plugins/georeferencer/qgsgcplistwidget.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgcplistwidget.cpp	2010-07-28 15:00:55 UTC (rev 13976)
+++ trunk/qgis/src/plugins/georeferencer/qgsgcplistwidget.cpp	2010-07-28 22:14:12 UTC (rev 13977)
@@ -18,6 +18,7 @@
 #include <QDoubleSpinBox>
 #include <QLineEdit>
 #include <QMenu>
+#include <QSortFilterProxyModel>
 
 #include "qgsgeorefdelegates.h"
 #include "qgsgeorefdatapoint.h"
@@ -35,12 +36,19 @@
     , 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::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::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 @@
   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 @@
   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::jumpToPoint()
 {
-  emit jumpToGCP( currentIndex().row() );
+  QModelIndex index = static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( currentIndex() );
+  emit jumpToGCP( index.row() );
 }
 
 void QgsGCPListWidget::adjustTableContent()

Modified: trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp
===================================================================
--- trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp	2010-07-28 15:00:55 UTC (rev 13976)
+++ trunk/qgis/src/plugins/georeferencer/qgsgeorefplugingui.cpp	2010-07-28 22:14:12 UTC (rev 13977)
@@ -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 @@
     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 @@
   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 @@
 
 void QgsGeorefPluginGui::clearGCPData()
 {
-  int rowCount = mGCPListWidget->model()->rowCount();
-  mGCPListWidget->model()->removeRows( 0, rowCount );
-
   qDeleteAll( mPoints );
   mPoints.clear();
+  mGCPListWidget->updateGCPList();
 
   mIface->mapCanvas()->refresh();
 }



More information about the QGIS-commit mailing list