diff --git a/python/gui/auto_generated/qgsmaptool.sip.in b/python/gui/auto_generated/qgsmaptool.sip.in index f11f37573a3..d088b40fa91 100644 --- a/python/gui/auto_generated/qgsmaptool.sip.in +++ b/python/gui/auto_generated/qgsmaptool.sip.in @@ -223,7 +223,7 @@ Any new actions added to the menu should be correctly parented to ``menu``. A pointer to the map mouse ``event`` can be provided to allow particular behavior depending on the map tool. -This method can return true to inform the caller that the menu was effectivly populated. +This method can return true to inform the caller that the menu was effectively populated. The default implementation does nothing and returns false. diff --git a/src/app/qgsmaptoolselect.cpp b/src/app/qgsmaptoolselect.cpp index ebbbb5eea9b..049e6f54a02 100644 --- a/src/app/qgsmaptoolselect.cpp +++ b/src/app/qgsmaptoolselect.cpp @@ -144,9 +144,13 @@ QgsMapTool::Flags QgsMapToolSelect::flags() const bool QgsMapToolSelect::populateContextMenuWithEvent( QMenu *menu, QgsMapMouseEvent *event ) { Q_ASSERT( menu ); - menu->addSeparator(); QgsVectorLayer *vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( mCanvas ); + if ( !vlayer ) + return false; + + menu->addSeparator(); + Qt::KeyboardModifiers modifiers = Qt::NoModifier; QgsPointXY mapPoint; if ( event ) diff --git a/src/app/qgsmaptoolselectutils.cpp b/src/app/qgsmaptoolselectutils.cpp index 64c1e774f93..e956e7d4a6a 100644 --- a/src/app/qgsmaptoolselectutils.cpp +++ b/src/app/qgsmaptoolselectutils.cpp @@ -483,7 +483,7 @@ void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::onSearchFinished() mAllFeatureIds = mFutureWatcher->result(); mActionChooseAll->setText( textForChooseAll( mAllFeatureIds.size() ) ); if ( !mAllFeatureIds.isEmpty() ) - connect( mActionChooseAll, &QAction::hovered, this, &QgsMapToolSelectMenuActions::highlightFeatures ); + connect( mActionChooseAll, &QAction::hovered, this, &QgsMapToolSelectMenuActions::highlightAllFeatures ); else mActionChooseAll->setEnabled( false ); if ( mAllFeatureIds.count() > 1 ) @@ -514,7 +514,7 @@ QString QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::textForChooseAll( qi QString featureCountText; if ( featureCount < 0 ) - featureCountText = QStringLiteral( "Searching..." ); + featureCountText = tr( "Searching…" ); else featureCountText = QString::number( featureCount ); @@ -561,41 +561,45 @@ QString QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::textForChooseOneMenu void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::populateChooseOneMenu( const QgsFeatureIds &ids ) { + if ( !mVectorLayer ) + return; + QgsFeatureIds displayedFeatureIds; QgsFeatureIds::ConstIterator it = ids.constBegin(); while ( displayedFeatureIds.count() <= 20 && it != ids.constEnd() ) //for now hardcoded, but maybe define a settings for this displayedFeatureIds.insert( *( it++ ) ); + QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) ); + QgsExpression exp = mVectorLayer->displayExpression(); + exp.prepare( &context ); + for ( QgsFeatureId id : qgis::as_const( displayedFeatureIds ) ) { - QAction *featureAction = new QAction( tr( "Feature %1" ).arg( id ), this ) ; - featureAction->setData( id ); - connect( featureAction, &QAction::triggered, this, &QgsMapToolSelectMenuActions::chooseOneCandidateFeature ); - connect( featureAction, &QAction::hovered, this, &QgsMapToolSelectMenuActions::highlightFeatures ); + QgsFeature feat = mVectorLayer->getFeature( id ); + context.setFeature( feat ); + + QString featureTitle = exp.evaluate( &context ).toString(); + if ( featureTitle.isEmpty() ) + featureTitle = FID_TO_STRING( feat.id() ); + + QAction *featureAction = new QAction( tr( "Feature %1" ).arg( featureTitle ), this ) ; + connect( featureAction, &QAction::triggered, this, [this, id]() {chooseOneCandidateFeature( id );} ); + connect( featureAction, &QAction::hovered, this, [this, id]() {this->highlightOneFeature( id );} ); mMenuChooseOne->addAction( featureAction ); } mMenuChooseOne->setEnabled( ids.count() != 0 ); } -void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::chooseOneCandidateFeature() +void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::chooseOneCandidateFeature( QgsFeatureId id ) { if ( !mVectorLayer ) return; - QAction *senderAction = qobject_cast( sender() ); - - if ( !senderAction ) - return; - - QVariant featureVariant = senderAction->data(); QgsFeatureIds ids; - if ( featureVariant.type() == QVariant::LongLong ) - ids.insert( featureVariant.toLongLong() ); - - if ( !ids.empty() ) - mVectorLayer->selectByIds( ids, mBehavior ); + ids << id; + mVectorLayer->selectByIds( ids, mBehavior ); } void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::chooseAllCandidateFeature() @@ -615,38 +619,17 @@ void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::chooseAllCandidateFeatu mVectorLayer->selectByIds( mAllFeatureIds, mBehavior ); } -void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::highlightFeatures() +void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::highlightAllFeatures() { removeHighlight(); if ( !mVectorLayer ) return; - QAction *senderAction = qobject_cast( sender() ); - if ( !senderAction ) - return; - - QgsFeatureIds ids; - if ( senderAction == mActionChooseAll ) - ids = mAllFeatureIds; - else - { - QVariant featureVariant = senderAction->data(); - if ( featureVariant.type() == QVariant::List ) - { - QVariantList list = featureVariant.toList(); - for ( const QVariant &var : list ) - ids.insert( var.toLongLong() ); - } - - if ( featureVariant.type() == QVariant::LongLong ) - ids.insert( featureVariant.toLongLong() ); - } - - if ( !ids.empty() ) + if ( !mAllFeatureIds.empty() ) { int count = 0; - for ( const QgsFeatureId &id : ids ) + for ( const QgsFeatureId &id : mAllFeatureIds ) { QgsFeature feat = mVectorLayer->getFeature( id ); QgsGeometry geom = feat.geometry(); @@ -663,6 +646,23 @@ void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::highlightFeatures() } } +void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::highlightOneFeature( QgsFeatureId id ) +{ + removeHighlight(); + + if ( !mVectorLayer ) + return; + + QgsFeature feat = mVectorLayer->getFeature( id ); + QgsGeometry geom = feat.geometry(); + if ( !geom.isEmpty() ) + { + QgsHighlight *hl = new QgsHighlight( mCanvas, geom, mVectorLayer ); + styleHighlight( hl ); + mHighlight.append( hl ); + } +} + void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::styleHighlight( QgsHighlight *highlight ) { QgsSettings settings; diff --git a/src/app/qgsmaptoolselectutils.h b/src/app/qgsmaptoolselectutils.h index a82eabc7ea9..5b1c14243b8 100644 --- a/src/app/qgsmaptoolselectutils.h +++ b/src/app/qgsmaptoolselectutils.h @@ -152,9 +152,8 @@ namespace QgsMapToolSelectUtils void populateMenu( QMenu *menu ); private slots: - void chooseOneCandidateFeature(); void chooseAllCandidateFeature(); - void highlightFeatures(); + void highlightAllFeatures(); void onLayerDestroyed(); void removeHighlight(); void onSearchFinished(); @@ -197,6 +196,9 @@ namespace QgsMapToolSelectUtils std::shared_ptr mJobData; static QgsFeatureIds search( std::shared_ptr data ); + + void chooseOneCandidateFeature( QgsFeatureId id ); + void highlightOneFeature( QgsFeatureId id ); }; } diff --git a/src/gui/qgsmaptool.h b/src/gui/qgsmaptool.h index 28b87520c93..c09e96d1bbf 100644 --- a/src/gui/qgsmaptool.h +++ b/src/gui/qgsmaptool.h @@ -224,7 +224,7 @@ class GUI_EXPORT QgsMapTool : public QObject * * A pointer to the map mouse \a event can be provided to allow particular behavior depending on the map tool. * - * This method can return true to inform the caller that the menu was effectivly populated. + * This method can return true to inform the caller that the menu was effectively populated. * * The default implementation does nothing and returns false. *