mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-20 00:03:07 -04:00
[FEATURE] Add snapping results to default value calculation
... as @snapping_results variable
This commit is contained in:
parent
a8cceff0fc
commit
9581fe0a10
@ -77,7 +77,7 @@ class QgsCompoundCurve: QgsCurve
|
||||
|
||||
void addCurve( QgsCurve *c /Transfer/ );
|
||||
%Docstring
|
||||
Adds a curve to the geometr (takes ownership)
|
||||
Adds a curve to the geometry (takes ownership)
|
||||
%End
|
||||
|
||||
void removeCurve( int i );
|
||||
|
@ -809,6 +809,15 @@ class QgsExpressionContextUtils
|
||||
:rtype: QgsExpressionContextScope
|
||||
%End
|
||||
|
||||
static QgsExpressionContextScope *mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches ) /Factory/;
|
||||
%Docstring
|
||||
Sets the expression context variables which are available for expressions triggered by
|
||||
a map tool capture like add feature.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
:rtype: QgsExpressionContextScope
|
||||
%End
|
||||
|
||||
static QgsExpressionContextScope *updateSymbolScope( const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope = 0 );
|
||||
%Docstring
|
||||
Updates a symbol scope related to a QgsSymbol to an expression context.
|
||||
|
@ -42,6 +42,14 @@ Adds a whole curve (e.g. circularstring) to the captured geometry. Curve must be
|
||||
:rtype: QgsCompoundCurve
|
||||
%End
|
||||
|
||||
QList<QgsPointLocator::Match> snappingMatches() const;
|
||||
%Docstring
|
||||
Return a list of matches for each point on the captureCurve.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
:rtype: list of QgsPointLocator.Match
|
||||
%End
|
||||
|
||||
virtual void cadCanvasMoveEvent( QgsMapMouseEvent *e );
|
||||
|
||||
virtual void keyPressEvent( QKeyEvent *e );
|
||||
|
@ -71,6 +71,8 @@ QgsAttributeTypeDialog::QgsAttributeTypeDialog( QgsVectorLayer *vl, int fieldIdx
|
||||
isFieldEditableCheckBox->setEnabled( false );
|
||||
}
|
||||
|
||||
mExpressionWidget->registerExpressionContextGenerator( this );
|
||||
|
||||
connect( mExpressionWidget, &QgsExpressionLineEdit::expressionChanged, this, &QgsAttributeTypeDialog::defaultExpressionChanged );
|
||||
connect( mUniqueCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
|
||||
{
|
||||
@ -293,6 +295,18 @@ void QgsAttributeTypeDialog::setDefaultValueExpression( const QString &expressio
|
||||
mExpressionWidget->setExpression( expression );
|
||||
}
|
||||
|
||||
QgsExpressionContext QgsAttributeTypeDialog::createExpressionContext() const
|
||||
{
|
||||
QgsExpressionContext context;
|
||||
context
|
||||
<< QgsExpressionContextUtils::globalScope()
|
||||
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
|
||||
<< QgsExpressionContextUtils::layerScope( mLayer )
|
||||
<< QgsExpressionContextUtils::mapToolCaptureScope( QList<QgsPointLocator::Match>() );
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
QString QgsAttributeTypeDialog::constraintExpression() const
|
||||
{
|
||||
return constraintExpressionWidget->asExpression();
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
class QDialog;
|
||||
|
||||
class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttributeTypeDialog
|
||||
class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttributeTypeDialog, QgsExpressionContextGenerator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -163,6 +163,8 @@ class APP_EXPORT QgsAttributeTypeDialog: public QDialog, private Ui::QgsAttribut
|
||||
*/
|
||||
void setDefaultValueExpression( const QString &expression );
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
|
||||
private slots:
|
||||
|
||||
/**
|
||||
|
@ -161,7 +161,7 @@ bool QgsFeatureAction::editFeature( bool showModal )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, bool showModal )
|
||||
bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, bool showModal, QgsExpressionContextScope *scope SIP_TRANSFER )
|
||||
{
|
||||
if ( !mLayer || !mLayer->isEditable() )
|
||||
return false;
|
||||
@ -188,6 +188,9 @@ bool QgsFeatureAction::addFeature( const QgsAttributeMap &defaultAttributes, boo
|
||||
// create new feature template - this will initialize the attributes to valid values, handling default
|
||||
// values and field constraints
|
||||
QgsExpressionContext context = mLayer->createExpressionContext();
|
||||
if ( scope )
|
||||
context.appendScope( scope );
|
||||
|
||||
QgsFeature newFeature = QgsVectorLayerUtils::createFeature( mLayer, mFeature->geometry(), initialAttributeValues,
|
||||
&context );
|
||||
*mFeature = newFeature;
|
||||
|
@ -29,6 +29,7 @@ class QgsIdentifyResultsDialog;
|
||||
class QgsVectorLayer;
|
||||
class QgsHighlight;
|
||||
class QgsAttributeDialog;
|
||||
class QgsExpressionContextScope;
|
||||
|
||||
class APP_EXPORT QgsFeatureAction : public QAction
|
||||
{
|
||||
@ -51,7 +52,7 @@ class APP_EXPORT QgsFeatureAction : public QAction
|
||||
*
|
||||
* \returns true if feature was added if showModal is true. If showModal is false, returns true in every case
|
||||
*/
|
||||
bool addFeature( const QgsAttributeMap &defaultAttributes = QgsAttributeMap(), bool showModal = true );
|
||||
bool addFeature( const QgsAttributeMap &defaultAttributes = QgsAttributeMap(), bool showModal = true, QgsExpressionContextScope *scope = nullptr );
|
||||
|
||||
private slots:
|
||||
void onFeatureSaved( const QgsFeature &feature );
|
||||
|
@ -48,8 +48,9 @@ QgsMapToolAddFeature::~QgsMapToolAddFeature()
|
||||
|
||||
bool QgsMapToolAddFeature::addFeature( QgsVectorLayer *vlayer, QgsFeature *f, bool showModal )
|
||||
{
|
||||
QgsExpressionContextScope *scope = QgsExpressionContextUtils::mapToolCaptureScope( snappingMatches() );
|
||||
QgsFeatureAction *action = new QgsFeatureAction( tr( "add feature" ), *f, vlayer, QString(), -1, this );
|
||||
bool res = action->addFeature( QgsAttributeMap(), showModal );
|
||||
bool res = action->addFeature( QgsAttributeMap(), showModal, scope );
|
||||
if ( showModal )
|
||||
delete action;
|
||||
return res;
|
||||
@ -250,6 +251,7 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
bool hasCurvedSegments = captureCurve()->hasCurvedSegments();
|
||||
bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries;
|
||||
|
||||
QList<QgsPointLocator::Match> snappingMatchesList;
|
||||
QgsCurve *curveToAdd = nullptr;
|
||||
if ( hasCurvedSegments && providerSupportsCurvedSegments )
|
||||
{
|
||||
@ -258,13 +260,13 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
else
|
||||
{
|
||||
curveToAdd = captureCurve()->curveToLine();
|
||||
snappingMatchesList = snappingMatches();
|
||||
}
|
||||
|
||||
if ( mode() == CaptureLine )
|
||||
{
|
||||
QgsGeometry *g = new QgsGeometry( curveToAdd );
|
||||
f->setGeometry( *g );
|
||||
delete g;
|
||||
QgsGeometry g( curveToAdd );
|
||||
f->setGeometry( g );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,9 +280,8 @@ void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
poly = new QgsPolygonV2();
|
||||
}
|
||||
poly->setExteriorRing( curveToAdd );
|
||||
QgsGeometry *g = new QgsGeometry( poly );
|
||||
f->setGeometry( *g );
|
||||
delete g;
|
||||
QgsGeometry g( poly );
|
||||
f->setGeometry( g );
|
||||
|
||||
QgsGeometry featGeom = f->geometry();
|
||||
int avoidIntersectionsReturn = featGeom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() );
|
||||
|
@ -44,7 +44,6 @@ class APP_EXPORT QgsMapToolAddFeature : public QgsMapToolCapture
|
||||
void setCheckGeometryType( bool checkGeometryType );
|
||||
|
||||
private:
|
||||
QVariant snappingMatchesAsVariable() const;
|
||||
|
||||
/** Check if CaptureMode matches layer type. Default is true.
|
||||
* \since QGIS 2.12 */
|
||||
|
@ -673,6 +673,19 @@ void QgsExpression::initVariableHelp()
|
||||
sVariableHelpTexts.insert( QStringLiteral( "grid_number" ), QCoreApplication::translate( "variable_help", "Current grid annotation value." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "grid_axis" ), QCoreApplication::translate( "variable_help", "Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
|
||||
|
||||
// map tool capture variables
|
||||
sVariableHelpTexts.insert( QStringLiteral( "snapping_results" ), QCoreApplication::translate( "variable_help",
|
||||
"<p>An array with an item for each snapped point.</p>"
|
||||
"<p>Each item is a map with the following keys:</p>"
|
||||
"<dl>"
|
||||
"<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>"
|
||||
"<dt>layer</dt><dd>The layer on which the snapped feature is</dd>"
|
||||
"<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>"
|
||||
"<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>"
|
||||
"<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>"
|
||||
"</dl>" ) );
|
||||
|
||||
|
||||
//symbol variables
|
||||
sVariableHelpTexts.insert( QStringLiteral( "geometry_part_count" ), QCoreApplication::translate( "variable_help", "Number of parts in rendered feature's geometry." ) );
|
||||
sVariableHelpTexts.insert( QStringLiteral( "geometry_part_num" ), QCoreApplication::translate( "variable_help", "Current geometry part number for feature being rendered." ) );
|
||||
|
@ -74,7 +74,7 @@ class CORE_EXPORT QgsCompoundCurve: public QgsCurve
|
||||
*/
|
||||
const QgsCurve *curveAt( int i ) const;
|
||||
|
||||
/** Adds a curve to the geometr (takes ownership)
|
||||
/** Adds a curve to the geometry (takes ownership)
|
||||
*/
|
||||
void addCurve( QgsCurve *c SIP_TRANSFER );
|
||||
|
||||
|
@ -912,6 +912,30 @@ QgsExpressionContextScope *QgsExpressionContextUtils::mapSettingsScope( const Qg
|
||||
return scope;
|
||||
}
|
||||
|
||||
QgsExpressionContextScope *QgsExpressionContextUtils::mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches )
|
||||
{
|
||||
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Map Tool Capture" ) );
|
||||
|
||||
QVariantList matchList;
|
||||
|
||||
for ( const QgsPointLocator::Match &match : matches )
|
||||
{
|
||||
QVariantMap matchMap;
|
||||
|
||||
matchMap.insert( QStringLiteral( "valid" ), match.isValid() );
|
||||
matchMap.insert( QStringLiteral( "layer" ), QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( match.layer() ) ) );
|
||||
matchMap.insert( QStringLiteral( "feature_id" ), match.featureId() );
|
||||
matchMap.insert( QStringLiteral( "vertex_index" ), match.vertexIndex() );
|
||||
matchMap.insert( QStringLiteral( "distance" ), match.distance() );
|
||||
|
||||
matchList.append( matchMap );
|
||||
}
|
||||
|
||||
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "snapping_results" ), matchList ) );
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
QgsExpressionContextScope *QgsExpressionContextUtils::updateSymbolScope( const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope )
|
||||
{
|
||||
if ( !symbolScope )
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsexpressionfunction.h"
|
||||
#include "qgspointlocator.h"
|
||||
|
||||
class QgsExpression;
|
||||
class QgsExpressionNodeFunction;
|
||||
@ -743,6 +744,14 @@ class CORE_EXPORT QgsExpressionContextUtils
|
||||
*/
|
||||
static QgsExpressionContextScope *mapSettingsScope( const QgsMapSettings &mapSettings ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Sets the expression context variables which are available for expressions triggered by
|
||||
* a map tool capture like add feature.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
static QgsExpressionContextScope *mapToolCaptureScope( const QList<QgsPointLocator::Match> &matches ) SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Updates a symbol scope related to a QgsSymbol to an expression context.
|
||||
* \param symbol symbol to extract properties from
|
||||
|
@ -222,6 +222,7 @@ bool QgsMapToolCapture::tracingAddVertex( const QgsPointXY &point )
|
||||
|
||||
mRubberBand->addPoint( point );
|
||||
mCaptureCurve.addVertex( layerPoint );
|
||||
mSnappingMatches.append( QgsPointLocator::Match() );
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -251,6 +252,7 @@ bool QgsMapToolCapture::tracingAddVertex( const QgsPointXY &point )
|
||||
continue; // avoid duplicate vertices if there are any
|
||||
mRubberBand->addPoint( points[i], i == points.count() - 1 );
|
||||
mCaptureCurve.addVertex( layerPoints[i - 1] );
|
||||
mSnappingMatches.append( QgsPointLocator::Match() );
|
||||
}
|
||||
|
||||
tracer->reportError( QgsTracer::ErrNone, true ); // clear messagebar if there was any error
|
||||
@ -433,6 +435,7 @@ int QgsMapToolCapture::addVertex( const QgsPointXY &point, const QgsPointLocator
|
||||
// ordinary digitizing
|
||||
mRubberBand->addPoint( point );
|
||||
mCaptureCurve.addVertex( layerPoint );
|
||||
mSnappingMatches.append( match );
|
||||
}
|
||||
|
||||
if ( mCaptureMode == CaptureLine )
|
||||
@ -493,10 +496,17 @@ int QgsMapToolCapture::addCurve( QgsCurve *c )
|
||||
c->transform( ct, QgsCoordinateTransform::ReverseTransform );
|
||||
}
|
||||
mCaptureCurve.addCurve( c );
|
||||
for ( int i = 0; i < c->length(); ++i )
|
||||
mSnappingMatches.append( QgsPointLocator::Match() );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<QgsPointLocator::Match> QgsMapToolCapture::snappingMatches() const
|
||||
{
|
||||
return mSnappingMatches;
|
||||
}
|
||||
|
||||
|
||||
void QgsMapToolCapture::undo()
|
||||
{
|
||||
@ -531,6 +541,7 @@ void QgsMapToolCapture::undo()
|
||||
vertexToRemove.ring = 0;
|
||||
vertexToRemove.vertex = size() - 1;
|
||||
mCaptureCurve.deleteVertex( vertexToRemove );
|
||||
mSnappingMatches.removeAt( vertexToRemove.vertex );
|
||||
|
||||
validateGeometry();
|
||||
}
|
||||
@ -599,6 +610,7 @@ void QgsMapToolCapture::stopCapturing()
|
||||
|
||||
mCapturing = false;
|
||||
mCaptureCurve.clear();
|
||||
mSnappingMatches.clear();
|
||||
if ( currentVectorLayer() )
|
||||
currentVectorLayer()->triggerRepaint();
|
||||
}
|
||||
@ -717,6 +729,9 @@ void QgsMapToolCapture::setPoints( const QList<QgsPointXY> &pointList )
|
||||
QgsLineString *line = new QgsLineString( pointList );
|
||||
mCaptureCurve.clear();
|
||||
mCaptureCurve.addCurve( line );
|
||||
mSnappingMatches.clear();
|
||||
for ( int i = 0; i < line->length(); ++i )
|
||||
mSnappingMatches.append( QgsPointLocator::Match() );
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -56,6 +56,13 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
|
||||
*/
|
||||
const QgsCompoundCurve *captureCurve() const { return &mCaptureCurve; }
|
||||
|
||||
/**
|
||||
* Return a list of matches for each point on the captureCurve.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
QList<QgsPointLocator::Match> snappingMatches() const;
|
||||
|
||||
virtual void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;
|
||||
|
||||
/**
|
||||
@ -193,6 +200,8 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
|
||||
//! List to store the points of digitized lines and polygons (in layer coordinates)
|
||||
QgsCompoundCurve mCaptureCurve;
|
||||
|
||||
QList<QgsPointLocator::Match> mSnappingMatches;
|
||||
|
||||
void validateGeometry();
|
||||
QStringList mValidationWarnings;
|
||||
QgsGeometryValidator *mValidator = nullptr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user