mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
switch to XY coordinate types when using label move tool
This commit is contained in:
parent
fd1b819243
commit
9f7353b91c
7
python/core/auto_additions/qgslabeling.py
Normal file
7
python/core/auto_additions/qgslabeling.py
Normal file
@ -0,0 +1,7 @@
|
||||
# The following has been generated automatically from src/core/labeling/qgslabeling.h
|
||||
# monkey patching scoped based enum
|
||||
QgsLabeling.CoordinateType.XY.__doc__ = "Coordinate defined by X and Y values"
|
||||
QgsLabeling.CoordinateType.Point.__doc__ = "Coordinate defined by a point"
|
||||
QgsLabeling.CoordinateType.__doc__ = 'Types of coordinate definitions\n\n.. versionadded:: 3.22\n\n' + '* ``XY``: ' + QgsLabeling.CoordinateType.XY.__doc__ + '\n' + '* ``Point``: ' + QgsLabeling.CoordinateType.Point.__doc__
|
||||
# --
|
||||
QgsLabeling.CoordinateType.baseClass = QgsLabeling
|
||||
@ -20,6 +20,9 @@ Contains constants and enums relating to labeling.
|
||||
%TypeHeaderCode
|
||||
#include "qgslabeling.h"
|
||||
%End
|
||||
public:
|
||||
static const QMetaObject staticMetaObject;
|
||||
|
||||
public:
|
||||
|
||||
enum LinePlacementFlag
|
||||
@ -40,6 +43,12 @@ Contains constants and enums relating to labeling.
|
||||
typedef QFlags<QgsLabeling::PolygonPlacementFlag> PolygonPlacementFlags;
|
||||
|
||||
|
||||
enum class CoordinateType
|
||||
{
|
||||
XY,
|
||||
Point
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
QFlags<QgsLabeling::LinePlacementFlag> operator|(QgsLabeling::LinePlacementFlag f1, QFlags<QgsLabeling::LinePlacementFlag> f2);
|
||||
|
||||
@ -218,6 +218,7 @@ Contains settings for how a map layer will be labeled.
|
||||
// (data defined only)
|
||||
PositionX,
|
||||
PositionY,
|
||||
PositionPoint,
|
||||
Hali,
|
||||
Vali,
|
||||
Rotation,
|
||||
@ -419,6 +420,24 @@ Set unit for rotation of labels.
|
||||
|
||||
int priority;
|
||||
|
||||
QgsLabeling::CoordinateType placementCoordinateType() const;
|
||||
%Docstring
|
||||
Coordinates type for data defined placement.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementCoordinateType`
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
void setPlacementCoordinateType( QgsLabeling::CoordinateType placementCoordinateType );
|
||||
%Docstring
|
||||
Set coordinates type for data defined placement.
|
||||
|
||||
.. seealso:: :py:func:`placementCoordinateType`
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
|
||||
bool scaleVisibility;
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
|
||||
class QgsAbstractVectorLayerLabeling
|
||||
class QgsAbstractVectorLayerLabeling : QObject
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
Abstract base class - its implementations define different approaches to the labeling of a vector layer.
|
||||
@ -112,6 +112,10 @@ Returns the default layer settings to use for the specified vector ``layer``.
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void labelingChanged();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QVariantMap &props ) const;
|
||||
|
||||
@ -145,11 +145,9 @@ Sets the background color for the text preview widget.
|
||||
:param color: background color
|
||||
%End
|
||||
|
||||
void enableDataDefinedAlignment( bool enable );
|
||||
void updateDataDefinedAlignment();
|
||||
%Docstring
|
||||
Controls whether data defined alignment buttons are enabled.
|
||||
|
||||
:param enable: set to ``True`` to enable alignment controls
|
||||
Update the enabled state of the data defined alignment buttons.
|
||||
%End
|
||||
|
||||
virtual QgsExpressionContext createExpressionContext() const;
|
||||
|
||||
@ -354,6 +354,14 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isCalloutMove
|
||||
&& vlayer->labeling()->settings().placementCoordinateType() != QgsLabeling::CoordinateType::XY )
|
||||
{
|
||||
QgsPalLayerSettings *settings = new QgsPalLayerSettings( mCurrentLabel.settings );
|
||||
settings->setPlacementCoordinateType( QgsLabeling::CoordinateType::XY );
|
||||
vlayer->labeling()->setSettings( settings );
|
||||
}
|
||||
|
||||
bool success = vlayer->changeAttributeValue( featureId, xCol, xNewPos );
|
||||
success = vlayer->changeAttributeValue( featureId, yCol, yNewPos ) && success;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include <QObject>
|
||||
#include <QFlags>
|
||||
|
||||
/**
|
||||
@ -30,6 +31,8 @@
|
||||
*/
|
||||
class CORE_EXPORT QgsLabeling
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -56,6 +59,18 @@ class CORE_EXPORT QgsLabeling
|
||||
};
|
||||
Q_DECLARE_FLAGS( PolygonPlacementFlags, PolygonPlacementFlag )
|
||||
|
||||
/**
|
||||
* Types of coordinate definitions
|
||||
*
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
enum class CoordinateType : int
|
||||
{
|
||||
XY, //!< Coordinate defined by X and Y values
|
||||
Point //!< Coordinate defined by a point
|
||||
};
|
||||
Q_ENUM( CoordinateType )
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsLabeling::LinePlacementFlags )
|
||||
|
||||
@ -244,6 +244,7 @@ void QgsPalLayerSettings::initPropertyDefinitions()
|
||||
{ QgsPalLayerSettings::PolygonLabelOutside, QgsPropertyDefinition( "PolygonLabelOutside", QgsPropertyDefinition::DataTypeString, QObject::tr( "Label outside polygons" ), QObject::tr( "string " ) + "[<b>yes</b> (allow placing outside)|<b>no</b> (never place outside)|<b>force</b> (always place outside)]", origin ) },
|
||||
{ QgsPalLayerSettings::PositionX, QgsPropertyDefinition( "PositionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) },
|
||||
{ QgsPalLayerSettings::PositionY, QgsPropertyDefinition( "PositionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) },
|
||||
{ QgsPalLayerSettings::PositionPoint, QgsPropertyDefinition( "PositionPoint", QObject::tr( "Position (point)" ), QgsPropertyDefinition::Point, origin ) },
|
||||
{ QgsPalLayerSettings::Hali, QgsPropertyDefinition( "Hali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Horizontal alignment" ), QObject::tr( "string " ) + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]", origin ) },
|
||||
{
|
||||
QgsPalLayerSettings::Vali, QgsPropertyDefinition( "Vali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Vertical alignment" ), QObject::tr( "string " ) + QStringLiteral( "[<b>Bottom</b>|<b>Base</b>|<br>"
|
||||
@ -340,6 +341,7 @@ QgsPalLayerSettings &QgsPalLayerSettings::operator=( const QgsPalLayerSettings &
|
||||
repeatDistance = s.repeatDistance;
|
||||
repeatDistanceUnit = s.repeatDistanceUnit;
|
||||
repeatDistanceMapUnitScale = s.repeatDistanceMapUnitScale;
|
||||
mPlacementCoordinateType = s.mPlacementCoordinateType;
|
||||
|
||||
// rendering
|
||||
scaleVisibility = s.scaleVisibility;
|
||||
@ -618,6 +620,16 @@ void QgsPalLayerSettings::setRotationUnit( QgsUnitTypes::AngleUnit angleUnit )
|
||||
mRotationUnit = angleUnit;
|
||||
}
|
||||
|
||||
QgsLabeling::CoordinateType QgsPalLayerSettings::placementCoordinateType() const
|
||||
{
|
||||
return mPlacementCoordinateType;
|
||||
}
|
||||
|
||||
void QgsPalLayerSettings::setPlacementCoordinateType( QgsLabeling::CoordinateType placementCoordinateType )
|
||||
{
|
||||
mPlacementCoordinateType = placementCoordinateType;
|
||||
}
|
||||
|
||||
QString updateDataDefinedString( const QString &value )
|
||||
{
|
||||
// TODO: update or remove this when project settings for labeling are migrated to better XML layout
|
||||
@ -841,6 +853,7 @@ void QgsPalLayerSettings::readFromLayerCustomProperties( QgsVectorLayer *layer )
|
||||
{
|
||||
repeatDistanceMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/repeatDistanceMapUnitScale" ) ).toString() );
|
||||
}
|
||||
mPlacementCoordinateType = layer->customEnumProperty( QStringLiteral( "labeling/placementCoordinateType" ), QgsLabeling::CoordinateType::XY );
|
||||
|
||||
// rendering
|
||||
double scalemn = layer->customProperty( QStringLiteral( "labeling/scaleMin" ), QVariant( 0 ) ).toDouble();
|
||||
@ -1091,6 +1104,8 @@ void QgsPalLayerSettings::readXml( const QDomElement &elem, const QgsReadWriteCo
|
||||
|
||||
layerType = qgsEnumKeyToValue( placementElem.attribute( QStringLiteral( "layerType" ) ), QgsWkbTypes::UnknownGeometry );
|
||||
|
||||
mPlacementCoordinateType = qgsEnumKeyToValue( placementElem.attribute( QStringLiteral( "coordinateType" ), qgsEnumValueToKey( QgsLabeling::CoordinateType::XY ) ), QgsLabeling::CoordinateType::XY );
|
||||
|
||||
// rendering
|
||||
QDomElement renderingElem = elem.firstChildElement( QStringLiteral( "rendering" ) );
|
||||
|
||||
@ -1248,6 +1263,8 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument &doc, const QgsReadWrite
|
||||
|
||||
placementElem.setAttribute( QStringLiteral( "layerType" ), metaEnum.valueToKey( layerType ) );
|
||||
|
||||
placementElem.setAttribute( QStringLiteral( "coordinateType" ), qgsEnumValueToKey( mPlacementCoordinateType ) );
|
||||
|
||||
// rendering
|
||||
QDomElement renderingElem = doc.createElement( QStringLiteral( "rendering" ) );
|
||||
renderingElem.setAttribute( QStringLiteral( "drawLabels" ), drawLabels );
|
||||
@ -2229,11 +2246,9 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
}
|
||||
|
||||
//data defined position / alignment / rotation?
|
||||
bool hasDataDefinedPosition = false;
|
||||
bool layerDefinedRotation = false;
|
||||
bool dataDefinedRotation = false;
|
||||
double xPos = 0.0, yPos = 0.0, angle = 0.0;
|
||||
bool ddXPos = false, ddYPos = false;
|
||||
double quadOffsetX = 0.0, quadOffsetY = 0.0;
|
||||
double offsetX = 0.0, offsetY = 0.0;
|
||||
QgsPointXY anchorPosition;
|
||||
@ -2378,119 +2393,158 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
}
|
||||
}
|
||||
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::PositionX ) )
|
||||
bool hasDataDefinedPosition = false;
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::PositionX, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
bool ddPosition = false;
|
||||
switch ( mPlacementCoordinateType )
|
||||
{
|
||||
if ( !exprVal.isNull() )
|
||||
xPos = exprVal.toDouble( &ddXPos );
|
||||
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::PositionY ) )
|
||||
case QgsLabeling::CoordinateType::XY:
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::PositionY, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::PositionX )
|
||||
&& mDataDefinedProperties.isActive( QgsPalLayerSettings::PositionY )
|
||||
&& !mDataDefinedProperties.value( QgsPalLayerSettings::PositionX, context.expressionContext() ).isNull()
|
||||
&& !mDataDefinedProperties.value( QgsPalLayerSettings::PositionY, context.expressionContext() ).isNull() )
|
||||
{
|
||||
//data defined position. But field values could be NULL -> positions will be generated by PAL
|
||||
if ( !exprVal.isNull() )
|
||||
yPos = exprVal.toDouble( &ddYPos );
|
||||
ddPosition = true;
|
||||
|
||||
bool ddXPos = false, ddYPos = false;
|
||||
xPos = mDataDefinedProperties.value( QgsPalLayerSettings::PositionX, context.expressionContext() ).toDouble( &ddXPos );
|
||||
yPos = mDataDefinedProperties.value( QgsPalLayerSettings::PositionY, context.expressionContext() ).toDouble( &ddYPos );
|
||||
if ( ddXPos && ddYPos )
|
||||
hasDataDefinedPosition = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QgsLabeling::CoordinateType::Point:
|
||||
{
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::PositionPoint )
|
||||
&& !mDataDefinedProperties.value( QgsPalLayerSettings::PositionPoint, context.expressionContext() ).isNull() )
|
||||
{
|
||||
ddPosition = true;
|
||||
|
||||
QVariant pointAsVariant = mDataDefinedProperties.value( QgsPalLayerSettings::PositionPoint, context.expressionContext() );
|
||||
if ( pointAsVariant.canConvert<QgsGeometry>() )
|
||||
{
|
||||
hasDataDefinedPosition = true;
|
||||
// layer rotation set, but don't rotate pinned labels unless data defined
|
||||
if ( layerDefinedRotation && !dataDefinedRotation )
|
||||
{
|
||||
angle = 0.0;
|
||||
}
|
||||
|
||||
//horizontal alignment
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Hali ) )
|
||||
QgsGeometry geometryPoint = pointAsVariant.value<QgsGeometry>();
|
||||
const QgsPoint *point = qgsgeometry_cast<QgsPoint *>( geometryPoint.constGet() );
|
||||
// QgsPoint point = geometryPoint.constGet()->vertexAt( vId );
|
||||
|
||||
xPos = point->x();
|
||||
yPos = point->y();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ddPosition )
|
||||
{
|
||||
//data defined position. But field values could be NULL -> positions will be generated by PAL
|
||||
if ( hasDataDefinedPosition )
|
||||
{
|
||||
// layer rotation set, but don't rotate pinned labels unless data defined
|
||||
if ( layerDefinedRotation && !dataDefinedRotation )
|
||||
{
|
||||
angle = 0.0;
|
||||
}
|
||||
|
||||
//horizontal alignment
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Hali ) )
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Hali, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
{
|
||||
QString haliString = exprVal.toString();
|
||||
if ( haliString.compare( QLatin1String( "Center" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Hali, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
xdiff -= labelX / 2.0;
|
||||
}
|
||||
else if ( haliString.compare( QLatin1String( "Right" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff -= labelX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//vertical alignment
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Vali ) )
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Vali, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
{
|
||||
QString valiString = exprVal.toString();
|
||||
if ( valiString.compare( QLatin1String( "Bottom" ), Qt::CaseInsensitive ) != 0 )
|
||||
{
|
||||
if ( valiString.compare( QLatin1String( "Top" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QString haliString = exprVal.toString();
|
||||
if ( haliString.compare( QLatin1String( "Center" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff -= labelX / 2.0;
|
||||
}
|
||||
else if ( haliString.compare( QLatin1String( "Right" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff -= labelX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//vertical alignment
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Vali ) )
|
||||
{
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Vali, context.expressionContext() );
|
||||
if ( !exprVal.isNull() )
|
||||
{
|
||||
QString valiString = exprVal.toString();
|
||||
if ( valiString.compare( QLatin1String( "Bottom" ), Qt::CaseInsensitive ) != 0 )
|
||||
{
|
||||
if ( valiString.compare( QLatin1String( "Top" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY;
|
||||
}
|
||||
else
|
||||
{
|
||||
double descentRatio = labelFontMetrics->descent() / labelFontMetrics->height();
|
||||
if ( valiString.compare( QLatin1String( "Base" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
}
|
||||
else //'Cap' or 'Half'
|
||||
{
|
||||
double capHeightRatio = ( labelFontMetrics->boundingRect( 'H' ).height() + 1 + labelFontMetrics->descent() ) / labelFontMetrics->height();
|
||||
ydiff -= labelY * capHeightRatio;
|
||||
if ( valiString.compare( QLatin1String( "Half" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff += labelY * ( capHeightRatio - descentRatio ) / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( dataDefinedRotation )
|
||||
{
|
||||
//adjust xdiff and ydiff because the hali/vali point needs to be the rotation center
|
||||
double xd = xdiff * std::cos( angle ) - ydiff * std::sin( angle );
|
||||
double yd = xdiff * std::sin( angle ) + ydiff * std::cos( angle );
|
||||
xdiff = xd;
|
||||
ydiff = yd;
|
||||
}
|
||||
|
||||
//project xPos and yPos from layer to map CRS, handle rotation
|
||||
QgsGeometry ddPoint( new QgsPoint( xPos, yPos ) );
|
||||
if ( QgsPalLabeling::geometryRequiresPreparation( ddPoint, context, ct ) )
|
||||
{
|
||||
ddPoint = QgsPalLabeling::prepareGeometry( ddPoint, context, ct );
|
||||
if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( ddPoint.constGet() ) )
|
||||
{
|
||||
xPos = point->x();
|
||||
yPos = point->y();
|
||||
anchorPosition = QgsPointXY( xPos, yPos );
|
||||
ydiff -= labelY;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QObject::tr( "Invalid data defined label position (%1, %2)" ).arg( xPos ).arg( yPos ), QObject::tr( "Labeling" ) );
|
||||
hasDataDefinedPosition = false;
|
||||
double descentRatio = labelFontMetrics->descent() / labelFontMetrics->height();
|
||||
if ( valiString.compare( QLatin1String( "Base" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
}
|
||||
else //'Cap' or 'Half'
|
||||
{
|
||||
double capHeightRatio = ( labelFontMetrics->boundingRect( 'H' ).height() + 1 + labelFontMetrics->descent() ) / labelFontMetrics->height();
|
||||
ydiff -= labelY * capHeightRatio;
|
||||
if ( valiString.compare( QLatin1String( "Half" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff += labelY * ( capHeightRatio - descentRatio ) / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorPosition = QgsPointXY( xPos, yPos );
|
||||
}
|
||||
|
||||
xPos += xdiff;
|
||||
yPos += ydiff;
|
||||
}
|
||||
}
|
||||
|
||||
if ( dataDefinedRotation )
|
||||
{
|
||||
//adjust xdiff and ydiff because the hali/vali point needs to be the rotation center
|
||||
double xd = xdiff * std::cos( angle ) - ydiff * std::sin( angle );
|
||||
double yd = xdiff * std::sin( angle ) + ydiff * std::cos( angle );
|
||||
xdiff = xd;
|
||||
ydiff = yd;
|
||||
}
|
||||
|
||||
//project xPos and yPos from layer to map CRS, handle rotation
|
||||
QgsGeometry ddPoint( new QgsPoint( xPos, yPos ) );
|
||||
if ( QgsPalLabeling::geometryRequiresPreparation( ddPoint, context, ct ) )
|
||||
{
|
||||
ddPoint = QgsPalLabeling::prepareGeometry( ddPoint, context, ct );
|
||||
if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( ddPoint.constGet() ) )
|
||||
{
|
||||
xPos = point->x();
|
||||
yPos = point->y();
|
||||
anchorPosition = QgsPointXY( xPos, yPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QObject::tr( "Invalid data defined label position (%1, %2)" ).arg( xPos ).arg( yPos ), QObject::tr( "Labeling" ) );
|
||||
hasDataDefinedPosition = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorPosition = QgsPointXY( xPos, yPos );
|
||||
}
|
||||
|
||||
xPos += xdiff;
|
||||
yPos += ydiff;
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorPosition = QgsPointXY( xPos, yPos );
|
||||
|
||||
// only rotate non-pinned OverPoint placements until other placements are supported in pal::Feature
|
||||
if ( dataDefinedRotation && placement != QgsPalLayerSettings::OverPoint )
|
||||
{
|
||||
angle = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +321,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
// (data defined only)
|
||||
PositionX = 9, //!< X-coordinate data defined label position
|
||||
PositionY = 10, //!< Y-coordinate data defined label position
|
||||
PositionPoint = 79, //!< Point-coordinate data defined label position
|
||||
Hali = 11, //!< Horizontal alignment for data defined label position (Left, Center, Right)
|
||||
Vali = 12, //!< Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
|
||||
Rotation = 14, //!< Label rotation (deprecated, for old project compatibility only)
|
||||
@ -667,6 +668,20 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
*/
|
||||
int priority = 5;
|
||||
|
||||
/**
|
||||
* Coordinates type for data defined placement.
|
||||
* \see setPlacementCoordinateType()
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
QgsLabeling::CoordinateType placementCoordinateType() const;
|
||||
|
||||
/**
|
||||
* Set coordinates type for data defined placement.
|
||||
* \see placementCoordinateType()
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
void setPlacementCoordinateType( QgsLabeling::CoordinateType placementCoordinateType );
|
||||
|
||||
//-- rendering
|
||||
|
||||
/**
|
||||
@ -1150,6 +1165,8 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
//! Unit for rotation of labels.
|
||||
QgsUnitTypes::AngleUnit mRotationUnit = QgsUnitTypes::AngleDegrees;
|
||||
|
||||
QgsLabeling::CoordinateType mPlacementCoordinateType = QgsLabeling::CoordinateType::XY;
|
||||
|
||||
static void initPropertyDefinitions();
|
||||
};
|
||||
|
||||
|
||||
@ -535,6 +535,8 @@ void QgsRuleBasedLabeling::setSettings( QgsPalLayerSettings *settings, const QSt
|
||||
if ( rule && rule->settings() )
|
||||
rule->setSettings( settings );
|
||||
}
|
||||
|
||||
emit labelingChanged();
|
||||
}
|
||||
|
||||
void QgsRuleBasedLabeling::toSld( QDomNode &parent, const QVariantMap &props ) const
|
||||
|
||||
@ -621,4 +621,6 @@ void QgsVectorLayerSimpleLabeling::setSettings( QgsPalLayerSettings *settings, c
|
||||
return;
|
||||
|
||||
mSettings.reset( settings );
|
||||
|
||||
emit labelingChanged();
|
||||
}
|
||||
|
||||
@ -38,8 +38,9 @@ class QgsStyleEntityVisitorInterface;
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsAbstractVectorLayerLabeling
|
||||
class CORE_EXPORT QgsAbstractVectorLayerLabeling : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#ifdef SIP_RUN
|
||||
SIP_CONVERT_TO_SUBCLASS_CODE
|
||||
@ -133,6 +134,10 @@ class CORE_EXPORT QgsAbstractVectorLayerLabeling
|
||||
*/
|
||||
static QgsPalLayerSettings defaultSettingsForLayer( const QgsVectorLayer *layer );
|
||||
|
||||
signals:
|
||||
|
||||
void labelingChanged();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
||||
@ -253,6 +253,9 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas,
|
||||
mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( QgsUnitTypes::AngleMilliradiansSI ), QgsUnitTypes::AngleMilliradiansSI );
|
||||
mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( QgsUnitTypes::AngleMilNATO ), QgsUnitTypes::AngleMilNATO );
|
||||
|
||||
mCoordTypeComboBox->addItem( tr( "X/Y" ), static_cast< int >( QgsLabeling::CoordinateType::XY ) );
|
||||
mCoordTypeComboBox->addItem( tr( "Point" ), static_cast< int >( QgsLabeling::CoordinateType::Point ) );
|
||||
|
||||
// connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
|
||||
connect( mBufferDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
|
||||
connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsLabelingGui::updateUi );
|
||||
@ -432,6 +435,10 @@ void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
|
||||
mFontMultiLineAlignComboBox->setCurrentIndex( 0 );
|
||||
}
|
||||
|
||||
mCoordTypeComboBox->setCurrentIndex( 0 );
|
||||
if ( mCoordTypeComboBox->findData( static_cast< int >( mSettings.placementCoordinateType() ) ) >= 0 )
|
||||
mCoordTypeComboBox->setCurrentIndex( mCoordTypeComboBox->findData( static_cast< int >( mSettings.placementCoordinateType() ) ) );
|
||||
|
||||
chkPreserveRotation->setChecked( mSettings.preserveRotation );
|
||||
|
||||
mCoordRotationUnitComboBox->setCurrentIndex( 0 );
|
||||
@ -482,7 +489,8 @@ void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
|
||||
// do this after other widgets are configured, so they can be enabled/disabled
|
||||
populateDataDefinedButtons();
|
||||
|
||||
enableDataDefinedAlignment( mCoordXDDBtn->isActive() && mCoordYDDBtn->isActive() );
|
||||
updateDataDefinedAlignment();
|
||||
|
||||
updateUi(); // should come after data defined button setup
|
||||
}
|
||||
|
||||
@ -624,6 +632,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
lyr.geometryGenerator = mGeometryGenerator->text();
|
||||
lyr.geometryGeneratorType = mGeometryGeneratorType->currentData().value<QgsWkbTypes::GeometryType>();
|
||||
lyr.geometryGeneratorEnabled = mGeometryGeneratorGroupBox->isChecked();
|
||||
lyr.setPlacementCoordinateType( static_cast< QgsLabeling::CoordinateType >( mCoordTypeComboBox->currentData().toInt() ) );
|
||||
|
||||
lyr.layerType = mLayer ? mLayer->geometryType() : mGeomType;
|
||||
|
||||
|
||||
@ -90,6 +90,8 @@ void QgsLabelingWidget::setLayer( QgsMapLayer *mapLayer )
|
||||
mOldLabelsEnabled = mLayer->labelsEnabled();
|
||||
|
||||
adaptToLayer();
|
||||
|
||||
connect( mLayer->labeling(), &QgsAbstractVectorLayerLabeling::labelingChanged, this, &QgsLabelingWidget::layerLabelingChanged );
|
||||
}
|
||||
|
||||
void QgsLabelingWidget::adaptToLayer()
|
||||
@ -300,3 +302,8 @@ void QgsLabelingWidget::showEngineConfigDialog()
|
||||
activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingWidget::layerLabelingChanged()
|
||||
{
|
||||
adaptToLayer();
|
||||
}
|
||||
|
||||
@ -77,6 +77,7 @@ class GUI_EXPORT QgsLabelingWidget : public QgsMapLayerConfigWidget, private Ui:
|
||||
private slots:
|
||||
void labelModeChanged( int index );
|
||||
void showEngineConfigDialog();
|
||||
void layerLabelingChanged();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -88,6 +88,8 @@ void QgsTextFormatWidget::initWidget()
|
||||
connect( mMaskBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mMaskBufferUnitWidget_changed );
|
||||
connect( mCoordXDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordXDDBtn_changed );
|
||||
connect( mCoordYDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordYDDBtn_changed );
|
||||
connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordPointDDBtn_changed );
|
||||
connect( mCoordTypeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mCoordTypeComboBox_currentIndexChanged );
|
||||
connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged );
|
||||
connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged );
|
||||
connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked );
|
||||
@ -358,6 +360,7 @@ void QgsTextFormatWidget::initWidget()
|
||||
<< mCentroidInsideCheckBox
|
||||
<< mChkNoObstacle
|
||||
<< mCoordRotationUnitComboBox
|
||||
<< mCoordTypeComboBox
|
||||
<< mDirectSymbChkBx
|
||||
<< mDirectSymbLeftLineEdit
|
||||
<< mDirectSymbRevChkBx
|
||||
@ -804,6 +807,7 @@ void QgsTextFormatWidget::populateDataDefinedButtons()
|
||||
// data defined-only
|
||||
registerDataDefinedButton( mCoordXDDBtn, QgsPalLayerSettings::PositionX );
|
||||
registerDataDefinedButton( mCoordYDDBtn, QgsPalLayerSettings::PositionY );
|
||||
registerDataDefinedButton( mCoordPointDDBtn, QgsPalLayerSettings::PositionPoint );
|
||||
registerDataDefinedButton( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Hali );
|
||||
registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali );
|
||||
registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::LabelRotation );
|
||||
@ -1572,28 +1576,34 @@ void QgsTextFormatWidget::mMaskBufferUnitWidget_changed()
|
||||
updateFont( mRefFont );
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::mCoordXDDBtn_changed( )
|
||||
void QgsTextFormatWidget::mCoordXDDBtn_changed()
|
||||
{
|
||||
if ( !mCoordXDDBtn->isActive() ) //no data defined alignment without data defined position
|
||||
{
|
||||
enableDataDefinedAlignment( false );
|
||||
}
|
||||
else if ( mCoordYDDBtn->isActive() )
|
||||
{
|
||||
enableDataDefinedAlignment( true );
|
||||
}
|
||||
updateDataDefinedAlignment();
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::mCoordYDDBtn_changed( )
|
||||
void QgsTextFormatWidget::mCoordYDDBtn_changed()
|
||||
{
|
||||
if ( !mCoordYDDBtn->isActive() ) //no data defined alignment without data defined position
|
||||
updateDataDefinedAlignment();
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::mCoordPointDDBtn_changed()
|
||||
{
|
||||
updateDataDefinedAlignment();
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::mCoordTypeComboBox_currentIndexChanged( int index )
|
||||
{
|
||||
switch ( static_cast<QgsLabeling::CoordinateType>( index ) )
|
||||
{
|
||||
enableDataDefinedAlignment( false );
|
||||
}
|
||||
else if ( mCoordXDDBtn->isActive() )
|
||||
{
|
||||
enableDataDefinedAlignment( true );
|
||||
case QgsLabeling::CoordinateType::XY:
|
||||
mCoordPositionStackWidget->setCurrentWidget( mCoordPositionXYStackWidgetPage );
|
||||
break;
|
||||
case QgsLabeling::CoordinateType::Point:
|
||||
mCoordPositionStackWidget->setCurrentWidget( mCoordPositionPointStackWidgetPage );
|
||||
break;
|
||||
}
|
||||
|
||||
updateDataDefinedAlignment();
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int )
|
||||
@ -2035,9 +2045,18 @@ void QgsTextFormatWidget::showBackgroundRadius( bool show )
|
||||
mShapeRadiusUnitsDDBtn->setVisible( show );
|
||||
}
|
||||
|
||||
void QgsTextFormatWidget::enableDataDefinedAlignment( bool enable )
|
||||
void QgsTextFormatWidget::updateDataDefinedAlignment()
|
||||
{
|
||||
mCoordAlignmentFrame->setEnabled( enable );
|
||||
// no data defined alignment without data defined position
|
||||
switch ( static_cast<QgsLabeling::CoordinateType>( mCoordTypeComboBox->currentData().toInt() ) )
|
||||
{
|
||||
case QgsLabeling::CoordinateType::XY:
|
||||
mCoordAlignmentFrame->setEnabled( mCoordXDDBtn->isActive() && mCoordYDDBtn->isActive() );
|
||||
break;
|
||||
case QgsLabeling::CoordinateType::Point:
|
||||
mCoordAlignmentFrame->setEnabled( mCoordPointDDBtn->isActive() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const
|
||||
|
||||
@ -154,10 +154,9 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
|
||||
void setPreviewBackground( const QColor &color );
|
||||
|
||||
/**
|
||||
* Controls whether data defined alignment buttons are enabled.
|
||||
* \param enable set to TRUE to enable alignment controls
|
||||
* Update the enabled state of the data defined alignment buttons.
|
||||
*/
|
||||
void enableDataDefinedAlignment( bool enable );
|
||||
void updateDataDefinedAlignment();
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
|
||||
@ -283,8 +282,10 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
|
||||
void mFontMaxPixelSpinBox_valueChanged( int px );
|
||||
void mBufferUnitWidget_changed();
|
||||
void mMaskBufferUnitWidget_changed();
|
||||
void mCoordXDDBtn_changed( );
|
||||
void mCoordYDDBtn_changed( );
|
||||
void mCoordXDDBtn_changed();
|
||||
void mCoordYDDBtn_changed();
|
||||
void mCoordPointDDBtn_changed();
|
||||
void mCoordTypeComboBox_currentIndexChanged( int index );
|
||||
void mShapeTypeCmbBx_currentIndexChanged( int index );
|
||||
void mShapeRotationCmbBx_currentIndexChanged( int index );
|
||||
void mShapeSVGParamsBtn_clicked();
|
||||
|
||||
@ -5519,44 +5519,102 @@ font-style: italic;</string>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_22">
|
||||
<item>
|
||||
<widget class="QLabel" name="mCoordXLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
<widget class="QStackedWidget" name="mCoordPositionStackWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mCoordPositionXYStackWidgetPage">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="mCoordXLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsPropertyOverrideButton" name="mCoordXDDBtn">
|
||||
<property name="text">
|
||||
<string>…</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mCoordYLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsPropertyOverrideButton" name="mCoordYDDBtn">
|
||||
<property name="text">
|
||||
<string>…</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="mCoordPositionPointStackWidgetPage">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="text">
|
||||
<string>Point</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsPropertyOverrideButton" name="mCoordPointDDBtn">
|
||||
<property name="text">
|
||||
<string>…</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_24">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>298</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsPropertyOverrideButton" name="mCoordXDDBtn">
|
||||
<property name="text">
|
||||
<string>…</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mCoordYLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsPropertyOverrideButton" name="mCoordYDDBtn">
|
||||
<property name="text">
|
||||
<string>…</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="mCoordTypeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_22">
|
||||
@ -6919,8 +6977,6 @@ font-style: italic;</string>
|
||||
<tabstop>mGeometryGeneratorGroupBox</tabstop>
|
||||
<tabstop>mGeometryGeneratorExpressionButton</tabstop>
|
||||
<tabstop>mGeometryGeneratorType</tabstop>
|
||||
<tabstop>mCoordXDDBtn</tabstop>
|
||||
<tabstop>mCoordYDDBtn</tabstop>
|
||||
<tabstop>mCoordAlignmentHDDBtn</tabstop>
|
||||
<tabstop>mCoordAlignmentVDDBtn</tabstop>
|
||||
<tabstop>mCoordRotationDDBtn</tabstop>
|
||||
|
||||
@ -85,6 +85,7 @@ class TestQgsLabelingEngine : public QObject
|
||||
void curvedOverrun();
|
||||
void parallelOverrun();
|
||||
void testDataDefinedLabelAllParts();
|
||||
void testDataDefinedPlacementPositionPoint();
|
||||
void testVerticalOrientation();
|
||||
void testVerticalOrientationLetterLineSpacing();
|
||||
void testRotationBasedOrientationPoint();
|
||||
@ -2859,7 +2860,50 @@ void TestQgsLabelingEngine::testDataDefinedLabelAllParts()
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_datadefined_label_all_parts" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testDataDefinedPlacementPositionPoint()
|
||||
{
|
||||
QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setLabelingEngineSettings( createLabelEngineSettings() );
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( vl->extent() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
// first render the map and labeling separately
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
|
||||
QPainter p( &img );
|
||||
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
|
||||
context.setPainter( &p );
|
||||
|
||||
QgsPalLayerSettings settings;
|
||||
settings.fieldName = QStringLiteral( "Class" );
|
||||
setDefaultLabelParams( settings );
|
||||
|
||||
settings.setPlacementCoordinateType( QgsLabeling::CoordinateType::Point );
|
||||
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::PositionPoint, QgsProperty::fromExpression( QStringLiteral( "translate($geometry, 1, 0.5)" ) ) );
|
||||
|
||||
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl->setLabelsEnabled( true );
|
||||
|
||||
QgsDefaultLabelingEngine engine;
|
||||
engine.setMapSettings( mapSettings );
|
||||
engine.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
|
||||
engine.run( context );
|
||||
|
||||
p.end();
|
||||
|
||||
QVERIFY( imageCheck( "label_datadefined_placement_position_point", img, 20 ) );
|
||||
|
||||
vl->setLabeling( nullptr );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testVerticalOrientation()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Loading…
x
Reference in New Issue
Block a user