void QgsActionMenu::triggerAction() { if ( !feature().isValid() ) return; QAction* action = qobject_cast<QAction*>( sender() ); if ( !action ) return; if ( !action->data().isValid() || !action->data().canConvert<ActionData>() ) return; ActionData data = action->data().value<ActionData>(); if ( data.actionType == Invalid ) return; if ( data.actionType == MapLayerAction ) { QgsMapLayerAction* mapLayerAction = data.actionData.value<QgsMapLayerAction*>(); mapLayerAction->triggerForFeature( data.mapLayer, &mFeature ); } else if ( data.actionType == AttributeAction ) { // define custom substitutions: layer id and clicked coords QgsExpressionContext context = mLayer->createExpressionContext(); QgsExpressionContextScope* actionScope = new QgsExpressionContextScope(); actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), mActionScope, true ) ); context << actionScope; QgsAction act = data.actionData.value<QgsAction>(); act.run( context ); } }
void QgsActionMenu::triggerAction() { if ( !feature() ) return; QAction* action = qobject_cast<QAction*>( sender() ); if ( !action ) return; if ( !action->data().isValid() || !action->data().canConvert<ActionData>() ) return; ActionData data = action->data().value<ActionData>(); if ( data.actionType == Invalid ) return; if ( data.actionType == MapLayerAction ) { QgsMapLayerAction* mapLayerAction = data.actionId.action; mapLayerAction->triggerForFeature( data.mapLayer, feature() ); } else if ( data.actionType == AttributeAction ) { mActions->doAction( data.actionId.id, *feature() ); } }
void QgsActionMenu::reloadActions() { clear(); delete mActions; mActions = new QgsAttributeAction( *mLayer->actions() ); for ( int idx = 0; idx < mActions->size(); ++idx ) { const QgsAction& qaction( mActions->at( idx ) ); QAction* action = new QAction( qaction.icon(), qaction.name(), this ); action->setData( QVariant::fromValue<ActionData>( ActionData( idx, mFeatureId, mLayer ) ) ); action->setIcon( qaction.icon() ); // Only enable items on supported platforms if ( !qaction.runable() ) { action->setEnabled( false ); action->setToolTip( tr( "Not supported on your platform" ) ); } else { action->setToolTip( qaction.action() ); } connect( action, SIGNAL( triggered() ), this, SLOT( triggerAction() ) ); addAction( action ); } QList<QgsMapLayerAction*> mapLayerActions = QgsMapLayerActionRegistry::instance()->mapLayerActions( mLayer, QgsMapLayerAction::SingleFeature ); if ( !mapLayerActions.isEmpty() ) { //add a separator between user defined and standard actions addSeparator(); for ( int i = 0; i < mapLayerActions.size(); ++i ) { QgsMapLayerAction* qaction = mapLayerActions.at( i ); QAction* action = new QAction( qaction->icon(), qaction->text(), this ); action->setData( QVariant::fromValue<ActionData>( ActionData( qaction, mFeatureId, mLayer ) ) ); addAction( action ); connect( action, SIGNAL( triggered() ), this, SLOT( triggerAction() ) ); } } emit reinit(); }
bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y ) { if ( !layer ) return false; QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y ); QgsFeatureList featList; // 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. try { // create the search rectangle double searchRadius = searchRadiusMU( mCanvas ); QgsRectangle r; r.setXMinimum( point.x() - searchRadius ); r.setXMaximum( point.x() + searchRadius ); r.setYMinimum( point.y() - searchRadius ); r.setYMaximum( point.y() + searchRadius ); r = toLayerCoordinates( layer, r ); QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) ); QgsFeature f; while ( fit.nextFeature( f ) ) featList << QgsFeature( f ); } catch ( QgsCsException & cse ) { Q_UNUSED( cse ); // catch exception for 'invalid' point and proceed with no features found QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) ); } if ( featList.size() == 0 ) return false; Q_FOREACH ( const QgsFeature& feat, featList ) { if ( layer->actions()->defaultAction() >= 0 ) { // define custom substitutions: layer id and clicked coords QMap<QString, QVariant> substitutionMap; substitutionMap.insert( "$layerid", layer->id() ); point = toLayerCoordinates( layer, point ); substitutionMap.insert( "$clickx", point.x() ); substitutionMap.insert( "$clicky", point.y() ); int actionIdx = layer->actions()->defaultAction(); layer->actions()->doAction( actionIdx, feat, &substitutionMap ); } else { QgsMapLayerAction* mapLayerAction = QgsMapLayerActionRegistry::instance()->defaultActionForLayer( layer ); if ( mapLayerAction ) { mapLayerAction->triggerForFeature( layer, &feat ); } } } return true; }
bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y ) { if ( !layer ) return false; QgsPointXY point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y ); QgsRectangle r; // create the search rectangle double searchRadius = searchRadiusMU( mCanvas ); r.setXMinimum( point.x() - searchRadius ); r.setXMaximum( point.x() + searchRadius ); r.setYMinimum( point.y() - searchRadius ); r.setYMaximum( point.y() + searchRadius ); // 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. try { r = toLayerCoordinates( layer, r ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); // catch exception for 'invalid' point and proceed with no features found QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) ); } QgsAction defaultAction = layer->actions()->defaultAction( QStringLiteral( "Canvas" ) ); QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) ); QgsFeature feat; while ( fit.nextFeature( feat ) ) { if ( defaultAction.isValid() ) { // define custom substitutions: layer id and clicked coords QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) << QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() ); QgsExpressionContextScope *actionScope = new QgsExpressionContextScope(); actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_x" ), point.x(), true ) ); actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "click_y" ), point.y(), true ) ); actionScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "action_scope" ), QStringLiteral( "Canvas" ), true ) ); context << actionScope; defaultAction.run( layer, feat, context ); } else { QgsMapLayerAction *mapLayerAction = QgsGui::mapLayerActionRegistry()->defaultActionForLayer( layer ); if ( mapLayerAction ) { mapLayerAction->triggerForFeature( layer, &feat ); } } } return true; }