Skip to content

Commit

Permalink
enabled identify results context menu for rasters, zoom to feature, c…
Browse files Browse the repository at this point in the history
…opy feature, copy GetFeatureInfo url
  • Loading branch information
blazek committed Mar 8, 2013
1 parent 31d7f65 commit 0dafb99
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 34 deletions.
129 changes: 99 additions & 30 deletions src/app/qgsidentifyresultsdialog.cpp
Expand Up @@ -304,7 +304,7 @@ void QgsIdentifyResultsDialog::addFeature( QgsMapToolIdentify::IdentifyResult re
}
else if ( result.mLayer->type() == QgsMapLayer::RasterLayer )
{
addFeature( qobject_cast<QgsRasterLayer *>( result.mLayer ), result.mLabel, result.mAttributes, result.mDerivedAttributes, result.mFields, result.mFeature );
addFeature( qobject_cast<QgsRasterLayer *>( result.mLayer ), result.mLabel, result.mAttributes, result.mDerivedAttributes, result.mFields, result.mFeature, result.mParams );
}
}

Expand Down Expand Up @@ -425,7 +425,8 @@ void QgsIdentifyResultsDialog::addFeature( QgsRasterLayer *layer,
const QMap<QString, QString> &attributes,
const QMap<QString, QString> &derivedAttributes,
const QgsFields &fields,
const QgsFeature &feature )
const QgsFeature &feature,
const QMap<QString, QVariant> &params )
{
QgsDebugMsg( QString( "feature.isValid() = %1" ).arg( feature.isValid() ) );
QTreeWidgetItem *layItem = layerItem( layer );
Expand All @@ -436,6 +437,8 @@ void QgsIdentifyResultsDialog::addFeature( QgsRasterLayer *layer,
{
layItem = new QTreeWidgetItem( QStringList() << QString::number( lstResults->topLevelItemCount() ) << layer->name() );
layItem->setData( 0, Qt::UserRole, QVariant::fromValue( qobject_cast<QObject *>( layer ) ) );

layItem->setData( 0, GetFeatureInfoUrlRole, params.value( "getFeatureInfoUrl" ) );
lstResults->addTopLevelItem( layItem );

QComboBox *formatCombo = new QComboBox();
Expand Down Expand Up @@ -647,39 +650,66 @@ void QgsIdentifyResultsDialog::itemClicked( QTreeWidgetItem *item, int column )

void QgsIdentifyResultsDialog::contextMenuEvent( QContextMenuEvent* event )
{
QgsDebugMsg( "Entered" );
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 )
return;

QgsVectorLayer *vlayer = vectorLayer( item );
if ( vlayer == 0 )
QgsRasterLayer *rlayer = rasterLayer( item );
if ( vlayer == 0 && rlayer == 0 )
{
QgsDebugMsg( "Item does not belong to a layer." );
return;
}

if ( mActionPopup )
delete mActionPopup;

mActionPopup = new QMenu();

int idx = -1;
QTreeWidgetItem *featItem = featureItem( item );
//QTreeWidgetItem *featItem = featureItem( item );
QgsIdentifyResultsFeatureItem *featItem = dynamic_cast<QgsIdentifyResultsFeatureItem *>( featureItem( item ) );
if ( featItem )
{
mActionPopup->addAction(
QgsApplication::getThemeIcon( vlayer->isEditable() ? "/mIconEditable.png" : "/mIconEditable.png" ),
vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ),
this, SLOT( featureForm() ) );
mActionPopup->addAction( tr( "Zoom to feature" ), this, SLOT( zoomToFeature() ) );
if ( vlayer )
{
mActionPopup->addAction(
QgsApplication::getThemeIcon( vlayer->isEditable() ? "/mIconEditable.png" : "/mIconEditable.png" ),
vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ),
this, SLOT( featureForm() ) );
}

if ( featItem->feature().isValid() )
{
mActionPopup->addAction( tr( "Zoom to feature" ), this, SLOT( zoomToFeature() ) );
mActionPopup->addAction( tr( "Copy feature" ), this, SLOT( copyFeature() ) );
}

mActionPopup->addAction( tr( "Copy attribute value" ), this, SLOT( copyAttributeValue() ) );
mActionPopup->addAction( tr( "Copy feature attributes" ), this, SLOT( copyFeatureAttributes() ) );
mActionPopup->addSeparator();

if ( item->parent() == featItem && item->childCount() == 0 )
{
idx = item->data( 0, Qt::UserRole + 1 ).toInt();
}
}

if ( rlayer )
{
QTreeWidgetItem *layItem = layerItem( item );
if ( layItem && !layItem->data( 0, GetFeatureInfoUrlRole ).toString().isEmpty() )
{
mActionPopup->addAction( tr( "Copy GetFeatureInfo request URL" ), this, SLOT( copyGetFeatureInfoUrl() ) );
}
}
if ( mActionPopup->children().size() > 0 )
{
mActionPopup->addSeparator();
}

mActionPopup->addAction( tr( "Clear results" ), this, SLOT( clear() ) );
mActionPopup->addAction( tr( "Clear highlights" ), this, SLOT( clearHighlights() ) );
mActionPopup->addAction( tr( "Highlight all" ), this, SLOT( highlightAll() ) );
Expand All @@ -690,7 +720,7 @@ void QgsIdentifyResultsDialog::contextMenuEvent( QContextMenuEvent* event )
mActionPopup->addAction( tr( "Collapse all" ), this, SLOT( collapseAll() ) );
mActionPopup->addSeparator();

if ( featItem && vlayer->actions()->size() > 0 )
if ( featItem && vlayer && vlayer->actions()->size() > 0 )
{
mActionPopup->addSeparator();

Expand Down Expand Up @@ -1104,27 +1134,29 @@ void QgsIdentifyResultsDialog::zoomToFeature()
{
QTreeWidgetItem *item = lstResults->currentItem();

QgsVectorLayer *layer = vectorLayer( item );
if ( !layer )
return;

QTreeWidgetItem *featItem = featureItem( item );
if ( !featItem )
QgsMapLayer *layer;
QgsVectorLayer *vlayer = vectorLayer( item );
QgsRasterLayer *rlayer = rasterLayer( item );
if ( !vlayer && !rlayer )
{
return;
}

int fid = STRING_TO_FID( featItem->data( 0, Qt::UserRole ) );
layer = vlayer ? ( QgsMapLayer * )vlayer : ( QgsMapLayer * )rlayer;

QgsFeature feat;
if ( ! layer->getFeatures( QgsFeatureRequest().setFilterFid( fid ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( feat ) )
QgsIdentifyResultsFeatureItem *featItem = dynamic_cast<QgsIdentifyResultsFeatureItem *>( featureItem( item ) );
if ( !featItem )
{
return;
}

QgsFeature feat = featItem->feature();
if ( !feat.geometry() )
{
return;
}

// TODO: verify CRS for raster WMS features
QgsRectangle rect = mCanvas->mapRenderer()->layerExtentToOutputExtent( layer, feat.geometry()->boundingBox() );

if ( rect.isEmpty() )
Expand Down Expand Up @@ -1237,32 +1269,59 @@ void QgsIdentifyResultsDialog::copyAttributeValue()

void QgsIdentifyResultsDialog::copyFeatureAttributes()
{
QgsDebugMsg( "Entered" );
QClipboard *clipboard = QApplication::clipboard();
QString text;

QgsVectorLayer *vlayer = vectorLayer( lstResults->currentItem() );
if ( !vlayer )
QgsRasterLayer *rlayer = rasterLayer( lstResults->currentItem() );
if ( !vlayer & !rlayer )
{
return;
}
if ( vlayer )
{
int idx;
QgsAttributeMap attributes;
retrieveAttributes( lstResults->currentItem(), attributes, idx );

int idx;
QgsAttributeMap attributes;
retrieveAttributes( lstResults->currentItem(), attributes, idx );
const QgsFields &fields = vlayer->pendingFields();

const QgsFields &fields = vlayer->pendingFields();
for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
{
int attrIdx = it.key();
if ( attrIdx < 0 || attrIdx >= fields.count() )
continue;

for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
text += QString( "%1: %2\n" ).arg( fields[attrIdx].name() ).arg( it.value().toString() );
}
}
else if ( rlayer )
{
int attrIdx = it.key();
if ( attrIdx < 0 || attrIdx >= fields.count() )
continue;
QTreeWidgetItem *featItem = featureItem( lstResults->currentItem() );
if ( !featItem ) return;

text += QString( "%1: %2\n" ).arg( fields[attrIdx].name() ).arg( it.value().toString() );
for ( int i = 0; i < featItem->childCount(); i++ )
{
QTreeWidgetItem *item = featItem->child( i );
if ( item->childCount() > 0 ) continue;
text += QString( "%1: %2\n" ).arg( item->data( 0, Qt::DisplayRole ).toString() ).arg( item->data( 1, Qt::DisplayRole ).toString() );
}
}

QgsDebugMsg( QString( "set clipboard: %1" ).arg( text ) );
clipboard->setText( text );
}

void QgsIdentifyResultsDialog::copyGetFeatureInfoUrl()
{
QClipboard *clipboard = QApplication::clipboard();
QTreeWidgetItem *item = lstResults->currentItem();
QTreeWidgetItem *layItem = layerItem( item );
if ( !layItem ) { return; }
clipboard->setText( layItem->data( 0, GetFeatureInfoUrlRole ).toString() );
}

void QgsIdentifyResultsDialog::openUrl( const QUrl &url )
{
if ( !QDesktopServices::openUrl( url ) )
Expand Down Expand Up @@ -1301,6 +1360,11 @@ void QgsIdentifyResultsDialog::on_mExpandNewToolButton_toggled( bool checked )
void QgsIdentifyResultsDialog::on_mCopyToolButton_clicked( bool checked )
{
Q_UNUSED( checked );
copyFeature();
}

void QgsIdentifyResultsDialog::copyFeature()
{
QgsDebugMsg( "Entered" );

QgsIdentifyResultsFeatureItem *item = dynamic_cast<QgsIdentifyResultsFeatureItem *>( featureItem( lstResults->selectedItems().value( 0 ) ) );
Expand Down Expand Up @@ -1338,6 +1402,11 @@ void QgsIdentifyResultsDialog::formatChanged( int index )

// remove all childs of that layer from results, except the first (format)
QTreeWidgetItem *layItem = layerItem(( QObject * )layer );
if ( !layItem )
{
QgsDebugMsg( "cannot get layer item" );
return;
}
for ( int i = layItem->childCount() - 1; i > 0; i-- )
{
layItem->removeChild( layItem->child( i ) );
Expand Down
9 changes: 8 additions & 1 deletion src/app/qgsidentifyresultsdialog.h
Expand Up @@ -112,7 +112,8 @@ class QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdentifyResultsBa
const QMap< QString, QString > &attributes,
const QMap< QString, QString > &derivedAttributes,
const QgsFields &fields = QgsFields(),
const QgsFeature &feature = QgsFeature() );
const QgsFeature &feature = QgsFeature(),
const QMap<QString, QVariant> &params = QMap<QString, QVariant>() );

/** Add feature from identify results */
void addFeature( QgsMapToolIdentify::IdentifyResult result );
Expand Down Expand Up @@ -150,7 +151,9 @@ class QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdentifyResultsBa
void featureForm();
void zoomToFeature();
void copyAttributeValue();
void copyFeature();
void copyFeatureAttributes();
void copyGetFeatureInfoUrl();
void highlightAll();
void highlightLayer();
void layerProperties();
Expand Down Expand Up @@ -184,6 +187,10 @@ class QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdentifyResultsBa
void printCurrentItem();

private:
enum ItemDataRole
{
GetFeatureInfoUrlRole = Qt::UserRole + 10
};

QMenu *mActionPopup;
QMap<QTreeWidgetItem *, QgsHighlight * > mHighlights;
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsmaptoolidentifyaction.cpp
Expand Up @@ -133,7 +133,7 @@ void QgsMapToolIdentifyAction::handleChangedRasterResults( QList<IdentifyResult>
{
if ( rresult->mLayer->type() == QgsMapLayer::RasterLayer )
{
resultsDialog()->addFeature( qobject_cast<QgsRasterLayer *>( rresult->mLayer ), rresult->mLabel, rresult->mAttributes, rresult->mDerivedAttributes, rresult->mFields, rresult->mFeature );
resultsDialog()->addFeature( *rresult );
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/gui/qgsmaptoolidentify.cpp
Expand Up @@ -487,12 +487,17 @@ bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, Qg
if ( featureType.compare( sublayer, Qt::CaseInsensitive ) != 0 || labels.isEmpty() )
{
labels << featureType;


}

QMap< QString, QString > derAttributes = derivedAttributes;
derAttributes.unite( featureDerivedAttributes( &feature, layer ) );

results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( " / " ), featureStore.fields(), feature, derAttributes ) );
IdentifyResult identifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( " / " ), featureStore.fields(), feature, derAttributes );

identifyResult.mParams.insert( "getFeatureInfoUrl", featureStore.params().value( "getFeatureInfoUrl" ) );
results->append( identifyResult );
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/qgsmaptoolidentify.h
Expand Up @@ -80,6 +80,7 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
QgsFeature mFeature;
QMap< QString, QString > mAttributes;
QMap< QString, QString > mDerivedAttributes;
QMap< QString, QVariant > mParams;
};

//! constructor
Expand Down
5 changes: 4 additions & 1 deletion src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -4197,12 +4197,15 @@ QMap<int, QVariant> QgsWmsProvider::identify( const QgsPoint & thePoint, Identif
#else
Q_UNUSED( ret );
#endif

// TODO: all features coming from this layer should probably have the same CRS
// the same as this layer, because layerExtentToOutputExtent() may be used
// for results -> verify CRS and reprojects if necessary
QMap<QgsFeatureId, QgsFeature* > features = gml.featuresMap();
QgsDebugMsg( QString( "%1 features read" ).arg( features.size() ) );
QgsFeatureStore featureStore( fields, crs() );
featureStore.params().insert( "sublayer", *layers );
featureStore.params().insert( "featureType", featureTypeName );
featureStore.params().insert( "getFeatureInfoUrl", requestUrl.toString() );
foreach ( QgsFeatureId id, features.keys() )
{
QgsFeature * feature = features.value( id );
Expand Down

0 comments on commit 0dafb99

Please sign in to comment.