[QGIS Commit] r11572 - in trunk/qgis: python/core src/app src/core src/core/raster src/ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Sep 5 15:49:47 EDT 2009


Author: jef
Date: 2009-09-05 15:49:47 -0400 (Sat, 05 Sep 2009)
New Revision: 11572

Modified:
   trunk/qgis/python/core/qgsrect.sip
   trunk/qgis/src/app/qgisapp.cpp
   trunk/qgis/src/app/qgsidentifyresults.cpp
   trunk/qgis/src/app/qgsidentifyresults.h
   trunk/qgis/src/app/qgsmaptoolidentify.cpp
   trunk/qgis/src/app/qgsmaptoolidentify.h
   trunk/qgis/src/app/qgsoptions.cpp
   trunk/qgis/src/app/qgsprojectproperties.cpp
   trunk/qgis/src/core/qgsrectangle.cpp
   trunk/qgis/src/core/qgsrectangle.h
   trunk/qgis/src/core/raster/qgsrasterlayer.cpp
   trunk/qgis/src/ui/qgsoptionsbase.ui
   trunk/qgis/src/ui/qgsprojectpropertiesbase.ui
Log:
[FEATURE] multi-layer identify

Modified: trunk/qgis/python/core/qgsrect.sip
===================================================================
--- trunk/qgis/python/core/qgsrect.sip	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/python/core/qgsrect.sip	2009-09-05 19:49:47 UTC (rev 11572)
@@ -64,6 +64,9 @@
     //! return true when rectangle contains other rectangle
     //! @note added in version 1.1
     bool contains( const QgsRectangle& rect ) const;
+    //! return true when rectangle contains a point
+    //! @note added in version 1.3
+    bool contains( const QgsPoint& p ) const;
     //! expand the rectangle so that covers both the original rectangle and the given rectangle
     void combineExtentWith(QgsRectangle *rect);
     //! expand the rectangle so that covers both the original rectangle and the given point

Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgisapp.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -767,7 +767,7 @@
   shortcuts->registerAction( mActionIdentify, tr( "Ctrl+Shift+I", "Click on features to identify them" ) );
   mActionIdentify->setStatusTip( tr( "Click on features to identify them" ) );
   connect( mActionIdentify, SIGNAL( triggered() ), this, SLOT( identify() ) );
-  mActionIdentify->setEnabled( false );
+  mActionIdentify->setEnabled( QSettings().value( "/Map/identifyMode", 0 ).toInt() != 0 );
 
   mActionMeasure = new QAction( getThemeIcon( "mActionMeasure.png" ), tr( "Measure Line " ), this );
   shortcuts->registerAction( mActionMeasure, tr( "Ctrl+Shift+M", "Measure a Line" ) );
@@ -5542,7 +5542,7 @@
   if ( !layer )
   {
     mActionSelect->setEnabled( false );
-    mActionIdentify->setEnabled( false );
+    mActionIdentify->setEnabled( QSettings().value( "/Map/identifyMode", 0 ).toInt() != 0 );
     mActionZoomActualSize->setEnabled( false );
     mActionOpenTable->setEnabled( false );
     mActionToggleEditing->setEnabled( false );
@@ -5785,19 +5785,25 @@
     //Enable the Identify tool ( GDAL datasets draw without a provider )
     //but turn off if data provider exists and has no Identify capabilities
     mActionIdentify->setEnabled( true );
-    const QgsRasterLayer* vlayer = dynamic_cast<const QgsRasterLayer*>( layer );
-    const QgsRasterDataProvider* dprovider = vlayer->dataProvider();
-    if ( dprovider )
+
+    QSettings settings;
+    int identifyMode = settings.value( "/Map/identifyMode", 0 ).toInt();
+    if ( identifyMode == 0 )
     {
-      // does provider allow the identify map tool?
-      if ( dprovider->capabilities() & QgsRasterDataProvider::Identify )
+      const QgsRasterLayer *rlayer = dynamic_cast<const QgsRasterLayer*>( layer );
+      const QgsRasterDataProvider* dprovider = rlayer->dataProvider();
+      if ( dprovider )
       {
-        mActionIdentify->setEnabled( TRUE );
+        // does provider allow the identify map tool?
+        if ( dprovider->capabilities() & QgsRasterDataProvider::Identify )
+        {
+          mActionIdentify->setEnabled( true );
+        }
+        else
+        {
+          mActionIdentify->setEnabled( false );
+        }
       }
-      else
-      {
-        mActionIdentify->setEnabled( FALSE );
-      }
     }
   }
 }

Modified: trunk/qgis/src/app/qgsidentifyresults.cpp
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsidentifyresults.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -21,6 +21,12 @@
 #include "qgscontexthelp.h"
 #include "qgsapplication.h"
 #include "qgisapp.h"
+#include "qgsmaplayer.h"
+#include "qgsvectorlayer.h"
+#include "qgsrubberband.h"
+#include "qgsgeometry.h"
+#include "qgsattributedialog.h"
+#include "qgsmapcanvas.h"
 
 #include <QCloseEvent>
 #include <QLabel>
@@ -33,13 +39,25 @@
 
 #include "qgslogger.h"
 
-QgsIdentifyResults::QgsIdentifyResults( const QgsAttributeAction& actions,
-                                        QWidget *parent, Qt::WFlags f )
+// Tree hierachy
+//
+// layer [userrole: QgsMapLayer]
+//   feature: displayfield|displayvalue [userrole: fid]
+//     derived attributes
+//       name value
+//     name value
+//     name value
+//     name value
+//   feature
+//     derived attributes
+//       name value
+//     name value
+
+QgsIdentifyResults::QgsIdentifyResults( QgsMapCanvas *canvas, QWidget *parent, Qt::WFlags f )
     : QDialog( parent, f ),
-    mActions( actions ),
-    mClickedOnValue( 0 ),
     mActionPopup( 0 ),
-    mCurrentFeatureId( 0 )
+    mRubberBand( 0 ),
+    mCanvas( canvas )
 {
   setupUi( this );
   lstResults->setColumnCount( 2 );
@@ -48,16 +66,12 @@
 
   connect( buttonCancel, SIGNAL( clicked() ),
            this, SLOT( close() ) );
-  connect( lstResults, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
-           this, SLOT( clicked( QTreeWidgetItem * ) ) );
+
   connect( lstResults, SIGNAL( itemExpanded( QTreeWidgetItem* ) ),
            this, SLOT( itemExpanded( QTreeWidgetItem* ) ) );
 
   connect( lstResults, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
            this, SLOT( handleCurrentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
-
-  // The label to use for the Derived node in the identify results
-  mDerivedLabel = tr( "(Derived)" );
 }
 
 QgsIdentifyResults::~QgsIdentifyResults()
@@ -65,6 +79,58 @@
   delete mActionPopup;
 }
 
+QTreeWidgetItem *QgsIdentifyResults::layerItem( QObject *layer )
+{
+  QTreeWidgetItem *item;
+
+  for ( int i = 0; i < lstResults->topLevelItemCount(); i++ )
+  {
+    item = lstResults->topLevelItem( i );
+    if ( item->data( 0, Qt::UserRole ).value<QObject*>() == layer )
+      return item;
+  }
+
+  return 0;
+}
+
+void QgsIdentifyResults::addFeature( QgsMapLayer *layer, int fid,
+                                     QString displayField, QString displayValue,
+                                     const QMap<QString, QString> &attributes,
+                                     const QMap<QString, QString> &derivedAttributes )
+{
+  QTreeWidgetItem *item = layerItem( layer );
+
+  if ( item == 0 )
+  {
+    item = new QTreeWidgetItem( QStringList() << layer->name() << tr( "Layer" ) );
+    item->setData( 0, Qt::UserRole, QVariant::fromValue( dynamic_cast<QObject*>( layer ) ) );
+    lstResults->addTopLevelItem( item );
+
+    connect( layer, SIGNAL( destroyed() ), this, SLOT( layerDestroyed() ) );
+  }
+
+  QTreeWidgetItem *featItem = new QTreeWidgetItem( QStringList() << displayField << displayValue );
+  featItem->setData( 0, Qt::UserRole, fid );
+
+  for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
+  {
+    featItem->addChild( new QTreeWidgetItem( QStringList() << it.key() << it.value() ) );
+  }
+
+  if ( derivedAttributes.size() >= 0 )
+  {
+    QTreeWidgetItem *derivedItem = new QTreeWidgetItem( QStringList() << tr( "(Derived)" ) );
+    featItem->addChild( derivedItem );
+
+    for ( QMap< QString, QString>::const_iterator it = derivedAttributes.begin(); it != derivedAttributes.end(); it++ )
+    {
+      derivedItem->addChild( new QTreeWidgetItem( QStringList() << it.key() << it.value() ) );
+    }
+  }
+
+  item->addChild( featItem );
+}
+
 // Call to show the dialog box.
 void QgsIdentifyResults::show()
 {
@@ -96,16 +162,30 @@
 
 void QgsIdentifyResults::contextMenuEvent( QContextMenuEvent* event )
 {
-  QTreeWidgetItem* item = lstResults->itemAt( lstResults->viewport()->mapFrom( this, event->pos() ) );
+  QTreeWidgetItem *item = lstResults->itemAt( lstResults->viewport()->mapFrom( this, event->pos() ) );
   // if the user clicked below the end of the attribute list, just return
-  if ( item == NULL )
+  if ( !item )
     return;
 
   if ( mActionPopup == 0 )
   {
+    QgsVectorLayer *vlayer = vectorLayer( item );
+    if ( vlayer == 0 )
+      return;
+
+    QgsAttributeAction *actions = vlayer->actions();
+
     mActionPopup = new QMenu();
 
     QAction *a;
+
+    if ( vlayer->isEditable() )
+    {
+      a = mActionPopup->addAction( tr( "Edit feature" ) );
+      a->setEnabled( true );
+      a->setData( QVariant::fromValue( -3 ) );
+    }
+
     a = mActionPopup->addAction( tr( "Copy attribute value" ) );
     a->setEnabled( true );
     a->setData( QVariant::fromValue( -2 ) );
@@ -114,7 +194,7 @@
     a->setEnabled( true );
     a->setData( QVariant::fromValue( -1 ) );
 
-    if ( mActions.size() > 0 )
+    if ( actions && actions->size() > 0 )
     {
       // The assumption is made that an instance of QgsIdentifyResults is
       // created for each new Identify Results dialog box, and that the
@@ -124,8 +204,8 @@
       a->setEnabled( false );
       mActionPopup->addSeparator();
 
-      QgsAttributeAction::aIter iter = mActions.begin();
-      for ( int j = 0; iter != mActions.end(); ++iter, ++j )
+      QgsAttributeAction::aIter iter = actions->begin();
+      for ( int j = 0; iter != actions->end(); ++iter, ++j )
       {
         QAction* a = mActionPopup->addAction( iter->name() );
         // The menu action stores an integer that is used later on to
@@ -134,14 +214,9 @@
       }
     }
 
-    connect( mActionPopup, SIGNAL( triggered( QAction* ) ),
-             this, SLOT( popupItemSelected( QAction* ) ) );
+    connect( mActionPopup, SIGNAL( triggered( QAction* ) ), this, SLOT( popupItemSelected( QAction* ) ) );
   }
 
-  // Save the attribute values as these are needed for substituting into
-  // the action.
-  extractAllItemData( item );
-
   mActionPopup->popup( event->globalPos() );
 }
 
@@ -160,75 +235,6 @@
   settings.setValue( "/Windows/Identify/geometry", saveGeometry() );
 }
 
-/** add an attribute and its value to the list */
-void QgsIdentifyResults::addAttribute( QTreeWidgetItem * fnode, QString field, QString value )
-{
-  QStringList labels;
-  labels << field << value;
-  new QTreeWidgetItem( fnode, labels );
-}
-
-void QgsIdentifyResults::addAttribute( QString field, QString value )
-{
-  QStringList labels;
-  labels << field << value;
-  new QTreeWidgetItem( lstResults, labels );
-}
-
-void QgsIdentifyResults::addDerivedAttribute( QTreeWidgetItem * fnode, QString field, QString value )
-{
-  QTreeWidgetItem * daRootNode;
-
-  // Determine if this is the first derived attribute for this feature or not
-  if ( mDerivedAttributeRootNodes.find( fnode ) != mDerivedAttributeRootNodes.end() )
-  {
-    // Reuse existing derived-attribute root node
-    daRootNode = mDerivedAttributeRootNodes[fnode];
-  }
-  else
-  {
-    // Create new derived-attribute root node
-    daRootNode = new QTreeWidgetItem( fnode, QStringList( mDerivedLabel ) );
-    QFont font = daRootNode->font( 0 );
-    font.setItalic( true );
-    daRootNode->setFont( 0, font );
-    mDerivedAttributeRootNodes[fnode] = daRootNode;
-  }
-
-  QStringList labels;
-  labels << field << value;
-  new QTreeWidgetItem( daRootNode, labels );
-}
-
-void QgsIdentifyResults::addEdit( QTreeWidgetItem * fnode, int id )
-{
-  QStringList labels;
-  labels << "edit" << QString::number( id );
-  QTreeWidgetItem *item = new QTreeWidgetItem( fnode, labels );
-
-  item->setIcon( 0, QgisApp::getThemeIcon( "/mIconEditable.png" ) );
-}
-
-void QgsIdentifyResults::addAction( QTreeWidgetItem * fnode, int id, QString field, QString value )
-{
-  QStringList labels;
-  labels << field << value << "action" << QString::number( id );
-  QTreeWidgetItem *item = new QTreeWidgetItem( fnode, labels );
-
-  item->setIcon( 0, QgisApp::getThemeIcon( "/mAction.png" ) );
-}
-
-/** Add a feature node to the list */
-QTreeWidgetItem *QgsIdentifyResults::addNode( QString label )
-{
-  return new QTreeWidgetItem( lstResults, QStringList( label ) );
-}
-
-void QgsIdentifyResults::setTitle( QString title )
-{
-  setWindowTitle( tr( "Identify Results - %1" ).arg( title ) );
-}
-
 void QgsIdentifyResults::setColumnText( int column, const QString & label )
 {
   QTreeWidgetItem* header = lstResults->headerItem();
@@ -238,6 +244,10 @@
 // Run the action that was selected in the popup menu
 void QgsIdentifyResults::popupItemSelected( QAction* menuAction )
 {
+  QTreeWidgetItem *item = lstResults->currentItem();
+  if ( item == 0 )
+    return;
+
   int id = menuAction->data().toInt();
 
   if ( id < 0 )
@@ -245,13 +255,20 @@
     QClipboard *clipboard = QApplication::clipboard();
     QString text;
 
-    if ( id == -2 )
+    if ( id == -3 )
     {
-      text = mValues[ mClickedOnValue ].second;
+      editFeature( item );
     }
+    else if ( id == -2 )
+    {
+      text = item->data( 1, Qt::DisplayRole ).toString();
+    }
     else
     {
-      for ( std::vector< std::pair<QString, QString> >::const_iterator it = mValues.begin(); it != mValues.end(); it++ )
+      std::vector< std::pair<QString, QString> > attributes;
+      retrieveAttributes( item, attributes );
+
+      for ( std::vector< std::pair<QString, QString> >::iterator it = attributes.begin(); it != attributes.end(); it++ )
       {
         text += QString( "%1: %2\n" ).arg( it->first ).arg( it->second );
       }
@@ -262,17 +279,10 @@
   }
   else
   {
-    mActions.doAction( id, mValues, mClickedOnValue );
+    doAction( item );
   }
 }
 
-/** Expand all the identified features (show their attributes). */
-void QgsIdentifyResults::showAllAttributes()
-{
-  // Easy now with Qt 4.2...
-  lstResults->expandAll();
-}
-
 void QgsIdentifyResults::expandColumnsToFit()
 {
   lstResults->resizeColumnToContents( 0 );
@@ -281,40 +291,86 @@
 
 void QgsIdentifyResults::clear()
 {
-  mDerivedAttributeRootNodes.clear();
   lstResults->clear();
+
+  if ( mRubberBand )
+  {
+    delete mRubberBand;
+    mRubberBand = 0;
+  }
 }
 
-void QgsIdentifyResults::setMessage( QString shortMsg, QString longMsg )
+void QgsIdentifyResults::doAction( QTreeWidgetItem *item )
 {
-  QStringList labels;
-  labels << shortMsg << longMsg;
-  new QTreeWidgetItem( lstResults, labels );
+  std::vector< std::pair<QString, QString> > attributes;
+  QTreeWidgetItem *featItem = retrieveAttributes( item, attributes );
+  if ( !featItem )
+    return;
+
+  int id = featItem->data( 0, Qt::UserRole ).toInt();
+
+  QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer *>( featItem->parent()->data( 0, Qt::UserRole ).value<QObject *>() );
+  if ( !layer )
+    return;
+
+  layer->actions()->doAction( id, attributes, id );
 }
 
-void QgsIdentifyResults::setActions( const QgsAttributeAction& actions )
+QTreeWidgetItem *QgsIdentifyResults::featureItem( QTreeWidgetItem *item )
 {
-  mActions = actions;
+  QTreeWidgetItem *featItem;
+  if ( item->parent() )
+  {
+    if ( item->parent()->parent() )
+    {
+      // attribute item
+      featItem = item->parent();
+    }
+    else
+    {
+      // feature item
+      featItem = item;
+    }
+  }
+  else
+  {
+    // layer item
+    if ( item->childCount() > 1 )
+      return 0;
+
+    featItem = item->child( 0 );
+  }
+
+  return featItem;
 }
 
-void QgsIdentifyResults::clicked( QTreeWidgetItem *item )
+QgsVectorLayer *QgsIdentifyResults::vectorLayer( QTreeWidgetItem *item )
 {
-  if ( !item )
-    return;
-
-  if ( item->text( 2 ) == "action" )
+  if ( item->parent() )
   {
-    int id = item->text( 3 ).toInt();
+    item = featureItem( item )->parent();
+  }
 
-    extractAllItemData( item );
+  return dynamic_cast<QgsVectorLayer *>( item->data( 0, Qt::UserRole ).value<QObject *>() );
+}
 
-    mActions.doAction( id, mValues, mClickedOnValue );
-  }
-  else if ( item->text( 0 ) == "edit" )
+
+QTreeWidgetItem *QgsIdentifyResults::retrieveAttributes( QTreeWidgetItem *item, std::vector< std::pair<QString, QString> > &attributes )
+{
+  QTreeWidgetItem *featItem = featureItem( item );
+
+  attributes.clear();
+  for ( int i = 0; i < featItem->childCount(); i++ )
   {
-    emit editFeature( item->text( 1 ).toInt() );
+    QTreeWidgetItem *item = featItem->child( i );
+    if ( item->childCount() > 0 )
+      continue;
+    attributes.push_back( std::make_pair( item->data( 0, Qt::DisplayRole ).toString(), item->data( 1, Qt::DisplayRole ).toString() ) );
   }
+
+  return featItem;
 }
+
 void QgsIdentifyResults::on_buttonHelp_clicked()
 {
   QgsContextHelp::run( context_id );
@@ -327,99 +383,94 @@
 
 void QgsIdentifyResults::handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
 {
-  if ( lstResults->model()->rowCount() <= 1 )
-    return;
-
   if ( current == NULL )
   {
-    mCurrentFeatureId = 0;
-    emit selectedFeatureChanged( 0 );
+    emit selectedFeatureChanged( 0, 0 );
     return;
   }
 
-  // move to node where is saved feature ID
-  QTreeWidgetItem* topLevelItem = current;
-  while ( topLevelItem->parent() != NULL )
-  {
-    topLevelItem = topLevelItem->parent();
-  }
+  highlightFeature( current );
+}
 
-  QVariant fid = topLevelItem->data( 0, Qt::UserRole );
+void QgsIdentifyResults::layerDestroyed()
+{
+  delete layerItem( sender() );
+}
 
-  // no data saved...
-  if ( fid.type() != QVariant::Int )
+void QgsIdentifyResults::highlightFeature( QTreeWidgetItem *item )
+{
+  QgsVectorLayer *layer = vectorLayer( item );
+  if ( !layer )
     return;
-  int fid2 = fid.toInt();
 
-  if ( fid2 == mCurrentFeatureId )
+  QTreeWidgetItem *featItem = featureItem( item );
+  if ( !featItem )
     return;
 
-  mCurrentFeatureId = fid2;
-  emit selectedFeatureChanged( mCurrentFeatureId );
-}
+  int fid = featItem->data( 0, Qt::UserRole ).toInt();
 
-void QgsIdentifyResults::extractAllItemData( QTreeWidgetItem* item )
-{
-  // Extracts the name/value pairs from the given item. This includes data
-  // under the (Derived) item.
+  delete mRubberBand;
+  mRubberBand = 0;
 
-  // A little bit complicated because the user could of right-clicked
-  // on any item in the dialog box. We want a toplevel item, so walk upwards
-  // as far as possible.
-  // We also want to keep track of which row in the identify results table was
-  // actually clicked on. This is stored as an index into the mValues vector.
+  QgsFeature feat;
+  if ( ! layer->featureAtId( fid, feat, true, false ) )
+  {
+    return;
+  }
 
-  QTreeWidgetItem* child = item;
-  QTreeWidgetItem* parent = child->parent();
-  while ( parent != 0 )
+  if ( !feat.geometry() )
   {
-    child = parent;
-    parent = parent->parent();
+    return;
   }
-  parent = child;
 
-  mValues.clear();
+  mRubberBand = new QgsRubberBand( mCanvas, feat.geometry()->type() == QGis::Polygon );
 
-  // For the code below we
-  // need to do the comparison on the text strings rather than the
-  // pointers because if the user clicked on the parent, we need
-  // to pick up which child that actually is (the parent in the
-  // identify results dialog box is just one of the children
-  // that has been chosen by some method).
+  if ( mRubberBand )
+  {
+    mRubberBand->setToGeometry( feat.geometry(), layer );
+    mRubberBand->setWidth( 2 );
+    mRubberBand->setColor( Qt::red );
+    mRubberBand->show();
+  }
+}
 
-  int valuesIndex = 0;
+void QgsIdentifyResults::editFeature( QTreeWidgetItem *item )
+{
+  QgsVectorLayer *layer = vectorLayer( item );
+  if ( !layer || !layer->isEditable() )
+    return;
 
-  for ( int j = 0; j < parent->childCount(); ++j )
-  {
-    // For derived attributes, build up a virtual name
-    if ( parent->child( j )->text( 0 ) == mDerivedLabel )
-    {
-      for ( int k = 0; k < parent->child( j )->childCount(); ++k )
-      {
-        mValues.push_back(
-          std::make_pair( mDerivedLabel + "."
-                          + parent->child( j )->child( k )->text( 0 ),
-                          parent->child( j )->child( k )->text( 1 ) ) );
+  QTreeWidgetItem *featItem = featureItem( item );
+  if ( !featItem )
+    return;
 
-        if ( item == parent->child( j )->child( k ) )
-        {
-          mClickedOnValue = valuesIndex;
-        }
+  int fid = featItem->data( 0, Qt::UserRole ).toInt();
 
-        valuesIndex++;
-      }
-    }
-    else // do the actual feature attributes
+  QgsFeature f;
+  if ( ! layer->featureAtId( fid, f ) )
+    return;
+
+  QgsAttributeMap src = f.attributeMap();
+
+  layer->beginEditCommand( tr( "Attribute changed" ) );
+  QgsAttributeDialog *ad = new QgsAttributeDialog( layer, &f );
+  if ( ad->exec() )
+  {
+    const QgsAttributeMap &dst = f.attributeMap();
+    for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
     {
-      mValues.push_back( std::make_pair( parent->child( j )->text( 0 ),
-                                         parent->child( j )->text( 1 ) ) );
-
-      if ( item == parent->child( j ) )
+      if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
       {
-        mClickedOnValue = valuesIndex;
+        layer->changeAttributeValue( f.id(), it.key(), it.value() );
       }
-
-      valuesIndex++;
     }
+    layer->endEditCommand();
   }
+  else
+  {
+    layer->destroyEditCommand();
+  }
+
+  delete ad;
+  mCanvas->refresh();
 }

Modified: trunk/qgis/src/app/qgsidentifyresults.h
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.h	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsidentifyresults.h	2009-09-05 19:49:47 UTC (rev 11572)
@@ -30,6 +30,11 @@
 class QAction;
 class QMenu;
 
+class QgsMapLayer;
+class QgsVectorLayer;
+class QgsRubberBand;
+class QgsMapCanvas;
+
 /**
  *@author Gary E.Sherman
  */
@@ -41,54 +46,26 @@
 
     //! Constructor - takes it own copy of the QgsAttributeAction so
     // that it is independent of whoever created it.
-    QgsIdentifyResults( const QgsAttributeAction& actions, QWidget *parent = 0, Qt::WFlags f = 0 );
+    QgsIdentifyResults( QgsMapCanvas *canvas, QWidget *parent = 0, Qt::WFlags f = 0 );
 
     ~QgsIdentifyResults();
 
-    /** Add an attribute to the feature display node */
-    void addAttribute( QTreeWidgetItem *parent, QString field, QString value );
+    /** Remove results */
+    void clear();
 
-    /** Add an attribute */
-    void addAttribute( QString field, QString value );
+    /** Add add feature */
+    void addFeature( QgsMapLayer *layer, int fid,
+                     QString displayField, QString displayValue,
+                     const QMap< QString, QString > &attributes,
+                     const QMap< QString, QString > &derivedAttributes );
 
-    /** Add a derived attribute (e.g. Length, Area) to the feature display node */
-    void addDerivedAttribute( QTreeWidgetItem *parent, QString field, QString value );
-
-    /** Add an action to the feature display node */
-    void addAction( QTreeWidgetItem *parent, int id, QString field, QString value );
-
-    /** Add an edit action to the feature display node */
-    void addEdit( QTreeWidgetItem *parent, int id );
-
-    /** Add a feature node to the feature display */
-    QTreeWidgetItem * addNode( QString label );
-    /** Set the title for the identify results dialog */
-    void setTitle( QString title );
-    /** Set header column */
-    void setColumnText( int column, const QString & label );
-    void saveWindowLocation();
-    void restorePosition();
     void closeEvent( QCloseEvent *e );
-    void showAllAttributes();
 
-    /** Resize all of the columns to fit the data in them */
-    void expandColumnsToFit();
-
-    /** Remove results */
-    void clear();
-
     /** Set "No features ... " */
     void setMessage( QString shortMsg, QString longMsg );
 
-    /** Set actions */
-    void setActions( const QgsAttributeAction& actions );
-
-    //void accept();
-    //void reject();
-
   signals:
-    void selectedFeatureChanged( int featureId );
-    void editFeature( int featureId );
+    void selectedFeatureChanged( QgsVectorLayer *, int featureId );
 
   public slots:
 
@@ -98,43 +75,39 @@
     void contextMenuEvent( QContextMenuEvent* );
     void popupItemSelected( QAction* menuAction );
 
-    /* Item in tree was clicked */
-    void clicked( QTreeWidgetItem *lvi );
+    void layerDestroyed();
 
     //! Context help
     void on_buttonHelp_clicked();
 
     /* Called when an item is expanded so that we can ensure that the
        column width if expanded to show it */
-    void itemExpanded( QTreeWidgetItem* );
+    void itemExpanded( QTreeWidgetItem * );
 
     //! sends signal if current feature id has changed
-    void handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous );
+    void handleCurrentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous );
 
-
   private:
+    QMenu *mActionPopup;
+    QgsRubberBand *mRubberBand;
+    QgsMapCanvas *mCanvas;
 
-    bool mEditable;
-    QgsAttributeAction mActions;
-    int mClickedOnValue;
-    QMenu* mActionPopup;
-    std::vector<std::pair<QString, QString> > mValues;
     static const int context_id = 689216579;
-    int mCurrentFeatureId;
-    QString mDerivedLabel;
 
-    /**
-     Keeps track of what derived-attribute (e.g. Length, Area)
-     root nodes have been generated for each feature in this widget.
+    QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
+    QTreeWidgetItem *featureItem( QTreeWidgetItem *item );
+    QTreeWidgetItem *layerItem( QObject *layer );
+    QTreeWidgetItem *retrieveAttributes( QTreeWidgetItem *item, std::vector< std::pair<QString, QString> > &attributes );
 
-     First item:  Feature root node
-     Second item: Derived-attribute root node for that feature
-     */
-    std::map<QTreeWidgetItem *, QTreeWidgetItem *> mDerivedAttributeRootNodes;
+    void setColumnText( int column, const QString & label );
+    void expandColumnsToFit();
+    void saveWindowLocation();
+    void restorePosition();
 
-    // Convenience function to populate mValues with all of the item names and
-    // values for a item, including the derived ones.
-    void extractAllItemData( QTreeWidgetItem* item );
+    void highlightFeature( QTreeWidgetItem *item );
+    void editFeature( QTreeWidgetItem *item );
+
+    void doAction( QTreeWidgetItem *item );
 };
 
 #endif

Modified: trunk/qgis/src/app/qgsmaptoolidentify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolidentify.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsmaptoolidentify.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -26,11 +26,11 @@
 #include "qgsmessageviewer.h"
 #include "qgsmaptoolidentify.h"
 #include "qgsrasterlayer.h"
-#include "qgsrubberband.h"
 #include "qgscoordinatereferencesystem.h"
 #include "qgsvectordataprovider.h"
 #include "qgsvectorlayer.h"
-#include "qgsattributedialog.h"
+#include "qgsproject.h"
+#include "qgsmaplayerregistry.h"
 
 #include <QSettings>
 #include <QMessageBox>
@@ -39,14 +39,13 @@
 #include <QPixmap>
 
 QgsMapToolIdentify::QgsMapToolIdentify( QgsMapCanvas* canvas )
-    : QgsMapTool( canvas ),
-    mResults( 0 ),
-    mRubberBand( 0 ),
-    mLayer( 0 )
+    : QgsMapTool( canvas )
 {
   // set cursor
   QPixmap myIdentifyQPixmap = QPixmap(( const char ** ) identify_cursor );
   mCursor = QCursor( myIdentifyQPixmap, 1, 1 );
+
+  mResults = new QgsIdentifyResults( canvas, mCanvas->window() );
 }
 
 QgsMapToolIdentify::~QgsMapToolIdentify()
@@ -55,8 +54,6 @@
   {
     mResults->done( 0 );
   }
-
-  delete mRubberBand;
 }
 
 void QgsMapToolIdentify::canvasMoveEvent( QMouseEvent * e )
@@ -74,173 +71,93 @@
     return;
   }
 
-  // delete rubber band if there was any
-  delete mRubberBand;
-  mRubberBand = 0;
+  mResults->clear();
 
-  mLayer = mCanvas->currentLayer();
+  QSettings settings;
+  int identifyMode = settings.value( "/Map/identifyMode", 0 ).toInt();
 
-  if ( !mLayer )
+  bool res = false;
+
+  if ( identifyMode == 0 )
   {
-    QMessageBox::warning( mCanvas,
-                          tr( "No active layer" ),
-                          tr( "To identify features, you must choose an active layer by clicking on its name in the legend" ) );
-    return;
-  }
+    QgsMapLayer *layer = mCanvas->currentLayer();
 
-  // cleanup, when layer is removed
-  connect( mLayer, SIGNAL( destroyed() ), this, SLOT( layerDestroyed() ) );
+    if ( !layer )
+    {
+      QMessageBox::warning( mCanvas,
+                            tr( "No active layer" ),
+                            tr( "To identify features, you must choose an active layer by clicking on its name in the legend" ) );
+      return;
+    }
 
-  // call identify method for selected layer
-
-  // In the special case of the WMS provider,
-  // coordinates are sent back to the server as pixel coordinates
-  // not the layer's native CRS.  So identify on screen coordinates!
-  if ( mLayer->type() == QgsMapLayer::RasterLayer &&
-       dynamic_cast<QgsRasterLayer*>( mLayer )->providerKey() == "wms" )
-  {
-    identifyRasterWmsLayer( QgsPoint( e->x(), e->y() ) );
+    res = identifyLayer( layer, e->x(), e->y() );
   }
   else
   {
-    // convert screen coordinates to map coordinates
-    QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates( e->x(), e->y() );
+    QStringList noIdentifyLayerIdList = QgsProject::instance()->readListEntry( "Identify", "/disabledLayers" );
 
-    if ( mLayer->type() == QgsMapLayer::VectorLayer )
+    for ( int i = 0; i < mCanvas->layerCount(); i++ )
     {
-      identifyVectorLayer( idPoint );
-    }
-    else if ( mLayer->type() == QgsMapLayer::RasterLayer )
-    {
-      identifyRasterLayer( idPoint );
-    }
-    else
-    {
-      QgsDebugMsg( "unknown layer type!" );
-    }
-  }
-}
+      QgsMapLayer *layer = mCanvas->layer( i );
 
+      if ( noIdentifyLayerIdList.contains( layer->getLayerID() ) )
+        continue;
 
-void QgsMapToolIdentify::identifyRasterLayer( const QgsPoint& point )
-{
-  QgsRasterLayer *layer = dynamic_cast<QgsRasterLayer*>( mLayer );
-  if ( !layer )
-  {
-    return;
+      if ( identifyLayer( layer, e->x(), e->y() ) )
+      {
+        res = true;
+        if ( identifyMode == 1 )
+          break;
+      }
+    }
   }
 
-  QMap<QString, QString> attributes;
-  layer->identify( point, attributes );
-
-  if ( !mResults )
+  if ( res )
   {
-    QgsAttributeAction aa;
-    mResults = new QgsIdentifyResults( aa, mCanvas->window() );
-    mResults->setAttribute( Qt::WA_DeleteOnClose );
-    // Be informed when the dialog box is closed so that we can stop using it.
-    connect( mResults, SIGNAL( accepted() ), this, SLOT( resultsDialogGone() ) );
-    connect( mResults, SIGNAL( rejected() ), this, SLOT( resultsDialogGone() ) );
-    mResults->restorePosition();
+    mResults->show();
+    mResults->raise();
   }
   else
   {
-    mResults->raise();
-    mResults->clear();
+    mResults->hide();
+    QMessageBox::information( 0, tr( "Identify results" ), tr( "No features at this position found." ) );
   }
-
-  mResults->setTitle( layer->name() );
-  mResults->setColumnText( 0, tr( "Band" ) );
-
-  QMap<QString, QString>::iterator it;
-  for ( it = attributes.begin(); it != attributes.end(); it++ )
-  {
-    mResults->addAttribute( it.key(), it.value() );
-  }
-
-  mResults->addAttribute( tr( "(clicked coordinate)" ), point.toString() );
-
-  mResults->showAllAttributes();
-  mResults->show();
 }
 
-
-void QgsMapToolIdentify::identifyRasterWmsLayer( const QgsPoint& point )
+bool QgsMapToolIdentify::identifyLayer( QgsMapLayer *layer, int x, int y )
 {
-  QgsRasterLayer *layer = dynamic_cast<QgsRasterLayer*>( mLayer );
-  if ( !layer )
-  {
-    return;
-  }
+  bool res = false;
 
-  //if WMS layer does not cover the view origin,
-  //we need to map the view pixel coordinates
-  //to WMS layer pixel coordinates
-  QgsRectangle viewExtent = mCanvas->extent();
-  double mapUnitsPerPixel = mCanvas->mapUnitsPerPixel();
-  if ( mapUnitsPerPixel == 0 )
+  if ( layer->type() == QgsMapLayer::RasterLayer )
   {
-    return;
+    res = identifyRasterLayer( dynamic_cast<QgsRasterLayer *>( layer ), x, y );
   }
-  double xMinView = viewExtent.xMinimum();
-  double yMaxView = viewExtent.yMaximum();
-
-  QgsRectangle layerExtent = layer->extent();
-  double xMinLayer = layerExtent.xMinimum();
-  double yMaxLayer = layerExtent.yMaximum();
-
-  double i, j;
-
-  if ( xMinView < xMinLayer )
-  {
-    i = ( int )( point.x() - ( xMinLayer - xMinView ) / mapUnitsPerPixel );
-  }
   else
   {
-    i = point.x();
+    res = identifyVectorLayer( dynamic_cast<QgsVectorLayer *>( layer ), x, y );
   }
 
-  if ( yMaxView > yMaxLayer )
-  {
-    j = ( int )( point.y() - ( yMaxView - yMaxLayer ) / mapUnitsPerPixel );
-  }
-  else
-  {
-    j = point.y();
-  }
+  return res;
+}
 
 
-  QString text = layer->identifyAsText( QgsPoint( i, j ) );
+bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int y )
+{
+  if ( !layer )
+    return false;
 
-  if ( text.isEmpty() )
-  {
-    showError();
-    return;
-  }
+  QMap< QString, QString > attributes, derivedAttributes;
 
-  QgsMessageViewer* viewer = new QgsMessageViewer();
-  viewer->setWindowTitle( layer->name() );
-  viewer->setMessageAsPlainText( tr( "WMS identify result for %1:\n%2" ).arg( point.toString() ).arg( text ) );
+  QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );
 
-  viewer->showMessage(); // deletes itself on close
-}
+  derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );
 
-void QgsMapToolIdentify::identifyVectorLayer( const QgsPoint& point )
-{
-  QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer*>( mLayer );
-  if ( !layer )
-  {
-    return;
-  }
-
   // load identify radius from settings
   QSettings settings;
   double identifyValue = settings.value( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble();
   QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();
 
   int featureCount = 0;
-  QgsAttributeAction& actions = *layer->actions();
-  QString fieldIndex = layer->displayField();
   const QgsFieldMap& fields = layer->pendingFields();
 
   // init distance/area calculator
@@ -249,9 +166,10 @@
   calc.setEllipsoid( ellipsoid );
   calc.setSourceCrs( layer->srs().srsid() );
 
-  mFeatureList.clear();
   QApplication::setOverrideCursor( Qt::WaitCursor );
 
+  QgsFeatureList featureList;
+
   // toLayerCoordinates will throw an exception for an 'invalid' point.
   // For example, if you project a world map onto a globe using EPSG 2163
   // and then click somewhere off the globe, an exception will be thrown.
@@ -271,7 +189,7 @@
     layer->select( layer->pendingAllAttributesList(), r, true, true );
     QgsFeature f;
     while ( layer->nextFeature( f ) )
-      mFeatureList << QgsFeature( f );
+      featureList << QgsFeature( f );
   }
   catch ( QgsCsException & cse )
   {
@@ -282,62 +200,29 @@
 
   QApplication::restoreOverrideCursor();
 
-  if ( layer->isEditable() && mFeatureList.size() == 1 )
-  {
-    editFeature( mFeatureList[0] );
-    return;
-  }
+  QgsFeatureList::iterator f_it = featureList.begin();
 
-  // display features falling within the search radius
-  if ( !mResults )
+  for ( ; f_it != featureList.end(); ++f_it )
   {
-    mResults = new QgsIdentifyResults( actions, mCanvas->window() );
-    mResults->setAttribute( Qt::WA_DeleteOnClose );
-    // Be informed when the dialog box is closed so that we can stop using it.
-    connect( mResults, SIGNAL( accepted() ), this, SLOT( resultsDialogGone() ) );
-    connect( mResults, SIGNAL( rejected() ), this, SLOT( resultsDialogGone() ) );
-    connect( mResults, SIGNAL( selectedFeatureChanged( int ) ), this, SLOT( highlightFeature( int ) ) );
-    connect( mResults, SIGNAL( editFeature( int ) ), this, SLOT( editFeature( int ) ) );
-
-    // restore the identify window position and show it
-    mResults->restorePosition();
-  }
-  else
-  {
-    mResults->raise();
-    mResults->clear();
-    mResults->setActions( actions );
-  }
-
-  QApplication::setOverrideCursor( Qt::WaitCursor );
-
-  int lastFeatureId = 0;
-  QgsFeatureList::iterator f_it = mFeatureList.begin();
-
-  for ( ; f_it != mFeatureList.end(); ++f_it )
-  {
     featureCount++;
 
-    QTreeWidgetItem* featureNode = mResults->addNode( "foo" );
-    featureNode->setData( 0, Qt::UserRole, QVariant( f_it->id() ) ); // save feature id
-    lastFeatureId = f_it->id();
-    featureNode->setText( 0, fieldIndex );
+    int fid = f_it->id();
+    QString displayField, displayValue;
+    QMap<QString, QString> attributes, derivedAttributes;
 
-    if ( layer->isEditable() )
-      mResults->addEdit( featureNode, f_it->id() );
-
     const QgsAttributeMap& attr = f_it->attributeMap();
 
     for ( QgsAttributeMap::const_iterator it = attr.begin(); it != attr.end(); ++it )
     {
-      //QgsDebugMsg(it->fieldName() + " == " + fieldIndex);
+      QString attributeName = layer->attributeDisplayName( it.key() );
 
-      if ( fields[it.key()].name() == fieldIndex )
+      if ( fields[it.key()].name() == layer->displayField() )
       {
-        featureNode->setText( 1, it->toString() );
+        displayField = attributeName;
+        displayValue = it->toString();
       }
-      QString attributeName = layer->attributeDisplayName( it.key() );
-      mResults->addAttribute( featureNode, attributeName, it->isNull() ? "NULL" : it->toString() );
+
+      attributes.insert( attributeName, it->isNull() ? "NULL" : it->toString() );
     }
 
     // Calculate derived attributes and insert:
@@ -348,18 +233,18 @@
       QGis::UnitType myDisplayUnits;
       convertMeasurement( calc, dist, myDisplayUnits, false );
       QString str = calc.textUnit( dist, 3, myDisplayUnits, false );  // dist and myDisplayUnits are out params
-      mResults->addDerivedAttribute( featureNode, tr( "Length" ), str );
+      derivedAttributes.insert( tr( "Length" ), str );
       if ( f_it->geometry()->wkbType() == QGis::WKBLineString )
       {
         // Add the start and end points in as derived attributes
         str = QLocale::system().toString( f_it->geometry()->asPolyline().first().x(), 'g', 10 );
-        mResults->addDerivedAttribute( featureNode, tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
+        derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
         str = QLocale::system().toString( f_it->geometry()->asPolyline().first().y(), 'g', 10 );
-        mResults->addDerivedAttribute( featureNode, tr( "firstY" ), str );
+        derivedAttributes.insert( tr( "firstY" ), str );
         str = QLocale::system().toString( f_it->geometry()->asPolyline().last().x(), 'g', 10 );
-        mResults->addDerivedAttribute( featureNode, tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
+        derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
         str = QLocale::system().toString( f_it->geometry()->asPolyline().last().y(), 'g', 10 );
-        mResults->addDerivedAttribute( featureNode, tr( "lastY" ), str );
+        derivedAttributes.insert( tr( "lastY" ), str );
       }
     }
     else if ( layer->geometryType() == QGis::Polygon )
@@ -368,179 +253,91 @@
       QGis::UnitType myDisplayUnits;
       convertMeasurement( calc, area, myDisplayUnits, true );  // area and myDisplayUnits are out params
       QString str = calc.textUnit( area, 3, myDisplayUnits, true );
-      mResults->addDerivedAttribute( featureNode, tr( "Area" ), str );
+      derivedAttributes.insert( tr( "Area" ), str );
     }
     else if ( layer->geometryType() == QGis::Point )
     {
       // Include the x and y coordinates of the point as a derived attribute
       QString str;
       str = QLocale::system().toString( f_it->geometry()->asPoint().x(), 'g', 10 );
-      mResults->addDerivedAttribute( featureNode, "X", str );
+      derivedAttributes.insert( "X", str );
       str = QLocale::system().toString( f_it->geometry()->asPoint().y(), 'g', 10 );
-      mResults->addDerivedAttribute( featureNode, "Y", str );
+      derivedAttributes.insert( "Y", str );
     }
 
-    // Add actions
-    QgsAttributeAction::aIter iter = actions.begin();
-    for ( register int i = 0; iter != actions.end(); ++iter, ++i )
-    {
-      mResults->addAction( featureNode, i, tr( "action" ), iter->name() );
-    }
+    mResults->addFeature( layer, fid, displayField, displayValue, attributes, derivedAttributes );
   }
 
   QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );
 
-  //also test the not commited features //todo: eliminate copy past code
-
-  if ( featureCount == 1 )
-  {
-    mResults->showAllAttributes();
-    highlightFeature( lastFeatureId );
-  }
-  else if ( featureCount == 0 )
-  {
-    mResults->setMessage( tr( "No features found" ), tr( "No features were found in the active layer at the point you clicked" ) );
-  }
-
-  mResults->setTitle( tr( "%1 - %n feature(s) found", "Identify results window title", featureCount ).arg( layer->name() ) );
-
   QApplication::restoreOverrideCursor();
 
-  mResults->show();
+  return featureCount > 0;
 }
 
-void QgsMapToolIdentify::showError()
+bool QgsMapToolIdentify::identifyRasterLayer( QgsRasterLayer *layer, int x, int y )
 {
-#if 0
-  QMessageBox::warning(
-    this,
-    mapLayer->lastErrorTitle(),
-    tr( "Could not draw %1 because:\n%2", "COMMENTED OUT" ).arg( mapLayer->name() ).arg( mapLayer->lastError() )
-  );
-#endif
+  bool res = true;
 
-  QgsMessageViewer * mv = new QgsMessageViewer();
-
-  if ( mLayer )
-  {
-    mv->setWindowTitle( mLayer->lastErrorTitle() );
-    mv->setMessageAsPlainText( tr( "Could not identify objects on %1 because:\n%2" )
-                               .arg( mLayer->name() ).arg( mLayer->lastError() ) );
-  }
-  else
-  {
-    mv->setWindowTitle( tr( "Layer was removed" ) );
-    mv->setMessageAsPlainText( tr( "Layer to identify objects on was removed" ) );
-  }
-
-  mv->exec(); // deletes itself on close
-}
-
-void QgsMapToolIdentify::resultsDialogGone()
-{
-  mResults = 0;
-
-  delete mRubberBand;
-  mRubberBand = 0;
-}
-
-void QgsMapToolIdentify::deactivate()
-{
-  if ( mResults )
-    mResults->done( 0 ); // close the window
-  QgsMapTool::deactivate();
-}
-
-void QgsMapToolIdentify::highlightFeature( int featureId )
-{
-  QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mLayer );
   if ( !layer )
-    return;
+    return false;
 
-  delete mRubberBand;
-  mRubberBand = 0;
+  QgsRasterDataProvider *dprovider = layer->dataProvider();
+  if ( dprovider && ( dprovider->capabilities() & QgsRasterDataProvider::Identify ) == 0 )
+    return false;
 
-  QgsFeature feat;
-  if ( ! layer->featureAtId( featureId, feat, true, false ) )
-  {
-    return;
-  }
+  QMap< QString, QString > attributes, derivedAttributes;
+  QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );
+  QString type;
 
-  if ( !feat.geometry() )
+  if ( layer->providerKey() == "wms" )
   {
-    return;
-  }
+    type = tr( "WMS layer" );
 
-  mRubberBand = new QgsRubberBand( mCanvas, feat.geometry()->type() == QGis::Polygon );
+    //if WMS layer does not cover the view origin,
+    //we need to map the view pixel coordinates
+    //to WMS layer pixel coordinates
+    QgsRectangle viewExtent = mCanvas->extent();
+    QgsRectangle layerExtent = layer->extent();
+    double mapUnitsPerPixel = mCanvas->mapUnitsPerPixel();
+    if ( mapUnitsPerPixel > 0 && viewExtent.intersects( layerExtent ) )
+    {
+      double xMinView = viewExtent.xMinimum();
+      double yMaxView = viewExtent.yMaximum();
+      double xMinLayer = layerExtent.xMinimum();
+      double yMaxLayer = layerExtent.yMaximum();
 
-  if ( mRubberBand )
-  {
-    mRubberBand->setToGeometry( feat.geometry(), layer );
-    mRubberBand->setWidth( 2 );
-    mRubberBand->setColor( Qt::red );
-    mRubberBand->show();
-  }
-}
+      idPoint.set(
+        xMinView < xMinLayer ? floor( x - ( xMinLayer - xMinView ) / mapUnitsPerPixel ) : x,
+        yMaxView > yMaxLayer ? floor( y - ( yMaxView - yMaxLayer ) / mapUnitsPerPixel ) : y
+      );
 
-void QgsMapToolIdentify::editFeature( int featureId )
-{
-  for ( QgsFeatureList::iterator it = mFeatureList.begin(); it != mFeatureList.end(); it++ )
-  {
-    if ( it->id() == featureId )
+      attributes.insert( tr( "Feature info" ), layer->identifyAsText( idPoint ) );
+    }
+    else
     {
-      editFeature( *it );
-      break;
+      res = false;
     }
   }
-}
-
-void QgsMapToolIdentify::editFeature( QgsFeature &f )
-{
-  QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( mLayer );
-  if ( !layer || !layer->isEditable() )
+  else
   {
-    return;
+    type = tr( "Raster" );
+    res = layer->extent().contains( idPoint ) && layer->identify( idPoint, attributes );
   }
 
-  QgsAttributeMap src = f.attributeMap();
-
-  layer->beginEditCommand( tr( "Attribute changed" ) );
-  QgsAttributeDialog *ad = new QgsAttributeDialog( layer, &f );
-  if ( ad->exec() )
+  if ( res )
   {
-    const QgsAttributeMap &dst = f.attributeMap();
-    for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
-    {
-      if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
-      {
-        layer->changeAttributeValue( f.id(), it.key(), it.value() );
-      }
-    }
-    layer->endEditCommand();
+    derivedAttributes.insert( tr( "(clicked coordinate)" ), idPoint.toString() );
+    mResults->addFeature( layer, -1, type, "", attributes, derivedAttributes );
   }
-  else
-  {
-    layer->destroyEditCommand();
-  }
 
-  delete ad;
-  mCanvas->refresh();
+  return res;
 }
 
-void QgsMapToolIdentify::layerDestroyed()
-{
-  mLayer = 0;
 
-  if ( mResults )
-  {
-    mResults->clear();
-  }
-
-  if ( mRubberBand )
-  {
-    delete mRubberBand;
-    mRubberBand = 0;
-  }
+void QgsMapToolIdentify::resultsDialogGone()
+{
+  mResults = 0;
 }
 
 void QgsMapToolIdentify::convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea )

Modified: trunk/qgis/src/app/qgsmaptoolidentify.h
===================================================================
--- trunk/qgis/src/app/qgsmaptoolidentify.h	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsmaptoolidentify.h	2009-09-05 19:49:47 UTC (rev 11572)
@@ -57,68 +57,27 @@
     //! Overridden mouse release event
     virtual void canvasReleaseEvent( QMouseEvent * e );
 
-    //! called when map tool is being deactivated
-    virtual void deactivate();
-
-  public slots:
-    //! creates rubberband on top of the feature to highlight it
-    void highlightFeature( int featureId );
-
-    //! edit a feature
-    void editFeature( int featureId );
-
   private:
+    bool identifyLayer( QgsMapLayer *layer, int x, int y );
+    bool identifyRasterLayer( QgsRasterLayer *layer, int x, int y );
+    bool identifyVectorLayer( QgsVectorLayer *layer, int x, int y );
 
-    /**
-     * \brief function for identifying pixel values at a coordinate in a non-OGC-WMS raster layer
-     *
-     * \param point[in]  The coordinate (as the CRS of the raster layer)
-     */
-    void identifyRasterLayer( const QgsPoint& point );
-
-    /**
-     * \brief function for identifying a pixel in a OGC WMS raster layer
-     *
-     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
-     *
-     * \note WMS Servers prefer to receive coordinates in image space not CRS space, therefore
-     *       this special variant of identifyRasterLayer.
-     */
-    void identifyRasterWmsLayer( const QgsPoint& point );
-
-    /**
-     * \brief function for identifying features at a coordinate in a vector layer
-     *
-     * \param point[in]  The coordinate (as the CRS of the vector layer)
-     */
-    void identifyVectorLayer( const QgsPoint& point );
-
-    //! show whatever error is exposed by the QgsMapLayer.
-    void showError();
-
-    //! edit a feature
-    void editFeature( QgsFeature &f );
-
     //! Pointer to the identify results dialog for name/value pairs
     QgsIdentifyResults *mResults;
 
-    //! Rubber band for highlighting identified feature
-    QgsRubberBand* mRubberBand;
-
-    QgsMapLayer *mLayer;
-
-    //! list of identified features
-    QgsFeatureList mFeatureList;
-
     //! Private helper
     void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea );
 
+    void addFeature( QgsMapLayer *layer, int fid,
+                     QString displayField, QString displayValue,
+                     const QMap< QString, QString > &attributes,
+                     const QMap< QString, QString > &derivedAttributes );
+
+    /** Add an action to the feature display node */
+
   private slots:
     // Let us know when the QgsIdentifyResults dialog box has been closed
     void resultsDialogGone();
-
-    // layer was destroyed
-    void layerDestroyed();
 };
 
 #endif

Modified: trunk/qgis/src/app/qgsoptions.cpp
===================================================================
--- trunk/qgis/src/app/qgsoptions.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsoptions.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -50,9 +50,14 @@
   connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
   connect( this, SIGNAL( accepted() ), this, SLOT( saveOptions() ) );
 
+  cmbIdentifyMode->addItem( tr( "current layer" ), 0 );
+  cmbIdentifyMode->addItem( tr( "top down, stop at first" ), 1 );
+  cmbIdentifyMode->addItem( tr( "top down" ), 2 );
+
   // read the current browser and set it
   QSettings settings;
-  QgsDebugMsg( QString( "Standard Identify radius setting: %1" ).arg( QGis::DEFAULT_IDENTIFY_RADIUS ) );
+  int identifyMode = settings.value( "/Map/identifyMode", 0 ).toInt();
+  cmbIdentifyMode->setCurrentIndex( cmbIdentifyMode->findData( identifyMode ) );
   double identifyValue = settings.value( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble();
   QgsDebugMsg( QString( "Standard Identify radius setting read from settings file: %1" ).arg( identifyValue ) );
   spinBoxIdentifyValue->setValue( identifyValue );
@@ -349,6 +354,7 @@
   settings.setValue( "proxy/proxyExcludedUrls", proxyExcludeString );
 
   //general settings
+  settings.setValue( "/Map/identifyMode", cmbIdentifyMode->itemData( cmbIdentifyMode->currentIndex() ).toInt() );
   settings.setValue( "/Map/identifyRadius", spinBoxIdentifyValue->value() );
   settings.setValue( "/qgis/showLegendClassifiers", cbxLegendClassifiers->isChecked() );
   settings.setValue( "/qgis/hideSplash", cbxHideSplash->isChecked() );

Modified: trunk/qgis/src/app/qgsprojectproperties.cpp
===================================================================
--- trunk/qgis/src/app/qgsprojectproperties.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/app/qgsprojectproperties.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -30,6 +30,7 @@
 #include "qgsproject.h"
 #include "qgsrenderer.h"
 #include "qgssnappingdialog.h"
+#include "qgsrasterlayer.h"
 
 //qt includes
 #include <QColorDialog>
@@ -205,6 +206,56 @@
       mSnappingLayerSettings.insert( *idIter, newEntry );
     }
   }
+
+  QStringList noIdentifyLayerIdList = QgsProject::instance()->readListEntry( "Identify", "/disabledLayers" );
+
+  const QMap<QString, QgsMapLayer*> &mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
+
+  twIdentifyLayers->setColumnCount( 3 );
+  twIdentifyLayers->horizontalHeader()->setVisible( true );
+  twIdentifyLayers->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Layer" ) ) );
+  twIdentifyLayers->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Type" ) ) );
+  twIdentifyLayers->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Identifiable" ) ) );
+  twIdentifyLayers->setRowCount( mapLayers.size() );
+  twIdentifyLayers->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents );
+
+  int i = 0;
+  for ( QMap<QString, QgsMapLayer*>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); it++, i++ )
+  {
+    currentLayer = it.value();
+
+    QTableWidgetItem *twi = new QTableWidgetItem( QString::number( i ) );
+    twi->setData( Qt::UserRole, it.key() );
+    twIdentifyLayers->setVerticalHeaderItem( i, twi );
+
+    twIdentifyLayers->setItem( i, 0, new QTableWidgetItem( currentLayer->name() ) );
+
+    QString type;
+    if ( currentLayer->type() == QgsMapLayer::VectorLayer )
+    {
+      type = tr( "Vector" );
+    }
+    else if ( currentLayer->type() == QgsMapLayer::RasterLayer )
+    {
+      QgsRasterLayer *rl = dynamic_cast<QgsRasterLayer *>( currentLayer );
+
+      if ( rl && rl->providerKey() == "wms" )
+      {
+        type = tr( "WMS" );
+      }
+      else
+      {
+        type = tr( "Raster" );
+      }
+    }
+
+    twIdentifyLayers->setItem( i, 1, new QTableWidgetItem( type ) );
+
+    QCheckBox *cb = new QCheckBox();
+    cb->setChecked( !noIdentifyLayerIdList.contains( currentLayer->getLayerID() ) );
+    twIdentifyLayers->setCellWidget( i, 2, cb );
+  }
+
   restoreState();
 }
 
@@ -387,6 +438,19 @@
     QgsProject::instance()->writeEntry( "Digitizing", "/LayerSnappingEnabledList", enabledList );
   }
 
+  QStringList noIdentifyLayerList;
+  for ( int i = 0; i < twIdentifyLayers->rowCount(); i++ )
+  {
+    QCheckBox *cb = dynamic_cast<QCheckBox*>( twIdentifyLayers->cellWidget( i, 2 ) );
+    if ( cb && !cb->isChecked() )
+    {
+      QString id = twIdentifyLayers->verticalHeaderItem( i )->data( Qt::UserRole ).toString();
+      noIdentifyLayerList << id;
+    }
+  }
+
+  QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", noIdentifyLayerList );
+
   //todo XXX set canvas colour
   emit refresh();
 }

Modified: trunk/qgis/src/core/qgsrectangle.cpp
===================================================================
--- trunk/qgis/src/core/qgsrectangle.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/core/qgsrectangle.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -161,6 +161,11 @@
   return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
 }
 
+bool QgsRectangle::contains( const QgsPoint &p ) const
+{
+  return xmin <= p.x() && p.x() <= xmax &&
+         ymin <= p.y() && p.y() <= ymax;
+}
 
 void QgsRectangle::combineExtentWith( QgsRectangle * rect )
 {

Modified: trunk/qgis/src/core/qgsrectangle.h
===================================================================
--- trunk/qgis/src/core/qgsrectangle.h	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/core/qgsrectangle.h	2009-09-05 19:49:47 UTC (rev 11572)
@@ -87,6 +87,9 @@
     //! return true when rectangle contains other rectangle
     //! @note added in version 1.1
     bool contains( const QgsRectangle& rect ) const;
+    //! return true when rectangle contains a point
+    //! @note added in version 1.3
+    bool contains( const QgsPoint &p ) const;
     //! expand the rectangle so that covers both the original rectangle and the given rectangle
     void combineExtentWith( QgsRectangle *rect );
     //! expand the rectangle so that covers both the original rectangle and the given point

Modified: trunk/qgis/src/core/raster/qgsrasterlayer.cpp
===================================================================
--- trunk/qgis/src/core/raster/qgsrasterlayer.cpp	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/core/raster/qgsrasterlayer.cpp	2009-09-05 19:49:47 UTC (rev 11572)
@@ -1507,7 +1507,7 @@
   {
     QgsDebugMsg( "Wanting a '" + mProviderKey + "' provider to draw this." );
 
-    emit statusChanged( tr( "Retrieving using %1" ).arg( mProviderKey ) );
+    emit statusChanged( tr( "Retrieving %1 using %2" ).arg( name() ).arg( mProviderKey ) );
 
     mDataProvider->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() );
 
@@ -1594,6 +1594,7 @@
       delete image;
     }
 
+    emit statusChanged( tr( "%1 retrieved using %2" ).arg( name() ).arg( mProviderKey ) );
   }
   else
   {
@@ -1846,12 +1847,9 @@
     return false;
   }
 
-  double x = thePoint.x();
-  double y = thePoint.y();
+  QgsDebugMsg( thePoint.toString() );
 
-  QgsDebugMsg( QString::number( x ) + ", " + QString::number( y ) );
-
-  if ( x < mLayerExtent.xMinimum() || x > mLayerExtent.xMaximum() || y < mLayerExtent.yMinimum() || y > mLayerExtent.yMaximum() )
+  if ( !mLayerExtent.contains( thePoint ) )
   {
     // Outside the raster
     for ( int i = 1; i <= GDALGetRasterCount( mGdalDataset ); i++ )
@@ -1861,6 +1859,9 @@
   }
   else
   {
+    double x = thePoint.x();
+    double y = thePoint.y();
+
     /* Calculate the row / column where the point falls */
     double xres = ( mLayerExtent.xMaximum() - mLayerExtent.xMinimum() ) / mWidth;
     double yres = ( mLayerExtent.yMaximum() - mLayerExtent.yMinimum() ) / mHeight;

Modified: trunk/qgis/src/ui/qgsoptionsbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsoptionsbase.ui	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/ui/qgsoptionsbase.ui	2009-09-05 19:49:47 UTC (rev 11572)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>617</width>
-    <height>521</height>
+    <width>654</width>
+    <height>546</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -503,13 +503,13 @@
        <item row="0" column="0">
         <widget class="QGroupBox" name="groupBox_7">
          <property name="title">
-          <string>Search radius</string>
+          <string>Identify</string>
          </property>
          <layout class="QGridLayout">
           <property name="margin">
            <number>11</number>
           </property>
-          <item row="1" column="0" colspan="2">
+          <item row="2" column="0" colspan="2">
            <widget class="QLabel" name="textLabel2">
             <property name="text">
              <string>&lt;b&gt;Note:&lt;/b&gt; Specify the search radius as a percentage of the map width</string>
@@ -519,7 +519,7 @@
             </property>
            </widget>
           </item>
-          <item row="0" column="0">
+          <item row="1" column="0">
            <widget class="QLabel" name="textLabel1_3">
             <property name="text">
              <string>Search radius for identifying features and displaying map tips</string>
@@ -529,7 +529,7 @@
             </property>
            </widget>
           </item>
-          <item row="0" column="1">
+          <item row="1" column="1">
            <widget class="QDoubleSpinBox" name="spinBoxIdentifyValue">
             <property name="suffix">
              <string>%</string>
@@ -545,6 +545,16 @@
             </property>
            </widget>
           </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="cmbIdentifyMode"/>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_4">
+            <property name="text">
+             <string>Mode</string>
+            </property>
+           </widget>
+          </item>
          </layout>
         </widget>
        </item>

Modified: trunk/qgis/src/ui/qgsprojectpropertiesbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsprojectpropertiesbase.ui	2009-09-05 19:49:10 UTC (rev 11571)
+++ trunk/qgis/src/ui/qgsprojectpropertiesbase.ui	2009-09-05 19:49:47 UTC (rev 11572)
@@ -1,81 +1,87 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>QgsProjectPropertiesBase</class>
- <widget class="QDialog" name="QgsProjectPropertiesBase" >
-  <property name="geometry" >
+ <widget class="QDialog" name="QgsProjectPropertiesBase">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>536</width>
-    <height>713</height>
+    <width>451</width>
+    <height>515</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Project Properties</string>
   </property>
-  <property name="windowIcon" >
-   <iconset>
-    <normaloff/> 
-   </iconset>
-  </property>
-  <property name="sizeGripEnabled" >
+  <property name="sizeGripEnabled">
    <bool>true</bool>
   </property>
-  <property name="modal" >
+  <property name="modal">
    <bool>true</bool>
   </property>
-  <layout class="QGridLayout" >
-   <item row="0" column="0" >
-    <widget class="QTabWidget" name="tabWidget" >
-     <property name="currentIndex" >
+  <layout class="QGridLayout">
+   <item row="2" column="0">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
       <number>0</number>
      </property>
-     <widget class="QWidget" name="tab1" >
-      <attribute name="title" >
+     <widget class="QWidget" name="tab1">
+      <attribute name="title">
        <string>General</string>
       </attribute>
-      <layout class="QGridLayout" >
-       <item row="0" column="0" >
-        <widget class="QGroupBox" name="titleBox" >
-         <property name="title" >
-          <string>Title and colors</string>
+      <layout class="QGridLayout">
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="titleBox">
+         <property name="title">
+          <string>General settings</string>
          </property>
-         <layout class="QGridLayout" >
-          <item row="0" column="0" >
-           <widget class="QLabel" name="label_2" >
-            <property name="text" >
+         <layout class="QGridLayout">
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_2">
+            <property name="text">
              <string>Project title</string>
             </property>
            </widget>
           </item>
-          <item row="0" column="1" colspan="3" >
-           <widget class="QLineEdit" name="titleEdit" >
-            <property name="toolTip" >
+          <item row="0" column="1" colspan="3">
+           <widget class="QLineEdit" name="titleEdit">
+            <property name="toolTip">
              <string>Descriptive project name</string>
             </property>
-            <property name="text" >
+            <property name="text">
              <string>Default project title</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="0" >
-           <widget class="QLabel" name="textLabel1" >
-            <property name="text" >
+          <item row="1" column="0">
+           <widget class="QLabel" name="textLabel1">
+            <property name="text">
              <string>Selection color</string>
             </property>
-            <property name="buddy" >
+            <property name="buddy">
              <cstring>pbnSelectionColour</cstring>
             </property>
            </widget>
           </item>
-          <item row="1" column="2" >
+          <item row="1" column="2">
            <spacer>
-            <property name="orientation" >
+            <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
-            <property name="sizeType" >
+            <property name="sizeType">
              <enum>QSizePolicy::Expanding</enum>
             </property>
-            <property name="sizeHint" >
+            <property name="sizeHint" stdset="0">
              <size>
               <width>40</width>
               <height>20</height>
@@ -83,35 +89,35 @@
             </property>
            </spacer>
           </item>
-          <item row="1" column="3" >
-           <widget class="QgsColorButton" name="pbnSelectionColour" >
-            <property name="minimumSize" >
+          <item row="1" column="3">
+           <widget class="QgsColorButton" name="pbnSelectionColour">
+            <property name="minimumSize">
              <size>
               <width>100</width>
               <height>0</height>
              </size>
             </property>
-            <property name="text" >
+            <property name="text">
              <string/>
             </property>
            </widget>
           </item>
-          <item row="2" column="0" colspan="2" >
-           <widget class="QLabel" name="label" >
-            <property name="text" >
+          <item row="2" column="0" colspan="2">
+           <widget class="QLabel" name="label">
+            <property name="text">
              <string>Background color</string>
             </property>
-            <property name="buddy" >
+            <property name="buddy">
              <cstring>pbnCanvasColor</cstring>
             </property>
            </widget>
           </item>
-          <item row="2" column="2" >
+          <item row="2" column="2">
            <spacer>
-            <property name="orientation" >
+            <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
-            <property name="sizeHint" >
+            <property name="sizeHint" stdset="0">
              <size>
               <width>40</width>
               <height>20</height>
@@ -119,60 +125,58 @@
             </property>
            </spacer>
           </item>
-          <item row="2" column="3" >
-           <widget class="QgsColorButton" name="pbnCanvasColor" >
-            <property name="minimumSize" >
+          <item row="2" column="3">
+           <widget class="QgsColorButton" name="pbnCanvasColor">
+            <property name="minimumSize">
              <size>
               <width>100</width>
               <height>0</height>
              </size>
             </property>
-            <property name="text" >
+            <property name="text">
              <string/>
             </property>
            </widget>
           </item>
+          <item row="3" column="0" colspan="4">
+           <widget class="QCheckBox" name="cbxAbsolutePath">
+            <property name="text">
+             <string>Save absolute paths</string>
+            </property>
+           </widget>
+          </item>
          </layout>
         </widget>
        </item>
-       <item row="1" column="0" >
-        <widget class="QGroupBox" name="btnGrpMapUnits" >
-         <property name="title" >
+       <item row="1" column="0">
+        <widget class="QGroupBox" name="btnGrpMapUnits">
+         <property name="title">
           <string>Layer units (only used when CRS transformation is disabled)</string>
          </property>
-         <layout class="QHBoxLayout" >
-          <property name="leftMargin" >
+         <layout class="QHBoxLayout">
+          <property name="margin">
            <number>11</number>
           </property>
-          <property name="topMargin" >
-           <number>11</number>
-          </property>
-          <property name="rightMargin" >
-           <number>11</number>
-          </property>
-          <property name="bottomMargin" >
-           <number>11</number>
-          </property>
           <item>
-           <widget class="QRadioButton" name="radMeters" >
-            <property name="text" >
+           <widget class="QRadioButton" name="radMeters">
+            <property name="text">
              <string>Meters</string>
             </property>
-            <property name="checked" >
+            <property name="checked">
              <bool>true</bool>
             </property>
            </widget>
           </item>
           <item>
-           <widget class="QRadioButton" name="radFeet" >
-            <property name="text" >
+           <widget class="QRadioButton" name="radFeet">
+            <property name="text">
              <string>Feet</string>
             </property>
            </widget>
           </item>
           <item>
-           <widget class="QRadioButton" name="radDecimalDegrees" >
-            <property name="text" >
+           <widget class="QRadioButton" name="radDecimalDegrees">
+            <property name="text">
              <string>Decimal degrees</string>
             </property>
            </widget>
@@ -180,60 +184,60 @@
          </layout>
         </widget>
        </item>
-       <item row="2" column="0" >
-        <widget class="QGroupBox" name="btnGrpPrecision" >
-         <property name="title" >
+       <item row="2" column="0">
+        <widget class="QGroupBox" name="btnGrpPrecision">
+         <property name="title">
           <string>Precision</string>
          </property>
-         <layout class="QGridLayout" >
-          <item row="0" column="0" >
-           <widget class="QRadioButton" name="radAutomatic" >
-            <property name="toolTip" >
+         <layout class="QGridLayout">
+          <item row="0" column="0">
+           <widget class="QRadioButton" name="radAutomatic">
+            <property name="toolTip">
              <string>Automatically sets the number of decimal places in the mouse position display</string>
             </property>
-            <property name="whatsThis" >
+            <property name="whatsThis">
              <string>The number of decimal places that are used when displaying the mouse position is automatically set to be enough so that moving the mouse by one pixel gives a change in the position display</string>
             </property>
-            <property name="text" >
+            <property name="text">
              <string>Automatic</string>
             </property>
-            <property name="checked" >
+            <property name="checked">
              <bool>true</bool>
             </property>
            </widget>
           </item>
-          <item row="0" column="1" >
-           <widget class="QRadioButton" name="radManual" >
-            <property name="toolTip" >
+          <item row="0" column="1">
+           <widget class="QRadioButton" name="radManual">
+            <property name="toolTip">
              <string>Sets the number of decimal places to use for the mouse position display</string>
             </property>
-            <property name="whatsThis" >
+            <property name="whatsThis">
              <string>Sets the number of decimal places to use for the mouse position display</string>
             </property>
-            <property name="text" >
+            <property name="text">
              <string>Manual</string>
             </property>
            </widget>
           </item>
-          <item row="0" column="2" >
-           <widget class="QSpinBox" name="spinBoxDP" >
-            <property name="toolTip" >
+          <item row="0" column="2">
+           <widget class="QSpinBox" name="spinBoxDP">
+            <property name="toolTip">
              <string>The number of decimal places for the manual option</string>
             </property>
-            <property name="whatsThis" >
+            <property name="whatsThis">
              <string>The number of decimal places for the manual option</string>
             </property>
            </widget>
           </item>
-          <item row="0" column="3" >
-           <widget class="QLabel" name="textLabel3" >
-            <property name="sizePolicy" >
-             <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+          <item row="0" column="3">
+           <widget class="QLabel" name="textLabel3">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
               <horstretch>0</horstretch>
               <verstretch>0</verstretch>
              </sizepolicy>
             </property>
-            <property name="text" >
+            <property name="text">
              <string>decimal places</string>
             </property>
            </widget>
@@ -241,35 +245,35 @@
          </layout>
         </widget>
        </item>
-       <item row="3" column="0" >
-        <widget class="QGroupBox" name="grpDigitizing" >
-         <property name="sizePolicy" >
-          <sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
+       <item row="3" column="0">
+        <widget class="QGroupBox" name="grpDigitizing">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
-         <property name="title" >
+         <property name="title">
           <string>Digitizing</string>
          </property>
-         <layout class="QGridLayout" >
-          <item row="0" column="0" >
-           <widget class="QCheckBox" name="mEnableTopologicalEditingCheckBox" >
-            <property name="text" >
+         <layout class="QGridLayout">
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="mEnableTopologicalEditingCheckBox">
+            <property name="text">
              <string>Enable topological editing</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="0" >
-           <widget class="QCheckBox" name="mAvoidIntersectionsCheckBox" >
-            <property name="text" >
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="mAvoidIntersectionsCheckBox">
+            <property name="text">
              <string>Avoid intersections of new polygons</string>
             </property>
            </widget>
           </item>
-          <item row="2" column="0" >
-           <widget class="QPushButton" name="mSnappingOptionsPushButton" >
-            <property name="text" >
+          <item row="2" column="0">
+           <widget class="QPushButton" name="mSnappingOptionsPushButton">
+            <property name="text">
              <string>Snapping options...</string>
             </property>
            </widget>
@@ -277,59 +281,86 @@
          </layout>
         </widget>
        </item>
-       <item row="4" column="0" >
-        <widget class="QCheckBox" name="cbxAbsolutePath" >
-         <property name="text" >
-          <string>Save absolute paths</string>
-         </property>
-        </widget>
-       </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="tab2" >
-      <attribute name="title" >
+     <widget class="QWidget" name="tab2">
+      <attribute name="title">
        <string>Coordinate Reference System (CRS)</string>
       </attribute>
-      <layout class="QGridLayout" >
-       <property name="leftMargin" >
+      <layout class="QGridLayout">
+       <property name="leftMargin">
         <number>3</number>
        </property>
-       <property name="topMargin" >
+       <property name="topMargin">
         <number>11</number>
        </property>
-       <property name="rightMargin" >
+       <property name="rightMargin">
         <number>3</number>
        </property>
-       <property name="bottomMargin" >
+       <property name="bottomMargin">
         <number>11</number>
        </property>
-       <item row="0" column="0" >
-        <widget class="QCheckBox" name="cbxProjectionEnabled" >
-         <property name="text" >
+       <item row="0" column="0">
+        <widget class="QCheckBox" name="cbxProjectionEnabled">
+         <property name="text">
           <string>Enable 'on the fly' CRS transformation</string>
          </property>
         </widget>
        </item>
-       <item row="1" column="0" >
-        <widget class="QgsProjectionSelector" native="1" name="projectionSelector" />
+       <item row="1" column="0">
+        <widget class="QgsProjectionSelector" name="projectionSelector" native="true"/>
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab3">
+      <attribute name="title">
+       <string>Identifiable layers</string>
+      </attribute>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QTableWidget" name="twIdentifyLayers">
+         <property name="sortingEnabled">
+          <bool>true</bool>
+         </property>
+         <attribute name="horizontalHeaderVisible">
+          <bool>false</bool>
+         </attribute>
+         <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+          <bool>false</bool>
+         </attribute>
+         <attribute name="horizontalHeaderStretchLastSection">
+          <bool>true</bool>
+         </attribute>
+         <attribute name="horizontalHeaderVisible">
+          <bool>false</bool>
+         </attribute>
+         <column>
+          <property name="text">
+           <string>Layer</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Type</string>
+          </property>
+         </column>
+         <column>
+          <property name="text">
+           <string>Identifiable</string>
+          </property>
+          <property name="textAlignment">
+           <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+          </property>
+         </column>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
-   <item row="2" column="0" >
-    <widget class="QDialogButtonBox" name="buttonBox" >
-     <property name="orientation" >
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons" >
-      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
   </layout>
  </widget>
- <layoutdefault spacing="6" margin="11" />
+ <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
   <customwidget>
    <class>QgsColorButton</class>
@@ -368,11 +399,11 @@
    <receiver>spinBoxDP</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>229</x>
      <y>280</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>416</x>
      <y>286</y>
     </hint>
@@ -384,11 +415,11 @@
    <receiver>textLabel3</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>240</x>
      <y>281</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>583</x>
      <y>290</y>
     </hint>
@@ -400,11 +431,11 @@
    <receiver>spinBoxDP</receiver>
    <slot>setDisabled(bool)</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>100</x>
      <y>290</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>395</x>
      <y>285</y>
     </hint>
@@ -416,11 +447,11 @@
    <receiver>textLabel3</receiver>
    <slot>setDisabled(bool)</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>87</x>
      <y>284</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>589</x>
      <y>285</y>
     </hint>



More information about the QGIS-commit mailing list